mirror of
https://github.com/github/codeql.git
synced 2026-01-29 06:12:58 +01:00
Merge branch 'main' into promote-xxe
This commit is contained in:
56
python/ql/src/experimental/Security/CWE-022/ZipSlip.qhelp
Normal file
56
python/ql/src/experimental/Security/CWE-022/ZipSlip.qhelp
Normal file
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Extracting files from a malicious zip archive without validating that the destination file path
|
||||
is within the destination directory can cause files outside the destination directory to be
|
||||
overwritten, due to the possible presence of directory traversal elements (<code>..</code>) in
|
||||
archive paths.</p>
|
||||
|
||||
<p>Zip archives 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 (<code>..</code>). If these
|
||||
file paths are used to determine an output file to write the contents of the archive item to, then
|
||||
the file may be written to an unexpected location. This can result in sensitive information being
|
||||
revealed or deleted, or an attacker being able to influence behavior by modifying unexpected
|
||||
files.</p>
|
||||
|
||||
<p>For example, if a Zip archive contains a file entry <code>..\sneaky-file</code>, and the Zip archive
|
||||
is extracted to the directory <code>c:\output</code>, then naively combining the paths would result
|
||||
in an output file path of <code>c:\output\..\sneaky-file</code>, which would cause the file to be
|
||||
written to <code>c:\sneaky-file</code>.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Ensure that output paths constructed from Zip archive entries are validated
|
||||
to prevent writing files to unexpected locations.</p>
|
||||
|
||||
<p>The recommended way of writing an output file from a Zip archive entry is to call <code>extract()</code> or <code>extractall()</code>.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In this example an archive is extracted without validating file paths.
|
||||
</p>
|
||||
|
||||
<sample src="zipslip_bad.py" />
|
||||
|
||||
<p>To fix this vulnerability, we need to call the function <code>extractall()</code>.
|
||||
</p>
|
||||
|
||||
<sample src="zipslip_good.py" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
<li>
|
||||
Snyk:
|
||||
<a href="https://snyk.io/research/zip-slip-vulnerability">Zip Slip Vulnerability</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
22
python/ql/src/experimental/Security/CWE-022/ZipSlip.ql
Normal file
22
python/ql/src/experimental/Security/CWE-022/ZipSlip.ql
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Arbitrary file write during archive extraction ("Zip Slip")
|
||||
* @description Extracting files from a malicious archive without validating that the
|
||||
* destination file path is within the destination directory can cause files outside
|
||||
* the destination directory to be overwritten.
|
||||
* @kind path-problem
|
||||
* @id py/zipslip
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-022
|
||||
*/
|
||||
|
||||
import python
|
||||
import experimental.semmle.python.security.ZipSlip
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from ZipSlipConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Extraction of zipfile from $@", source.getNode(),
|
||||
"a potentially untrusted source"
|
||||
16
python/ql/src/experimental/Security/CWE-022/zipslip_bad.py
Normal file
16
python/ql/src/experimental/Security/CWE-022/zipslip_bad.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import zipfile
|
||||
import shutil
|
||||
|
||||
def unzip(filename):
|
||||
with tarfile.open(filename) as zipf:
|
||||
#BAD : This could write any file on the filesystem.
|
||||
for entry in zipf:
|
||||
shutil.copyfile(entry, "/tmp/unpack/")
|
||||
|
||||
def unzip4(filename):
|
||||
zf = zipfile.ZipFile(filename)
|
||||
filelist = zf.namelist()
|
||||
for x in filelist:
|
||||
with zf.open(x) as srcf:
|
||||
shutil.copyfileobj(srcf, dstfile)
|
||||
|
||||
10
python/ql/src/experimental/Security/CWE-022/zipslip_good.py
Normal file
10
python/ql/src/experimental/Security/CWE-022/zipslip_good.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import zipfile
|
||||
|
||||
def unzip(filename, dir):
|
||||
zf = zipfile.ZipFile(filename)
|
||||
zf.extractall(dir)
|
||||
|
||||
|
||||
def unzip1(filename, dir):
|
||||
zf = zipfile.ZipFile(filename)
|
||||
zf.extract(dir)
|
||||
Reference in New Issue
Block a user