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

Skip to content

Commit 5af608c

Browse files
committed
JS: Port TypeConfusionThroughParameterTampering
1 parent 25962a9 commit 5af608c

4 files changed

Lines changed: 109 additions & 81 deletions

File tree

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ module TypeConfusionThroughParameterTampering {
2323
*/
2424
abstract class Barrier extends DataFlow::Node { }
2525

26+
/**
27+
* A barrier guard for type confusion for HTTP request inputs.
28+
*/
29+
abstract class BarrierGuard extends DataFlow::Node {
30+
/**
31+
* Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`.
32+
*/
33+
predicate blocksExpr(boolean outcome, Expr e) { none() }
34+
}
35+
36+
/** A subclass of `BarrierGuard` that is used for backward compatibility with the old data flow library. */
37+
abstract class BarrierGuardLegacy extends BarrierGuard, TaintTracking::SanitizerGuardNode {
38+
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
39+
}
40+
2641
/**
2742
* An HTTP request parameter that the user controls the type of.
2843
*

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

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,33 @@ private import semmle.javascript.dataflow.InferredTypes
1313
import TypeConfusionThroughParameterTamperingCustomizations::TypeConfusionThroughParameterTampering
1414

1515
/**
16-
* A taint tracking configuration for type confusion for HTTP request inputs.
16+
* Data flow configuration for type confusion for HTTP request inputs.
1717
*/
18-
class Configuration extends DataFlow::Configuration {
19-
Configuration() { this = "TypeConfusionThroughParameterTampering" }
20-
21-
override predicate isSource(DataFlow::Node source) { source instanceof Source }
18+
module TypeConfusionConfig implements DataFlow::ConfigSig {
19+
predicate isSource(DataFlow::Node source) { source instanceof Source }
2220

23-
override predicate isSink(DataFlow::Node sink) {
21+
predicate isSink(DataFlow::Node sink) {
2422
sink instanceof Sink and
2523
sink.analyze().getAType() = TTString() and
2624
sink.analyze().getAType() = TTObject()
2725
}
2826

29-
override predicate isBarrier(DataFlow::Node node) {
30-
super.isBarrier(node)
31-
or
32-
node instanceof Barrier
33-
}
34-
35-
override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) {
36-
guard instanceof TypeOfTestBarrier or
37-
guard instanceof IsArrayBarrier
27+
predicate isBarrier(DataFlow::Node node) {
28+
node instanceof Barrier or node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
3829
}
3930
}
4031

41-
private class TypeOfTestBarrier extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
32+
/**
33+
* Data flow for type confusion for HTTP request inputs.
34+
*/
35+
module TypeConfusionFlow = DataFlow::Global<TypeConfusionConfig>;
36+
37+
private class TypeOfTestBarrier extends BarrierGuardLegacy, DataFlow::ValueNode {
4238
override EqualityTest astNode;
4339

4440
TypeOfTestBarrier() { TaintTracking::isTypeofGuard(astNode, _, _) }
4541

46-
override predicate blocks(boolean outcome, Expr e) {
42+
override predicate blocksExpr(boolean outcome, Expr e) {
4743
exists(string tag |
4844
TaintTracking::isTypeofGuard(astNode, e, tag) and
4945
if tag = ["string", "object"]
@@ -53,11 +49,33 @@ private class TypeOfTestBarrier extends DataFlow::BarrierGuardNode, DataFlow::Va
5349
}
5450
}
5551

56-
private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallNode {
52+
private class IsArrayBarrier extends BarrierGuardLegacy, DataFlow::CallNode {
5753
IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
5854

59-
override predicate blocks(boolean outcome, Expr e) {
55+
override predicate blocksExpr(boolean outcome, Expr e) {
6056
e = this.getArgument(0).asExpr() and
6157
outcome = [true, false] // separation between string/array removes type confusion in both branches
6258
}
6359
}
60+
61+
/**
62+
* DEPRECATED. Use the `TypeConfusionFlow` module instead.
63+
*/
64+
deprecated class Configuration extends DataFlow::Configuration {
65+
Configuration() { this = "TypeConfusionThroughParameterTampering" }
66+
67+
override predicate isSource(DataFlow::Node source) { TypeConfusionConfig::isSource(source) }
68+
69+
override predicate isSink(DataFlow::Node sink) { TypeConfusionConfig::isSink(sink) }
70+
71+
override predicate isBarrier(DataFlow::Node node) {
72+
super.isBarrier(node)
73+
or
74+
node instanceof Barrier
75+
}
76+
77+
override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) {
78+
guard instanceof TypeOfTestBarrier or
79+
guard instanceof IsArrayBarrier
80+
}
81+
}

javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.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.TypeConfusionThroughParameterTamperingQuery
15-
import DataFlow::PathGraph
15+
import TypeConfusionFlow::PathGraph
1616

17-
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
18-
where cfg.hasFlowPath(source, sink)
17+
from TypeConfusionFlow::PathNode source, TypeConfusionFlow::PathNode sink
18+
where TypeConfusionFlow::flowPath(source, sink)
1919
select sink.getNode(), source, sink,
2020
"Potential type confusion as $@ may be either an array or a string.", source.getNode(),
2121
"this HTTP request parameter"

javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,76 @@
1-
nodes
2-
| tst.js:5:9:5:27 | foo |
3-
| tst.js:5:15:5:27 | req.query.foo |
4-
| tst.js:5:15:5:27 | req.query.foo |
5-
| tst.js:6:5:6:7 | foo |
6-
| tst.js:6:5:6:7 | foo |
7-
| tst.js:8:5:8:7 | foo |
8-
| tst.js:8:5:8:7 | foo |
9-
| tst.js:11:9:11:11 | foo |
10-
| tst.js:11:9:11:11 | foo |
11-
| tst.js:14:16:14:18 | bar |
12-
| tst.js:15:9:15:11 | bar |
13-
| tst.js:15:9:15:11 | bar |
14-
| tst.js:17:7:17:9 | foo |
15-
| tst.js:27:5:27:7 | foo |
16-
| tst.js:27:5:27:7 | foo |
17-
| tst.js:28:5:28:7 | foo |
18-
| tst.js:28:5:28:7 | foo |
19-
| tst.js:45:9:45:35 | foo |
20-
| tst.js:45:15:45:35 | ctx.req ... ery.foo |
21-
| tst.js:45:15:45:35 | ctx.req ... ery.foo |
22-
| tst.js:46:5:46:7 | foo |
23-
| tst.js:46:5:46:7 | foo |
24-
| tst.js:77:25:77:38 | req.query.path |
25-
| tst.js:77:25:77:38 | req.query.path |
26-
| tst.js:80:23:80:23 | p |
27-
| tst.js:81:9:81:9 | p |
28-
| tst.js:81:9:81:9 | p |
29-
| tst.js:82:9:82:9 | p |
30-
| tst.js:82:9:82:9 | p |
31-
| tst.js:90:5:90:12 | data.foo |
32-
| tst.js:90:5:90:12 | data.foo |
33-
| tst.js:90:5:90:12 | data.foo |
34-
| tst.js:92:9:92:16 | data.foo |
35-
| tst.js:92:9:92:16 | data.foo |
36-
| tst.js:92:9:92:16 | data.foo |
37-
| tst.js:98:9:98:16 | data.foo |
38-
| tst.js:98:9:98:16 | data.foo |
39-
| tst.js:98:9:98:16 | data.foo |
40-
| tst.js:103:9:103:29 | data |
41-
| tst.js:103:16:103:29 | req.query.data |
42-
| tst.js:103:16:103:29 | req.query.data |
43-
| tst.js:104:5:104:8 | data |
44-
| tst.js:104:5:104:8 | data |
451
edges
462
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
473
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
484
| tst.js:5:9:5:27 | foo | tst.js:8:5:8:7 | foo |
495
| tst.js:5:9:5:27 | foo | tst.js:8:5:8:7 | foo |
50-
| tst.js:5:9:5:27 | foo | tst.js:11:9:11:11 | foo |
51-
| tst.js:5:9:5:27 | foo | tst.js:11:9:11:11 | foo |
526
| tst.js:5:9:5:27 | foo | tst.js:17:7:17:9 | foo |
7+
| tst.js:5:9:5:27 | foo | tst.js:21:5:21:7 | foo |
8+
| tst.js:5:9:5:27 | foo | tst.js:22:5:22:7 | foo |
9+
| tst.js:5:9:5:27 | foo | tst.js:23:5:23:7 | foo |
10+
| tst.js:5:9:5:27 | foo | tst.js:25:5:25:7 | foo |
5311
| tst.js:5:9:5:27 | foo | tst.js:27:5:27:7 | foo |
5412
| tst.js:5:9:5:27 | foo | tst.js:27:5:27:7 | foo |
5513
| tst.js:5:9:5:27 | foo | tst.js:28:5:28:7 | foo |
56-
| tst.js:5:9:5:27 | foo | tst.js:28:5:28:7 | foo |
57-
| tst.js:5:15:5:27 | req.query.foo | tst.js:5:9:5:27 | foo |
5814
| tst.js:5:15:5:27 | req.query.foo | tst.js:5:9:5:27 | foo |
59-
| tst.js:14:16:14:18 | bar | tst.js:15:9:15:11 | bar |
15+
| tst.js:6:5:6:7 | foo | tst.js:8:5:8:7 | foo |
16+
| tst.js:6:5:6:7 | foo | tst.js:8:5:8:7 | foo |
17+
| tst.js:8:5:8:7 | foo | tst.js:10:5:12:5 | functio ... K\\n } [foo] |
18+
| tst.js:8:5:8:7 | foo | tst.js:17:7:17:9 | foo |
19+
| tst.js:10:5:12:5 | functio ... K\\n } [foo] | tst.js:10:14:10:14 | f [foo] |
20+
| tst.js:10:5:12:5 | functio ... K\\n } [foo] | tst.js:11:9:11:11 | foo |
21+
| tst.js:10:14:10:14 | f [foo] | tst.js:39:12:39:12 | f [foo] |
6022
| tst.js:14:16:14:18 | bar | tst.js:15:9:15:11 | bar |
6123
| tst.js:17:7:17:9 | foo | tst.js:14:16:14:18 | bar |
24+
| tst.js:17:7:17:9 | foo | tst.js:21:5:21:7 | foo |
25+
| tst.js:21:5:21:7 | foo | tst.js:22:5:22:7 | foo |
26+
| tst.js:22:5:22:7 | foo | tst.js:23:5:23:7 | foo |
27+
| tst.js:23:5:23:7 | foo | tst.js:25:5:25:7 | foo |
28+
| tst.js:25:5:25:7 | foo | tst.js:27:5:27:7 | foo |
29+
| tst.js:25:5:25:7 | foo | tst.js:27:5:27:7 | foo |
30+
| tst.js:27:5:27:7 | foo | tst.js:28:5:28:7 | foo |
31+
| tst.js:39:12:39:12 | f [foo] | tst.js:11:9:11:11 | foo |
6232
| tst.js:45:9:45:35 | foo | tst.js:46:5:46:7 | foo |
63-
| tst.js:45:9:45:35 | foo | tst.js:46:5:46:7 | foo |
64-
| tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:45:9:45:35 | foo |
6533
| tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:45:9:45:35 | foo |
6634
| tst.js:77:25:77:38 | req.query.path | tst.js:80:23:80:23 | p |
67-
| tst.js:77:25:77:38 | req.query.path | tst.js:80:23:80:23 | p |
68-
| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p |
6935
| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p |
7036
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
71-
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
72-
| tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo |
73-
| tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo |
74-
| tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo |
7537
| tst.js:103:9:103:29 | data | tst.js:104:5:104:8 | data |
76-
| tst.js:103:9:103:29 | data | tst.js:104:5:104:8 | data |
77-
| tst.js:103:16:103:29 | req.query.data | tst.js:103:9:103:29 | data |
7838
| tst.js:103:16:103:29 | req.query.data | tst.js:103:9:103:29 | data |
39+
nodes
40+
| tst.js:5:9:5:27 | foo | semmle.label | foo |
41+
| tst.js:5:15:5:27 | req.query.foo | semmle.label | req.query.foo |
42+
| tst.js:6:5:6:7 | foo | semmle.label | foo |
43+
| tst.js:6:5:6:7 | foo | semmle.label | foo |
44+
| tst.js:8:5:8:7 | foo | semmle.label | foo |
45+
| tst.js:8:5:8:7 | foo | semmle.label | foo |
46+
| tst.js:10:5:12:5 | functio ... K\\n } [foo] | semmle.label | functio ... K\\n } [foo] |
47+
| tst.js:10:14:10:14 | f [foo] | semmle.label | f [foo] |
48+
| tst.js:11:9:11:11 | foo | semmle.label | foo |
49+
| tst.js:14:16:14:18 | bar | semmle.label | bar |
50+
| tst.js:15:9:15:11 | bar | semmle.label | bar |
51+
| tst.js:17:7:17:9 | foo | semmle.label | foo |
52+
| tst.js:21:5:21:7 | foo | semmle.label | foo |
53+
| tst.js:22:5:22:7 | foo | semmle.label | foo |
54+
| tst.js:23:5:23:7 | foo | semmle.label | foo |
55+
| tst.js:25:5:25:7 | foo | semmle.label | foo |
56+
| tst.js:27:5:27:7 | foo | semmle.label | foo |
57+
| tst.js:27:5:27:7 | foo | semmle.label | foo |
58+
| tst.js:28:5:28:7 | foo | semmle.label | foo |
59+
| tst.js:39:12:39:12 | f [foo] | semmle.label | f [foo] |
60+
| tst.js:45:9:45:35 | foo | semmle.label | foo |
61+
| tst.js:45:15:45:35 | ctx.req ... ery.foo | semmle.label | ctx.req ... ery.foo |
62+
| tst.js:46:5:46:7 | foo | semmle.label | foo |
63+
| tst.js:77:25:77:38 | req.query.path | semmle.label | req.query.path |
64+
| tst.js:80:23:80:23 | p | semmle.label | p |
65+
| tst.js:81:9:81:9 | p | semmle.label | p |
66+
| tst.js:82:9:82:9 | p | semmle.label | p |
67+
| tst.js:90:5:90:12 | data.foo | semmle.label | data.foo |
68+
| tst.js:92:9:92:16 | data.foo | semmle.label | data.foo |
69+
| tst.js:98:9:98:16 | data.foo | semmle.label | data.foo |
70+
| tst.js:103:9:103:29 | data | semmle.label | data |
71+
| tst.js:103:16:103:29 | req.query.data | semmle.label | req.query.data |
72+
| tst.js:104:5:104:8 | data | semmle.label | data |
73+
subpaths
7974
#select
8075
| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |
8176
| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |

0 commit comments

Comments
 (0)