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

Skip to content

Commit 8309553

Browse files
committed
JS: Port UnvalidatedDynamicMethodCall
1 parent ba9edb4 commit 8309553

4 files changed

Lines changed: 151 additions & 149 deletions

File tree

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ module UnvalidatedDynamicMethodCall {
5454
}
5555
}
5656

57+
/**
58+
* A barrier guard for unvalidated dynamic method calls.
59+
*/
60+
abstract class BarrierGuard extends DataFlow::Node {
61+
/**
62+
* Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`.
63+
*/
64+
predicate blocksExpr(boolean outcome, Expr e) { none() }
65+
66+
/**
67+
* Holds if this node acts as a barrier for `label`, blocking further flow from `e` if `this` evaluates to `outcome`.
68+
*/
69+
predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { none() }
70+
}
71+
72+
/** A subclass of `BarrierGuard` that is used for backward compatibility with the old data flow library. */
73+
abstract class BarrierGuardLegacy extends BarrierGuard, TaintTracking::SanitizerGuardNode {
74+
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
75+
76+
override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
77+
this.blocksExpr(outcome, e, label)
78+
}
79+
}
80+
5781
/**
5882
* A flow label describing values read from a user-controlled property that
5983
* may not be functions.
@@ -109,26 +133,26 @@ module UnvalidatedDynamicMethodCall {
109133
* A check of the form `typeof x === 'function'`, which sanitizes away the `MaybeNonFunction`
110134
* taint kind.
111135
*/
112-
class FunctionCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode {
136+
class FunctionCheck extends BarrierGuardLegacy, DataFlow::ValueNode {
113137
override EqualityTest astNode;
114138
Expr operand;
115139

116140
FunctionCheck() { TaintTracking::isTypeofGuard(astNode, operand, "function") }
117141

118-
override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
142+
override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) {
119143
outcome = astNode.getPolarity() and
120144
e = operand and
121145
label instanceof MaybeNonFunction
122146
}
123147
}
124148

125149
/** A guard that checks whether `x` is a number. */
126-
class NumberGuard extends TaintTracking::SanitizerGuardNode instanceof DataFlow::CallNode {
150+
class NumberGuard extends BarrierGuardLegacy instanceof DataFlow::CallNode {
127151
Expr x;
128152
boolean polarity;
129153

130154
NumberGuard() { TaintTracking::isNumberGuard(this, x, polarity) }
131155

132-
override predicate sanitizes(boolean outcome, Expr e) { e = x and outcome = polarity }
156+
override predicate blocksExpr(boolean outcome, Expr e) { e = x and outcome = polarity }
133157
}
134158
}

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

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,32 @@ private class ConcreteMaybeFromProto extends MaybeFromProto {
2727
/**
2828
* A taint-tracking configuration for reasoning about unvalidated dynamic method calls.
2929
*/
30-
class Configuration extends TaintTracking::Configuration {
31-
Configuration() { this = "UnvalidatedDynamicMethodCall" }
30+
module UnvalidatedDynamicMethodCallConfig implements DataFlow::StateConfigSig {
31+
class FlowState = DataFlow::FlowLabel;
3232

33-
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
33+
predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
3434
source.(Source).getFlowLabel() = label
3535
}
3636

37-
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
37+
predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
3838
sink.(Sink).getFlowLabel() = label
3939
}
4040

41-
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
42-
super.isLabeledBarrier(node, label)
43-
or
41+
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
4442
node.(Sanitizer).getFlowLabel() = label
43+
or
44+
TaintTracking::defaultSanitizer(node) and
45+
label.isTaint()
46+
or
47+
node = DataFlow::MakeLabeledBarrierGuard<BarrierGuard>::getABarrierNode(label)
4548
}
4649

47-
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
48-
guard instanceof NumberGuard or
49-
guard instanceof FunctionCheck
50+
predicate isBarrier(DataFlow::Node node) {
51+
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
5052
}
5153

52-
override predicate isAdditionalFlowStep(
53-
DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel,
54+
predicate isAdditionalFlowStep(
55+
DataFlow::Node src, DataFlow::FlowLabel srclabel, DataFlow::Node dst,
5456
DataFlow::FlowLabel dstlabel
5557
) {
5658
exists(DataFlow::PropRead read |
@@ -74,5 +76,48 @@ class Configuration extends TaintTracking::Configuration {
7476
) and
7577
srclabel.isTaint() and
7678
dstlabel instanceof MaybeNonFunction
79+
or
80+
srclabel.isTaint() and
81+
TaintTracking::defaultTaintStep(src, dst) and
82+
srclabel = dstlabel
83+
}
84+
}
85+
86+
/**
87+
* Taint-tracking for reasoning about unvalidated dynamic method calls.
88+
*/
89+
module UnvalidatedDynamicMethodCallFlow =
90+
DataFlow::GlobalWithState<UnvalidatedDynamicMethodCallConfig>;
91+
92+
/**
93+
* DEPRECATED. Use the `UnvalidatedDynamicMethodCallFlow` module instead.
94+
*/
95+
deprecated class Configuration extends TaintTracking::Configuration {
96+
Configuration() { this = "UnvalidatedDynamicMethodCall" }
97+
98+
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
99+
source.(Source).getFlowLabel() = label
100+
}
101+
102+
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
103+
sink.(Sink).getFlowLabel() = label
104+
}
105+
106+
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
107+
super.isLabeledBarrier(node, label)
108+
or
109+
node.(Sanitizer).getFlowLabel() = label
110+
}
111+
112+
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
113+
guard instanceof NumberGuard or
114+
guard instanceof FunctionCheck
115+
}
116+
117+
override predicate isAdditionalFlowStep(
118+
DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel,
119+
DataFlow::FlowLabel dstlabel
120+
) {
121+
UnvalidatedDynamicMethodCallConfig::isAdditionalFlowStep(src, srclabel, dst, dstlabel)
77122
}
78123
}

javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql

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

1414
import javascript
1515
import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCallQuery
16-
import DataFlow::PathGraph
16+
import DataFlow::DeduplicatePathGraph<UnvalidatedDynamicMethodCallFlow::PathNode, UnvalidatedDynamicMethodCallFlow::PathGraph>
1717

18-
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
19-
where cfg.hasFlowPath(source, sink)
18+
from PathNode source, PathNode sink
19+
where
20+
UnvalidatedDynamicMethodCallFlow::flowPath(source.getAnOriginalPathNode(),
21+
sink.getAnOriginalPathNode())
2022
select sink.getNode(), source, sink,
2123
"Invocation of method with $@ name may dispatch to unexpected target and cause an exception.",
2224
source.getNode(), "user-controlled"

0 commit comments

Comments
 (0)