Skip to content

Commit 7cbaa11

Browse files
authored
Merge pull request #20296 from Napalys/js/remote-property-injection-update
JS: Detect property injection via object enumeration patterns
2 parents a9baf34 + 8fc81f4 commit 7cbaa11

File tree

6 files changed

+33
-13
lines changed

6 files changed

+33
-13
lines changed

javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import javascript
1212
import RemotePropertyInjectionCustomizations::RemotePropertyInjection
13+
private import semmle.javascript.DynamicPropertyAccess
1314

1415
/**
1516
* A taint-tracking configuration for reasoning about remote property injection.
@@ -24,6 +25,10 @@ module RemotePropertyInjectionConfig implements DataFlow::ConfigSig {
2425
node = StringConcatenation::getRoot(any(ConstantString str).flow())
2526
}
2627

28+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
29+
node1 = node2.(EnumeratedPropName).getSourceObject()
30+
}
31+
2732
predicate observeDiffInformedIncrementalMode() { any() }
2833
}
2934

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The query `js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as `Object.keys()`.
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
| tst.js:13:15:13:18 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:13:15:13:18 | prop | A property name to write to depends on a $@. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
44
| tst.js:14:31:14:34 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:14:31:14:34 | prop | A property name to write to depends on a $@. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
55
| tst.js:16:10:16:13 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:16:10:16:13 | prop | A property name to write to depends on a $@. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
6+
| tst.js:22:10:22:12 | key | tst.js:20:14:20:21 | req.body | tst.js:22:10:22:12 | key | A property name to write to depends on a $@. | tst.js:20:14:20:21 | req.body | user-provided value |
67
| tstNonExpr.js:8:17:8:23 | userVal | tstNonExpr.js:5:17:5:23 | req.url | tstNonExpr.js:8:17:8:23 | userVal | A header name depends on a $@. | tstNonExpr.js:5:17:5:23 | req.url | user-provided value |
78
edges
89
| tst.js:8:6:8:9 | prop | tst.js:9:8:9:11 | prop | provenance | |
@@ -11,11 +12,13 @@ edges
1112
| tst.js:8:6:8:9 | prop | tst.js:16:10:16:13 | prop | provenance | |
1213
| tst.js:8:13:8:52 | myCoolL ... rolled) | tst.js:8:6:8:9 | prop | provenance | |
1314
| tst.js:8:28:8:51 | req.que ... trolled | tst.js:8:13:8:52 | myCoolL ... rolled) | provenance | |
14-
| tst.js:8:28:8:51 | req.que ... trolled | tst.js:21:25:21:25 | x | provenance | |
15-
| tst.js:21:25:21:25 | x | tst.js:22:15:22:15 | x | provenance | |
16-
| tst.js:22:6:22:11 | result | tst.js:23:9:23:14 | result | provenance | |
17-
| tst.js:22:15:22:15 | x | tst.js:22:6:22:11 | result | provenance | |
18-
| tst.js:23:9:23:14 | result | tst.js:23:9:23:42 | result. ... length) | provenance | |
15+
| tst.js:8:28:8:51 | req.que ... trolled | tst.js:27:25:27:25 | x | provenance | |
16+
| tst.js:20:14:20:21 | req.body | tst.js:21:3:21:5 | key | provenance | Config |
17+
| tst.js:21:3:21:5 | key | tst.js:22:10:22:12 | key | provenance | |
18+
| tst.js:27:25:27:25 | x | tst.js:28:15:28:15 | x | provenance | |
19+
| tst.js:28:6:28:11 | result | tst.js:29:9:29:14 | result | provenance | |
20+
| tst.js:28:15:28:15 | x | tst.js:28:6:28:11 | result | provenance | |
21+
| tst.js:29:9:29:14 | result | tst.js:29:9:29:42 | result. ... length) | provenance | |
1922
| tstNonExpr.js:5:7:5:13 | userVal | tstNonExpr.js:8:17:8:23 | userVal | provenance | |
2023
| tstNonExpr.js:5:17:5:23 | req.url | tstNonExpr.js:5:7:5:13 | userVal | provenance | |
2124
nodes
@@ -26,13 +29,16 @@ nodes
2629
| tst.js:13:15:13:18 | prop | semmle.label | prop |
2730
| tst.js:14:31:14:34 | prop | semmle.label | prop |
2831
| tst.js:16:10:16:13 | prop | semmle.label | prop |
29-
| tst.js:21:25:21:25 | x | semmle.label | x |
30-
| tst.js:22:6:22:11 | result | semmle.label | result |
31-
| tst.js:22:15:22:15 | x | semmle.label | x |
32-
| tst.js:23:9:23:14 | result | semmle.label | result |
33-
| tst.js:23:9:23:42 | result. ... length) | semmle.label | result. ... length) |
32+
| tst.js:20:14:20:21 | req.body | semmle.label | req.body |
33+
| tst.js:21:3:21:5 | key | semmle.label | key |
34+
| tst.js:22:10:22:12 | key | semmle.label | key |
35+
| tst.js:27:25:27:25 | x | semmle.label | x |
36+
| tst.js:28:6:28:11 | result | semmle.label | result |
37+
| tst.js:28:15:28:15 | x | semmle.label | x |
38+
| tst.js:29:9:29:14 | result | semmle.label | result |
39+
| tst.js:29:9:29:42 | result. ... length) | semmle.label | result. ... length) |
3440
| tstNonExpr.js:5:7:5:13 | userVal | semmle.label | userVal |
3541
| tstNonExpr.js:5:17:5:23 | req.url | semmle.label | req.url |
3642
| tstNonExpr.js:8:17:8:23 | userVal | semmle.label | userVal |
3743
subpaths
38-
| tst.js:8:28:8:51 | req.que ... trolled | tst.js:21:25:21:25 | x | tst.js:23:9:23:42 | result. ... length) | tst.js:8:13:8:52 | myCoolL ... rolled) |
44+
| tst.js:8:28:8:51 | req.que ... trolled | tst.js:27:25:27:25 | x | tst.js:29:9:29:42 | result. ... length) | tst.js:8:13:8:52 | myCoolL ... rolled) |

javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/tst.js renamed to javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection/tst.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ app.get('/user/:id', function(req, res) {
1616
headers[prop] = 42; // $ Alert
1717
res.set(headers);
1818
myCoolLocalFct[req.query.x](); // OK - flagged by method name injection
19+
20+
Object.keys(req.body).forEach( // $ Source
21+
key => {
22+
myObj[key] = 42; // $ Alert
23+
}
24+
);
1925
});
2026

2127
function myCoolLocalFct(x) {
2228
var result = x;
2329
return result.substring(0, result.length);
24-
25-
}
30+
}

0 commit comments

Comments
 (0)