contrib.nodejsscan.archive_path_overwrite.zip_path_overwrite2

Author
99
Download Count*
License
Insecure ZIP archive extraction can result in arbitrary path over write and can result in code injection.
Run Locally
Run in CI
Defintion
rules:
- id: zip_path_overwrite2
patterns:
- pattern-either:
- pattern-inside: |
$X = require('unzip');
...
- pattern-inside: |
$X = require('unzipper');
...
- pattern-inside: |
$UNZIP.Parse(...).on('entry', function $FUNC($ENTRY) {
...
}, ...);
- pattern-not: |
if ($FILENAME.indexOf('..'));
- pattern-not: >
$FS.createWriteStream($PATH.join(..., $PATH.basename($FILENAME, ...)));
- pattern-not: |
$FS.writeFile($PATH.join(..., $PATH.basename($FILENAME, ...)));
- pattern-not: |
$FS.writeFileSync($PATH.join(..., $PATH.basename($FILENAME, ...)));
- pattern-either:
- pattern: |
$FS.createWriteStream($FIL, ...);
- pattern: |
$FS.writeFile($FIL, ...);
- pattern: |
$FS.writeFileSync($FIL, ...);
message: Insecure ZIP archive extraction can result in arbitrary path over write
and can result in code injection.
languages:
- javascript
severity: ERROR
metadata:
owasp: A05:2017 - Broken Access Control
cwe: "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path
Traversal')"
category: security
technology:
- node.js
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
Examples
archive_path_overwrite.js
//Ref: https://snyk.io/research/zip-slip-vulnerability
const fs = require('fs');
const unzip = require('unzip');
fs.createReadStream('archive.zip')
.pipe(unzip.Parse())
.on('entry', entry => {
const fileName = entry.path;
// Arbitrary file overwrite
// ruleid:zip_path_overwrite
entry.pipe(fs.createWriteStream(fileName));
});
fs.createReadStream('archive.zip')
.pipe(unzip.Parse())
.on('entry', entry => {
const fileName = entry.path;
// Arbitrary file overwrite
// ruleid:zip_path_overwrite
entry.pipe(fs.writeFileSync(fileName));
});
fs.readFile('path/to/archive.zip', function (err, zipContents) {
unzip.Parse(zipContents).on('entry', function (entry) {
var fileName = 'output/path/' + entry.path;
// Arbitrary file overwrite
// ruleid:zip_path_overwrite2
fs.writeFileSync(fileName, entry.contents);
});
});
//admzip
const fs = require('fs');
var AdmZip = require('adm-zip');
var zip = new AdmZip("archive.zip");
var zipEntries = zip.getEntries();
// ruleid:admzip_path_overwrite
zipEntries.forEach(function (zipEntry) {
fs.createWriteStream(zipEntry.entryName);
});
// ruleid:admzip_path_overwrite
zip.getEntries().forEach(function (zipEntry) {
fs.writeFileSync(zipEntry.entryName);
});
// tar-stream overwrite
const tar = require('tar-stream');
const extract = tar.extract();
extract.on('entry', (header, stream, next) => {
// ruleid:tar_path_overwrite
const out = fs.createWriteStream(header.name);
stream.pipe(out);
stream.on('end', () => {
next();
})
stream.resume();
})
tar.extract().on('entry', (header, stream, next) => {
// ruleid:tar_path_overwrite
const out = fs.writeFileSync(header.name);
stream.pipe(out);
stream.on('end', () => {
next();
})
stream.resume();
})
///unzipper lib
fs.createReadStream('./bad.tar').pipe(extract);
const fs = require('fs');
const unzipper = require('unzipper');
fs.createReadStream('path/to/archive.zip')
.pipe(unzipper.Parse())
.on('entry', function (entry) {
var fileName = entry.path;
// ruleid:zip_path_overwrite
entry.pipe(fs.createWriteStream(fileName));
});
Short Link: https://sg.run/x1J0