mirror of
https://github.com/github/codeql.git
synced 2025-12-18 18:10:39 +01:00
432 lines
11 KiB
JavaScript
432 lines
11 KiB
JavaScript
var fs = require('fs'),
|
|
express = require('express'),
|
|
url = require('url'),
|
|
sanitize = require('sanitize-filename'),
|
|
pathModule = require('path')
|
|
;
|
|
|
|
let app = express();
|
|
|
|
app.get('/basic', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
fs.readFileSync('./' + path); // $ Alert
|
|
fs.readFileSync(path + '/index.html'); // $ Alert
|
|
fs.readFileSync(pathModule.join(path, 'index.html')); // $ Alert
|
|
fs.readFileSync(pathModule.join('/home/user/www', path)); // $ Alert
|
|
});
|
|
|
|
app.get('/normalize', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
fs.readFileSync('./' + path); // $ Alert
|
|
fs.readFileSync(path + '/index.html'); // $ Alert
|
|
fs.readFileSync(pathModule.join(path, 'index.html')); // $ Alert
|
|
fs.readFileSync(pathModule.join('/home/user/www', path)); // $ Alert
|
|
});
|
|
|
|
app.get('/normalize-notAbsolute', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (pathModule.isAbsolute(path))
|
|
return;
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
if (!path.startsWith("."))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert - wrong polarity
|
|
|
|
if (!path.startsWith(".."))
|
|
fs.readFileSync(path);
|
|
|
|
if (!path.startsWith("../"))
|
|
fs.readFileSync(path);
|
|
|
|
if (!path.startsWith(".." + pathModule.sep))
|
|
fs.readFileSync(path);
|
|
});
|
|
|
|
app.get('/normalize-noInitialDotDot', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (path.startsWith(".."))
|
|
return;
|
|
|
|
fs.readFileSync(path); // $ Alert - could be absolute
|
|
|
|
fs.readFileSync("./" + path); // OK - coerced to relative
|
|
|
|
fs.readFileSync(path + "/index.html"); // $ Alert - not coerced
|
|
|
|
if (!pathModule.isAbsolute(path))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
});
|
|
|
|
app.get('/prepend-normalize', (req, res) => {
|
|
// Coerce to relative prior to normalization
|
|
let path = pathModule.normalize('./' + req.query.path); // $ Source
|
|
|
|
if (!path.startsWith(".."))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
});
|
|
|
|
app.get('/absolute', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
|
|
if (!pathModule.isAbsolute(path))
|
|
return;
|
|
|
|
res.write(fs.readFileSync(path)); // $ Alert
|
|
|
|
if (path.startsWith('/home/user/www'))
|
|
res.write(fs.readFileSync(path)); // $ Alert - can still contain '../'
|
|
});
|
|
|
|
app.get('/normalized-absolute', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (!pathModule.isAbsolute(path))
|
|
return;
|
|
|
|
res.write(fs.readFileSync(path)); // $ Alert
|
|
|
|
if (path.startsWith('/home/user/www'))
|
|
res.write(fs.readFileSync(path));
|
|
});
|
|
|
|
app.get('/combined-check', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path);
|
|
|
|
// Combined absoluteness and folder check in one startsWith call
|
|
if (path.startsWith("/home/user/www"))
|
|
fs.readFileSync(path);
|
|
|
|
if (path[0] !== "/" && path[0] !== ".")
|
|
fs.readFileSync(path);
|
|
});
|
|
|
|
app.get('/realpath', (req, res) => {
|
|
let path = fs.realpathSync(req.query.path); // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
fs.readFileSync(pathModule.join(path, 'index.html')); // $ Alert
|
|
|
|
if (path.startsWith("/home/user/www"))
|
|
fs.readFileSync(path); // OK - both absolute and normalized before check
|
|
|
|
fs.readFileSync(pathModule.join('.', path)); // OK - normalized and coerced to relative
|
|
fs.readFileSync(pathModule.join('/home/user/www', path));
|
|
});
|
|
|
|
app.get('/coerce-relative', (req, res) => {
|
|
let path = pathModule.join('.', req.query.path); // $ Source
|
|
|
|
if (!path.startsWith('..'))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
});
|
|
|
|
app.get('/coerce-absolute', (req, res) => {
|
|
let path = pathModule.join('/home/user/www', req.query.path); // $ Source
|
|
|
|
if (path.startsWith('/home/user/www'))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
});
|
|
|
|
app.get('/concat-after-normalization', (req, res) => {
|
|
let path = 'foo/' + pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (!path.startsWith('..'))
|
|
fs.readFileSync(path); // $ Alert - prefixing foo/ invalidates check
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
if (!path.includes('..'))
|
|
fs.readFileSync(path);
|
|
});
|
|
|
|
app.get('/noDotDot', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (path.includes('..'))
|
|
return;
|
|
|
|
fs.readFileSync(path); // $ Alert - can still be absolute
|
|
|
|
if (!pathModule.isAbsolute(path))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
});
|
|
|
|
app.get('/join-regression', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
|
|
// Regression test for a specific corner case:
|
|
// Some guard nodes sanitize both branches, but for a different set of flow labels.
|
|
// Verify that this does not break anything.
|
|
if (pathModule.isAbsolute(path)) {path;} else {path;}
|
|
if (path.startsWith('/')) {path;} else {path;}
|
|
if (path.startsWith('/x')) {path;} else {path;}
|
|
if (path.startsWith('.')) {path;} else {path;}
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
if (pathModule.isAbsolute(path))
|
|
fs.readFileSync(path); // $ Alert
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
if (path.includes('..'))
|
|
fs.readFileSync(path); // $ Alert
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
if (!path.includes('..') && !pathModule.isAbsolute(path))
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
let normalizedPath = pathModule.normalize(path);
|
|
if (normalizedPath.startsWith('/home/user/www'))
|
|
fs.readFileSync(normalizedPath);
|
|
else
|
|
fs.readFileSync(normalizedPath); // $ Alert
|
|
|
|
if (normalizedPath.startsWith('/home/user/www') || normalizedPath.startsWith('/home/user/public'))
|
|
fs.readFileSync(normalizedPath); // $ SPURIOUS: Alert
|
|
else
|
|
fs.readFileSync(normalizedPath); // $ Alert
|
|
});
|
|
|
|
app.get('/decode-after-normalization', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path); // $ Source
|
|
|
|
if (!pathModule.isAbsolute(path) && !path.startsWith('..'))
|
|
fs.readFileSync(path);
|
|
|
|
path = decodeURIComponent(path);
|
|
|
|
if (!pathModule.isAbsolute(path) && !path.startsWith('..'))
|
|
fs.readFileSync(path); // $ Alert - not normalized
|
|
});
|
|
|
|
app.get('/replace', (req, res) => {
|
|
let path = pathModule.normalize(req.query.path).replace(/%20/g, ' '); // $ Source
|
|
if (!pathModule.isAbsolute(path)) {
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
path = path.replace(/\.\./g, '');
|
|
fs.readFileSync(path);
|
|
}
|
|
});
|
|
|
|
app.get('/resolve-path', (req, res) => {
|
|
let path = pathModule.resolve(req.query.path); // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
var self = something();
|
|
|
|
if (path.substring(0, self.dir.length) === self.dir)
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert - wrong polarity
|
|
|
|
if (path.slice(0, self.dir.length) === self.dir)
|
|
fs.readFileSync(path);
|
|
else
|
|
fs.readFileSync(path); // $ Alert - wrong polarity
|
|
});
|
|
|
|
app.get('/relative-startswith', (req, res) => {
|
|
let path = pathModule.resolve(req.query.path); // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
var self = something();
|
|
|
|
var relative = pathModule.relative(self.webroot, path);
|
|
if(relative.startsWith(".." + pathModule.sep) || relative == "..") {
|
|
fs.readFileSync(path); // $ Alert
|
|
} else {
|
|
fs.readFileSync(path);
|
|
}
|
|
|
|
let newpath = pathModule.normalize(path);
|
|
var relativePath = pathModule.relative(pathModule.normalize(workspaceDir), newpath);
|
|
if (relativePath.indexOf('..' + pathModule.sep) === 0) {
|
|
fs.readFileSync(newpath); // $ Alert
|
|
} else {
|
|
fs.readFileSync(newpath);
|
|
}
|
|
|
|
let newpath = pathModule.normalize(path);
|
|
var relativePath = pathModule.relative(pathModule.normalize(workspaceDir), newpath);
|
|
if (relativePath.indexOf('../') === 0) {
|
|
fs.readFileSync(newpath); // $ Alert
|
|
} else {
|
|
fs.readFileSync(newpath);
|
|
}
|
|
|
|
let newpath = pathModule.normalize(path);
|
|
var relativePath = pathModule.relative(pathModule.normalize(workspaceDir), newpath);
|
|
if (pathModule.normalize(relativePath).indexOf('../') === 0) {
|
|
fs.readFileSync(newpath); // $ Alert
|
|
} else {
|
|
fs.readFileSync(newpath);
|
|
}
|
|
|
|
let newpath = pathModule.normalize(path);
|
|
var relativePath = pathModule.relative(pathModule.normalize(workspaceDir), newpath);
|
|
if (pathModule.normalize(relativePath).indexOf('../')) {
|
|
fs.readFileSync(newpath);
|
|
} else {
|
|
fs.readFileSync(newpath); // $ Alert
|
|
}
|
|
});
|
|
|
|
var isPathInside = require("is-path-inside"),
|
|
pathIsInside = require("path-is-inside");
|
|
app.get('/pseudo-normalizations', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
fs.readFileSync(path); // $ Alert
|
|
if (isPathInside(path, SAFE)) {
|
|
fs.readFileSync(path);
|
|
return;
|
|
} else {
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
}
|
|
if (pathIsInside(path, SAFE)) {
|
|
fs.readFileSync(path); // $ Alert - can be of the form 'safe/directory/../../../etc/passwd'
|
|
return;
|
|
} else {
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
}
|
|
|
|
let normalizedPath = pathModule.join(SAFE, path);
|
|
if (pathIsInside(normalizedPath, SAFE)) {
|
|
fs.readFileSync(normalizedPath);
|
|
return;
|
|
} else {
|
|
fs.readFileSync(normalizedPath); // $ Alert
|
|
}
|
|
|
|
if (pathIsInside(normalizedPath, SAFE)) {
|
|
fs.readFileSync(normalizedPath);
|
|
return;
|
|
} else {
|
|
fs.readFileSync(normalizedPath); // $ Alert
|
|
|
|
}
|
|
|
|
});
|
|
|
|
app.get('/yet-another-prefix', (req, res) => {
|
|
let path = pathModule.resolve(req.query.path); // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
var abs = pathModule.resolve(path);
|
|
|
|
if (abs.indexOf(root) !== 0) {
|
|
fs.readFileSync(path); // $ Alert
|
|
return;
|
|
}
|
|
fs.readFileSync(path);
|
|
});
|
|
|
|
var rootPath = process.cwd();
|
|
app.get('/yet-another-prefix2', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
var requestPath = pathModule.join(rootPath, path);
|
|
|
|
var targetPath;
|
|
if (!allowPath(requestPath, rootPath)) {
|
|
targetPath = rootPath;
|
|
fs.readFileSync(requestPath); // $ Alert
|
|
} else {
|
|
targetPath = requestPath;
|
|
fs.readFileSync(requestPath);
|
|
}
|
|
fs.readFileSync(targetPath);
|
|
|
|
function allowPath(requestPath, rootPath) {
|
|
return requestPath.indexOf(rootPath) === 0;
|
|
}
|
|
});
|
|
|
|
import slash from 'slash';
|
|
app.get('/slash-stuff', (req, res) => {
|
|
let path = req.query.path; // $ Source
|
|
|
|
fs.readFileSync(path); // $ Alert
|
|
|
|
fs.readFileSync(slash(path)); // $ Alert
|
|
});
|
|
|
|
app.get('/dotdot-regexp', (req, res) => {
|
|
let path = pathModule.normalize(req.query.x); // $ Source
|
|
if (pathModule.isAbsolute(path))
|
|
return;
|
|
fs.readFileSync(path); // $ Alert
|
|
if (!path.match(/\./)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.match(/\.\./)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.match(/\.\.\//)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.match(/\.\.\/foo/)) {
|
|
fs.readFileSync(path); // $ Alert
|
|
}
|
|
if (!path.match(/(\.\.\/|\.\.\\)/)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
});
|
|
|
|
app.get('/join-spread', (req, res) => {
|
|
fs.readFileSync(pathModule.join('foo', ...req.query.x.split('/'))); // $ Alert
|
|
fs.readFileSync(pathModule.join(...req.query.x.split('/'))); // $ Alert
|
|
});
|
|
|
|
app.get('/dotdot-matchAll-regexp', (req, res) => {
|
|
let path = pathModule.normalize(req.query.x); // $ Source
|
|
if (pathModule.isAbsolute(path))
|
|
return;
|
|
fs.readFileSync(path); // $ Alert
|
|
if (!path.matchAll(/\./)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.matchAll(/\.\./)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.matchAll(/\.\.\//)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
if (!path.matchAll(/\.\.\/foo/)) {
|
|
fs.readFileSync(path); // $ Alert
|
|
}
|
|
if (!path.matchAll(/(\.\.\/|\.\.\\)/)) {
|
|
fs.readFileSync(path);
|
|
}
|
|
});
|