Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7f4d42d

Browse files
committed
JS: Port UnsafeDynamicMethodAccess
1 parent 758f424 commit 7f4d42d

3 files changed

Lines changed: 93 additions & 50 deletions

File tree

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

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,66 @@ private class ConcreteUnsafeFunction extends UnsafeFunction {
2020
/**
2121
* A taint-tracking configuration for reasoning about unsafe dynamic method access.
2222
*/
23-
class Configuration extends TaintTracking::Configuration {
23+
module UnsafeDynamicMethodAccessConfig implements DataFlow::StateConfigSig {
24+
class FlowState = DataFlow::FlowLabel;
25+
26+
predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
27+
source.(Source).getFlowLabel() = label
28+
}
29+
30+
predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
31+
sink.(Sink).getFlowLabel() = label
32+
}
33+
34+
predicate isBarrier(DataFlow::Node node) {
35+
node instanceof Sanitizer
36+
or
37+
exists(StringConcatenation::getOperand(node, _)) and
38+
not StringConcatenation::isCoercion(node)
39+
}
40+
41+
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
42+
TaintTracking::defaultSanitizer(node) and
43+
label.isTaint()
44+
}
45+
46+
predicate isAdditionalFlowStep(
47+
DataFlow::Node src, DataFlow::FlowLabel srclabel, DataFlow::Node dst,
48+
DataFlow::FlowLabel dstlabel
49+
) {
50+
// Reading a property of the global object or of a function
51+
exists(DataFlow::PropRead read |
52+
PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource()) and
53+
src = read.getPropertyNameExpr().flow() and
54+
dst = read and
55+
srclabel.isTaint() and
56+
dstlabel = unsafeFunction()
57+
)
58+
or
59+
// Reading a chain of properties from any object with a prototype can lead to Function
60+
exists(PropertyProjection proj |
61+
not PropertyInjection::isPrototypeLessObject(proj.getObject().getALocalSource()) and
62+
src = proj.getASelector() and
63+
dst = proj and
64+
srclabel.isTaint() and
65+
dstlabel = unsafeFunction()
66+
)
67+
or
68+
srclabel.isTaint() and
69+
TaintTracking::defaultTaintStep(src, dst) and
70+
srclabel = dstlabel
71+
}
72+
}
73+
74+
/**
75+
* Taint-tracking for reasoning about unsafe dynamic method access.
76+
*/
77+
module UnsafeDynamicMethodAccessFlow = DataFlow::GlobalWithState<UnsafeDynamicMethodAccessConfig>;
78+
79+
/**
80+
* DEPRECATED. Use the `UnsafeDynamicMethodAccessFlow` module instead.
81+
*/
82+
deprecated class Configuration extends TaintTracking::Configuration {
2483
Configuration() { this = "UnsafeDynamicMethodAccess" }
2584

2685
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {

javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
import javascript
1414
import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccessQuery
15-
import DataFlow::PathGraph
15+
import UnsafeDynamicMethodAccessFlow::PathGraph
1616

17-
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
18-
where cfg.hasFlowPath(source, sink)
17+
from UnsafeDynamicMethodAccessFlow::PathNode source, UnsafeDynamicMethodAccessFlow::PathNode sink
18+
where UnsafeDynamicMethodAccessFlow::flowPath(source, sink)
1919
select sink, source, sink,
2020
"This method is invoked using a $@, which may allow remote code execution.", source.getNode(),
2121
"user-controlled value"

javascript/ql/test/query-tests/Security/CWE-094/UnsafeDynamicMethodAccess/UnsafeDynamicMethodAccess.expected

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,12 @@
1-
nodes
2-
| example.js:9:37:9:38 | ev |
3-
| example.js:9:37:9:38 | ev |
4-
| example.js:10:9:10:37 | message |
5-
| example.js:10:19:10:37 | JSON.parse(ev.data) |
6-
| example.js:10:30:10:31 | ev |
7-
| example.js:10:30:10:36 | ev.data |
8-
| example.js:13:5:13:24 | window[message.name] |
9-
| example.js:13:5:13:24 | window[message.name] |
10-
| example.js:13:12:13:18 | message |
11-
| example.js:13:12:13:23 | message.name |
12-
| tst.js:3:37:3:38 | ev |
13-
| tst.js:3:37:3:38 | ev |
14-
| tst.js:4:9:4:37 | message |
15-
| tst.js:4:19:4:37 | JSON.parse(ev.data) |
16-
| tst.js:4:30:4:31 | ev |
17-
| tst.js:4:30:4:36 | ev.data |
18-
| tst.js:5:5:5:24 | window[message.name] |
19-
| tst.js:5:5:5:24 | window[message.name] |
20-
| tst.js:5:12:5:18 | message |
21-
| tst.js:5:12:5:23 | message.name |
22-
| tst.js:6:9:6:28 | window[message.name] |
23-
| tst.js:6:9:6:28 | window[message.name] |
24-
| tst.js:6:16:6:22 | message |
25-
| tst.js:6:16:6:27 | message.name |
26-
| tst.js:11:5:11:19 | f[message.name] |
27-
| tst.js:11:5:11:19 | f[message.name] |
28-
| tst.js:11:7:11:13 | message |
29-
| tst.js:11:7:11:18 | message.name |
30-
| tst.js:15:5:15:14 | window[ev] |
31-
| tst.js:15:5:15:14 | window[ev] |
32-
| tst.js:15:12:15:13 | ev |
33-
| tst.js:21:5:21:29 | window[ ... e.name] |
34-
| tst.js:21:5:21:29 | window[ ... e.name] |
35-
| tst.js:21:12:21:28 | '' + message.name |
36-
| tst.js:21:17:21:23 | message |
37-
| tst.js:21:17:21:28 | message.name |
381
edges
392
| example.js:9:37:9:38 | ev | example.js:10:30:10:31 | ev |
40-
| example.js:9:37:9:38 | ev | example.js:10:30:10:31 | ev |
413
| example.js:10:9:10:37 | message | example.js:13:12:13:18 | message |
424
| example.js:10:19:10:37 | JSON.parse(ev.data) | example.js:10:9:10:37 | message |
435
| example.js:10:30:10:31 | ev | example.js:10:30:10:36 | ev.data |
446
| example.js:10:30:10:36 | ev.data | example.js:10:19:10:37 | JSON.parse(ev.data) |
457
| example.js:13:12:13:18 | message | example.js:13:12:13:23 | message.name |
468
| example.js:13:12:13:23 | message.name | example.js:13:5:13:24 | window[message.name] |
47-
| example.js:13:12:13:23 | message.name | example.js:13:5:13:24 | window[message.name] |
489
| tst.js:3:37:3:38 | ev | tst.js:4:30:4:31 | ev |
49-
| tst.js:3:37:3:38 | ev | tst.js:4:30:4:31 | ev |
50-
| tst.js:3:37:3:38 | ev | tst.js:15:12:15:13 | ev |
5110
| tst.js:3:37:3:38 | ev | tst.js:15:12:15:13 | ev |
5211
| tst.js:4:9:4:37 | message | tst.js:5:12:5:18 | message |
5312
| tst.js:4:9:4:37 | message | tst.js:6:16:6:22 | message |
@@ -58,19 +17,44 @@ edges
5817
| tst.js:4:30:4:36 | ev.data | tst.js:4:19:4:37 | JSON.parse(ev.data) |
5918
| tst.js:5:12:5:18 | message | tst.js:5:12:5:23 | message.name |
6019
| tst.js:5:12:5:23 | message.name | tst.js:5:5:5:24 | window[message.name] |
61-
| tst.js:5:12:5:23 | message.name | tst.js:5:5:5:24 | window[message.name] |
6220
| tst.js:6:16:6:22 | message | tst.js:6:16:6:27 | message.name |
6321
| tst.js:6:16:6:27 | message.name | tst.js:6:9:6:28 | window[message.name] |
64-
| tst.js:6:16:6:27 | message.name | tst.js:6:9:6:28 | window[message.name] |
6522
| tst.js:11:7:11:13 | message | tst.js:11:7:11:18 | message.name |
6623
| tst.js:11:7:11:18 | message.name | tst.js:11:5:11:19 | f[message.name] |
67-
| tst.js:11:7:11:18 | message.name | tst.js:11:5:11:19 | f[message.name] |
68-
| tst.js:15:12:15:13 | ev | tst.js:15:5:15:14 | window[ev] |
6924
| tst.js:15:12:15:13 | ev | tst.js:15:5:15:14 | window[ev] |
7025
| tst.js:21:12:21:28 | '' + message.name | tst.js:21:5:21:29 | window[ ... e.name] |
71-
| tst.js:21:12:21:28 | '' + message.name | tst.js:21:5:21:29 | window[ ... e.name] |
7226
| tst.js:21:17:21:23 | message | tst.js:21:17:21:28 | message.name |
7327
| tst.js:21:17:21:28 | message.name | tst.js:21:12:21:28 | '' + message.name |
28+
nodes
29+
| example.js:9:37:9:38 | ev | semmle.label | ev |
30+
| example.js:10:9:10:37 | message | semmle.label | message |
31+
| example.js:10:19:10:37 | JSON.parse(ev.data) | semmle.label | JSON.parse(ev.data) |
32+
| example.js:10:30:10:31 | ev | semmle.label | ev |
33+
| example.js:10:30:10:36 | ev.data | semmle.label | ev.data |
34+
| example.js:13:5:13:24 | window[message.name] | semmle.label | window[message.name] |
35+
| example.js:13:12:13:18 | message | semmle.label | message |
36+
| example.js:13:12:13:23 | message.name | semmle.label | message.name |
37+
| tst.js:3:37:3:38 | ev | semmle.label | ev |
38+
| tst.js:4:9:4:37 | message | semmle.label | message |
39+
| tst.js:4:19:4:37 | JSON.parse(ev.data) | semmle.label | JSON.parse(ev.data) |
40+
| tst.js:4:30:4:31 | ev | semmle.label | ev |
41+
| tst.js:4:30:4:36 | ev.data | semmle.label | ev.data |
42+
| tst.js:5:5:5:24 | window[message.name] | semmle.label | window[message.name] |
43+
| tst.js:5:12:5:18 | message | semmle.label | message |
44+
| tst.js:5:12:5:23 | message.name | semmle.label | message.name |
45+
| tst.js:6:9:6:28 | window[message.name] | semmle.label | window[message.name] |
46+
| tst.js:6:16:6:22 | message | semmle.label | message |
47+
| tst.js:6:16:6:27 | message.name | semmle.label | message.name |
48+
| tst.js:11:5:11:19 | f[message.name] | semmle.label | f[message.name] |
49+
| tst.js:11:7:11:13 | message | semmle.label | message |
50+
| tst.js:11:7:11:18 | message.name | semmle.label | message.name |
51+
| tst.js:15:5:15:14 | window[ev] | semmle.label | window[ev] |
52+
| tst.js:15:12:15:13 | ev | semmle.label | ev |
53+
| tst.js:21:5:21:29 | window[ ... e.name] | semmle.label | window[ ... e.name] |
54+
| tst.js:21:12:21:28 | '' + message.name | semmle.label | '' + message.name |
55+
| tst.js:21:17:21:23 | message | semmle.label | message |
56+
| tst.js:21:17:21:28 | message.name | semmle.label | message.name |
57+
subpaths
7458
#select
7559
| example.js:13:5:13:24 | window[message.name] | example.js:9:37:9:38 | ev | example.js:13:5:13:24 | window[message.name] | This method is invoked using a $@, which may allow remote code execution. | example.js:9:37:9:38 | ev | user-controlled value |
7660
| tst.js:5:5:5:24 | window[message.name] | tst.js:3:37:3:38 | ev | tst.js:5:5:5:24 | window[message.name] | This method is invoked using a $@, which may allow remote code execution. | tst.js:3:37:3:38 | ev | user-controlled value |

0 commit comments

Comments
 (0)