JS: Port PrototypePollutingMergeCall

This commit is contained in:
Asger F
2023-10-04 21:42:40 +02:00
parent adf7d5409d
commit a5c221fcfc
3 changed files with 88 additions and 64 deletions

View File

@@ -14,7 +14,10 @@ import semmle.javascript.dependencies.SemVer
import PrototypePollutionCustomizations::PrototypePollution
// Materialize flow labels
private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapper {
/**
* We no longer use this flow label, since it does not work in a world where flow states inherit taint steps.
*/
deprecated private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapper {
ConcreteTaintedObjectWrapper() { this = this }
}
@@ -22,7 +25,45 @@ private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapper {
* A taint tracking configuration for user-controlled objects flowing into deep `extend` calls,
* leading to prototype pollution.
*/
class Configuration extends TaintTracking::Configuration {
module PrototypePollutionConfig implements DataFlow::StateConfigSig {
class FlowState = DataFlow::FlowLabel;
predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) {
node.(Source).getAFlowLabel() = label
}
predicate isSink(DataFlow::Node node, DataFlow::FlowLabel label) {
node.(Sink).getAFlowLabel() = label
}
predicate isAdditionalFlowStep(
DataFlow::Node src, DataFlow::FlowLabel inlbl, DataFlow::Node dst, DataFlow::FlowLabel outlbl
) {
TaintedObject::step(src, dst, inlbl, outlbl)
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) {
// For recursive merge sinks, the deeply tainted object only needs to be reachable from the input, the input itself
// does not need to be deeply tainted.
isSink(node, TaintedObject::label()) and
contents = DataFlow::ContentSet::anyProperty()
}
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
node = TaintedObject::SanitizerGuard::getABarrierNode(label)
}
}
/**
* Taint tracking for user-controlled objects flowing into deep `extend` calls,
* leading to prototype pollution.
*/
module PrototypePollutionFlow = TaintTracking::GlobalWithState<PrototypePollutionConfig>;
/**
* DEPRECATED. Use the `PrototypePollutionFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PrototypePollution" }
override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) {

View File

@@ -19,13 +19,11 @@
import javascript
import semmle.javascript.security.dataflow.PrototypePollutionQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<PrototypePollutionFlow::PathNode, PrototypePollutionFlow::PathGraph>
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string moduleName,
Locatable dependencyLoc
from PathNode source, PathNode sink, string moduleName, Locatable dependencyLoc
where
cfg.hasFlowPath(source, sink) and
PrototypePollutionFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode()) and
sink.getNode().(Sink).dependencyInfo(moduleName, dependencyLoc)
select sink.getNode(), source, sink,
"Prototype pollution caused by merging a $@ using a vulnerable version of $@.", source,

View File

@@ -1,77 +1,62 @@
nodes
| angularmerge.js:1:30:1:34 | event |
| angularmerge.js:1:30:1:34 | event |
| angularmerge.js:2:21:2:42 | JSON.pa ... t.data) |
| angularmerge.js:2:21:2:42 | JSON.pa ... t.data) |
| angularmerge.js:2:32:2:36 | event |
| angularmerge.js:2:32:2:41 | event.data |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
| webix/webix.html:3:34:3:38 | event |
| webix/webix.html:3:34:3:38 | event |
| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
| webix/webix.html:4:37:4:41 | event |
| webix/webix.html:4:37:4:46 | event.data |
| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
| webix/webix.html:5:35:5:39 | event |
| webix/webix.html:5:35:5:44 | event.data |
| webix/webix.js:3:30:3:34 | event |
| webix/webix.js:3:30:3:34 | event |
| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
| webix/webix.js:4:33:4:37 | event |
| webix/webix.js:4:33:4:42 | event.data |
| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
| webix/webix.js:5:31:5:35 | event |
| webix/webix.js:5:31:5:40 | event.data |
| angularmerge.js:1:30:1:34 | event | semmle.label | event |
| angularmerge.js:2:21:2:42 | JSON.pa ... t.data) | semmle.label | JSON.pa ... t.data) |
| angularmerge.js:2:32:2:36 | event | semmle.label | event |
| angularmerge.js:2:32:2:41 | event.data | semmle.label | event.data |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | semmle.label | req.query.foo |
| src-vulnerable-lodash/tst.js:10:17:12:5 | [post update] {\\n ... K\\n } [value] | semmle.label | [post update] {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } | semmle.label | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } [value] | semmle.label | {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | semmle.label | req.query.value |
| src-vulnerable-lodash/tst.js:14:9:16:5 | opts [thing] | semmle.label | opts [thing] |
| src-vulnerable-lodash/tst.js:14:16:16:5 | {\\n ... e\\n } [thing] | semmle.label | {\\n ... e\\n } [thing] |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | semmle.label | req.query.value |
| src-vulnerable-lodash/tst.js:17:17:19:5 | [post update] {\\n ... K\\n } [value] | semmle.label | [post update] {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } | semmle.label | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } [value] | semmle.label | {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:18:16:18:19 | opts [thing] | semmle.label | opts [thing] |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | semmle.label | opts.thing |
| webix/webix.html:3:34:3:38 | event | semmle.label | event |
| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) | semmle.label | JSON.pa ... t.data) |
| webix/webix.html:4:37:4:41 | event | semmle.label | event |
| webix/webix.html:4:37:4:46 | event.data | semmle.label | event.data |
| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) | semmle.label | JSON.pa ... t.data) |
| webix/webix.html:5:35:5:39 | event | semmle.label | event |
| webix/webix.html:5:35:5:44 | event.data | semmle.label | event.data |
| webix/webix.js:3:30:3:34 | event | semmle.label | event |
| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) | semmle.label | JSON.pa ... t.data) |
| webix/webix.js:4:33:4:37 | event | semmle.label | event |
| webix/webix.js:4:33:4:42 | event.data | semmle.label | event.data |
| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) | semmle.label | JSON.pa ... t.data) |
| webix/webix.js:5:31:5:35 | event | semmle.label | event |
| webix/webix.js:5:31:5:40 | event.data | semmle.label | event.data |
edges
| angularmerge.js:1:30:1:34 | event | angularmerge.js:2:32:2:36 | event |
| angularmerge.js:1:30:1:34 | event | angularmerge.js:2:32:2:36 | event |
| angularmerge.js:2:32:2:36 | event | angularmerge.js:2:32:2:41 | event.data |
| angularmerge.js:2:32:2:41 | event.data | angularmerge.js:2:21:2:42 | JSON.pa ... t.data) |
| angularmerge.js:2:32:2:41 | event.data | angularmerge.js:2:21:2:42 | JSON.pa ... t.data) |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:10:17:12:5 | [post update] {\\n ... K\\n } [value] | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } [value] | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | [post update] {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:14:9:16:5 | opts [thing] | src-vulnerable-lodash/tst.js:18:16:18:19 | opts [thing] |
| src-vulnerable-lodash/tst.js:14:16:16:5 | {\\n ... e\\n } [thing] | src-vulnerable-lodash/tst.js:14:9:16:5 | opts [thing] |
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | src-vulnerable-lodash/tst.js:14:16:16:5 | {\\n ... e\\n } [thing] |
| src-vulnerable-lodash/tst.js:17:17:19:5 | [post update] {\\n ... K\\n } [value] | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } [value] |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } [value] | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:18:16:18:19 | opts [thing] | src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | [post update] {\\n ... K\\n } [value] |
| webix/webix.html:3:34:3:38 | event | webix/webix.html:4:37:4:41 | event |
| webix/webix.html:3:34:3:38 | event | webix/webix.html:4:37:4:41 | event |
| webix/webix.html:3:34:3:38 | event | webix/webix.html:5:35:5:39 | event |
| webix/webix.html:3:34:3:38 | event | webix/webix.html:5:35:5:39 | event |
| webix/webix.html:4:37:4:41 | event | webix/webix.html:4:37:4:46 | event.data |
| webix/webix.html:4:37:4:46 | event.data | webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
| webix/webix.html:4:37:4:46 | event.data | webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
| webix/webix.html:5:35:5:39 | event | webix/webix.html:5:35:5:44 | event.data |
| webix/webix.html:5:35:5:44 | event.data | webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
| webix/webix.html:5:35:5:44 | event.data | webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
| webix/webix.js:3:30:3:34 | event | webix/webix.js:4:33:4:37 | event |
| webix/webix.js:3:30:3:34 | event | webix/webix.js:4:33:4:37 | event |
| webix/webix.js:3:30:3:34 | event | webix/webix.js:5:31:5:35 | event |
| webix/webix.js:3:30:3:34 | event | webix/webix.js:5:31:5:35 | event |
| webix/webix.js:4:33:4:37 | event | webix/webix.js:4:33:4:42 | event.data |
| webix/webix.js:4:33:4:42 | event.data | webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
| webix/webix.js:4:33:4:42 | event.data | webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
| webix/webix.js:5:31:5:35 | event | webix/webix.js:5:31:5:40 | event.data |
| webix/webix.js:5:31:5:40 | event.data | webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
| webix/webix.js:5:31:5:40 | event.data | webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
subpaths
#select
| angularmerge.js:2:21:2:42 | JSON.pa ... t.data) | angularmerge.js:1:30:1:34 | event | angularmerge.js:2:21:2:42 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | angularmerge.js:1:30:1:34 | event | user-controlled value | angularmerge.js:2:3:2:43 | angular ... .data)) | angular |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | user-controlled value | src-vulnerable-lodash/package.json:3:19:3:26 | "4.17.4" | lodash |