Merge pull request #2731 from erik-krogh/CVE527

Approved by esbena
This commit is contained in:
semmle-qlci 2020-02-04 08:38:26 +00:00 коммит произвёл GitHub
Родитель 931c0e982e 5ff958a9cf
Коммит bd51ef35b7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 107 добавлений и 17 удалений

Просмотреть файл

@ -47,25 +47,13 @@ abstract class EnumeratedPropName extends DataFlow::Node {
*/
abstract DataFlow::Node getSourceObject();
/**
* Gets a local reference of the source object.
*/
SourceNode getASourceObjectRef() {
exists(SourceNode root, string path |
getSourceObject() = AccessPath::getAReferenceTo(root, path) and
result = AccessPath::getAReferenceTo(root, path)
)
or
result = getSourceObject().getALocalSource()
}
/**
* Gets a property read that accesses the corresponding property value in the source object.
*
* For example, gets `src[key]` in `for (var key in src) { src[key]; }`.
*/
PropRead getASourceProp() {
result = getASourceObjectRef().getAPropertyRead() and
result = AccessPath::getAnAliasedSourceNode(getSourceObject()).getAPropertyRead() and
result.getPropertyNameExpr().flow().getImmediatePredecessor*() = this
}
}
@ -125,7 +113,7 @@ class EntriesEnumeratedPropName extends EnumeratedPropName {
* Holds if the properties of `node` are enumerated locally.
*/
predicate arePropertiesEnumerated(DataFlow::SourceNode node) {
node = any(EnumeratedPropName name).getASourceObjectRef()
node = AccessPath::getAnAliasedSourceNode(any(EnumeratedPropName name).getSourceObject())
}
/**

Просмотреть файл

@ -412,4 +412,17 @@ module AccessPath {
isAssignedInUniqueFile(name)
)
}
/**
* Gets a `SourceNode` that refers to the same value or access path as the given node.
*/
pragma[inline]
DataFlow::SourceNode getAnAliasedSourceNode(DataFlow::Node node) {
exists(DataFlow::SourceNode root, string accessPath |
node = AccessPath::getAReferenceTo(root, accessPath) and
result = AccessPath::getAReferenceTo(root, accessPath)
)
or
result = node.getALocalSource()
}
}

Просмотреть файл

@ -165,10 +165,10 @@ module StringOps {
StartsWith_Substring() {
astNode.hasOperands(call.asExpr(), substring.asExpr()) and
(call.getMethodName() = "substring" or call.getMethodName() = "substr") and
(call.getMethodName() = "substring" or call.getMethodName() = "substr" or call.getMethodName() = "slice") and
call.getNumArgument() = 2 and
(
substring.getALocalSource().getAPropertyRead("length").flowsTo(call.getArgument(1))
AccessPath::getAnAliasedSourceNode(substring).getAPropertyRead("length").flowsTo(call.getArgument(1))
or
substring.getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
)

Просмотреть файл

@ -55,7 +55,7 @@ module ClientSideUrlRedirect {
// exclude `location.href.split('?')[0]`, which can never refer to the query string
not exists(PropAccess pacc | mce = pacc.getBase() | pacc.getPropertyName() = "0")
or
(methodName = "substring" or methodName = "substr") and
(methodName = "substring" or methodName = "substr" or methodName = "slice") and
// exclude `location.href.substring(0, ...)` and similar, which can
// never refer to the query string
not mce.getArgument(0).(NumberLiteral).getIntValue() = 0

Просмотреть файл

@ -14,3 +14,5 @@
| tst.js:19:9:19:36 | A.subst ... "web/" | tst.js:19:9:19:9 | A | tst.js:19:31:19:36 | "web/" | true |
| tst.js:32:9:32:32 | strings ... h(A, B) | tst.js:32:28:32:28 | A | tst.js:32:31:32:31 | B | true |
| tst.js:33:9:33:47 | strings ... h(A, B) | tst.js:33:43:33:43 | A | tst.js:33:46:33:46 | B | true |
| tst.js:34:9:34:34 | A.slice ... ) !== B | tst.js:34:9:34:9 | A | tst.js:34:34:34:34 | B | false |
| tst.js:35:9:35:42 | A.slice ... = B.foo | tst.js:35:9:35:9 | A | tst.js:35:38:35:42 | B.foo | false |

Просмотреть файл

@ -31,4 +31,6 @@ function f(A, B) {
if (strings.startsWith(A, B)) {}
if (strings.caseInsensitiveStartsWith(A, B)) {}
if (A.slice(0, B.length) !== B) {}
if (A.slice(0, B.foo.length) !== B.foo) {}
}

Просмотреть файл

@ -1145,6 +1145,34 @@ nodes
| normalizedPaths.js:228:21:228:24 | path |
| normalizedPaths.js:228:21:228:24 | path |
| normalizedPaths.js:228:21:228:24 | path |
| normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path |
| normalizedPaths.js:236:33:236:46 | req.query.path |
| normalizedPaths.js:236:33:236:46 | req.query.path |
| normalizedPaths.js:236:33:236:46 | req.query.path |
| normalizedPaths.js:236:33:236:46 | req.query.path |
| normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:250:21:250:24 | path |
| tainted-require.js:7:19:7:37 | req.param("module") |
| tainted-require.js:7:19:7:37 | req.param("module") |
| tainted-require.js:7:19:7:37 | req.param("module") |
@ -2903,6 +2931,42 @@ edges
| normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:226:14:226:49 | pathMod ... y.path) |
| normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:226:14:226:49 | pathMod ... y.path) |
| normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:226:14:226:49 | pathMod ... y.path) |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:238:19:238:22 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:245:21:245:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:7:236:47 | path | normalizedPaths.js:250:21:250:24 | path |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) | normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) | normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) | normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:14:236:47 | pathMod ... y.path) | normalizedPaths.js:236:7:236:47 | path |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:236:14:236:47 | pathMod ... y.path) |
| tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") |
| tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") |
| tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") |
@ -3016,6 +3080,9 @@ edges
| normalizedPaths.js:210:21:210:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:210:21:210:34 | normalizedPath | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value |
| normalizedPaths.js:222:21:222:24 | path | normalizedPaths.js:214:35:214:48 | req.query.path | normalizedPaths.js:222:21:222:24 | path | This path depends on $@. | normalizedPaths.js:214:35:214:48 | req.query.path | a user-provided value |
| normalizedPaths.js:228:21:228:24 | path | normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:228:21:228:24 | path | This path depends on $@. | normalizedPaths.js:226:35:226:48 | req.query.path | a user-provided value |
| normalizedPaths.js:238:19:238:22 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:238:19:238:22 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value |
| normalizedPaths.js:245:21:245:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:245:21:245:24 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value |
| normalizedPaths.js:250:21:250:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:250:21:250:24 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value |
| tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value |
| tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | a user-provided value |
| tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | a user-provided value |

Просмотреть файл

@ -231,3 +231,21 @@ app.get('/replace', (req, res) => {
fs.readFileSync(path); // OK
}
});
app.get('/resolve-path', (req, res) => {
let path = pathModule.resolve(req.query.path);
fs.readFileSync(path); // NOT OK
var self = something();
if (path.substring(0, self.dir.length) === self.dir)
fs.readFileSync(path); // OK
else
fs.readFileSync(path); // NOT OK - wrong polarity
if (path.slice(0, self.dir.length) === self.dir)
fs.readFileSync(path); // OK
else
fs.readFileSync(path); // NOT OK - wrong polarity
});