Repository navigation
Python: Unsafe unpacking using shutil.unpack_archive() query and tests - #11570
Conversation
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
yoff
left a comment
There was a problem hiding this comment.
It looks like you did a lot of work finding relevant calls to model. It would be nice to document that a bit, both as comments in the code and as tests, so we can see what the code is supposed to model and that it works (and keeps working in the future :-)).
For testing, we now have inline tests for dataflow queries. To use it, you have to put your data flow configuration into a qll file. Then you can import it similarly to this example (just copy that file and change the second import) and you can then annotate your test files like in this example (with # $result=BAD and # $MISSING:result=BAD).
It is not required that you do this, but it might be easier for you and it would be easier for me than it is to read the expected files.
Sync with the upstream
This is what I did for now:
I don't really understand the tag |
Yes, definitely Co-authored-by: yoff <lerchedahl@gmail.com>
The documentation is the comment at the top of this file, specifically this part. It is telling you that from your annotations you expected results on line 12 and line 55 and both of those are missing. In this case, it is because you did not import any data flow configuration into the test. If you put the class |
|
Cool, I will take a look. We normally use the re-request review button to signal that we are ready for more reviewing, then it pops up in my list of PRs needing review :-) |
yoff
left a comment
There was a problem hiding this comment.
Thanks for all the changes. I think that between the comments referencing the relevant APIs and the example code in the test cases, it is now clear what flow the various predicates are meant to model.
|
QHelp previews: python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.qhelpArbitrary file write during a tarball extraction from a user controlled sourceExtracting files from a malicious tarball without validating that the destination file path is within the destination directory using Tarball contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element ( For example, if a tarball contains a file entry RecommendationEnsure that output paths constructed from tarball entries are validated to prevent writing files to unexpected locations. Consider using a safer module, such as: ExampleIn this example an archive is extracted without validating file paths. import requests
import shutil
url = "https://www.someremote.location/tarball.tar.gz"
response = requests.get(url, stream=True)
tarpath = "/tmp/tmp456/tarball.tar.gz"
with open(tarpath, "wb") as f:
f.write(response.raw.read())
untarredpath = "/tmp/tmp123"
shutil.unpack_archive(tarpath, untarredpath)To fix this vulnerability, we need to call the function import requests
import tarfile
url = "https://www.someremote.location/tarball.tar.gz"
response = requests.get(url, stream=True)
tarpath = "/tmp/tmp456/tarball.tar.gz"
with open(tarpath, "wb") as f:
f.write(response.raw.read())
untarredpath = "/tmp/tmp123"
with tarfile.open(tarpath) as tar:
for member in tar.getmembers():
if member.name.startswith("/") or ".." in member.name:
raise Exception("Path traversal identified in tarball")
tar.extract(untarredpath, member)References
|
Co-authored-by: yoff <lerchedahl@gmail.com>
|
It seems the tests do not pass. You can see the failures here and here. This happens because you have shared the test directory with the tar-file query. The first failure comes from the inline dataflow test picking up For any sink that is not an alert, you have to make one of two annotations:
This makes it clear how the test file is intended to be read, i.e. which parts are examples of vulnerable code and which parts are not. These annotations are not yet present in The second failure comes from the tar slip query now picking up The easiest here may be to separate the test into two directories, i.e. to split |
|
Thanks @yoff I removed the annotations since the sinks should be reached and within the same commit I re-organized the test folder 📂 into two seperate for each query :Tarslip and UnsafeUnpack. |
|
Ah, I think you only had to split out the files. For sinks that are reached, we do want the annotation of When the tests pass with an empty expected file, then we know that all the annotations are in agreement with what dataflow finds :-) |
Dear CodeQL team,
Please, find enclosed the CodeQL query and the associated tests for an unsafe unpacking using
shutil.unpack_archive()of a malicious tarball retrieved from a remote location.Regards