Skip to content

Commit a574ff1

Browse files
committed
JS: Remove use of MakeLegacyBarrierGuard in experimental SSRF
1 parent 08d25c1 commit a574ff1

File tree

1 file changed

+17
-24
lines changed
  • javascript/ql/src/experimental/Security/CWE-918

1 file changed

+17
-24
lines changed

javascript/ql/src/experimental/Security/CWE-918/SSRF.qll

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ module SsrfConfig implements DataFlow::ConfigSig {
88
predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgery::Sink }
99

1010
predicate isBarrier(DataFlow::Node node) {
11-
node instanceof RequestForgery::Sanitizer or node = Guards::getABarrierNode()
11+
node instanceof RequestForgery::Sanitizer or
12+
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
1213
}
1314

1415
private predicate hasSanitizingSubstring(DataFlow::Node nd) {
@@ -27,14 +28,6 @@ module SsrfConfig implements DataFlow::ConfigSig {
2728
}
2829

2930
predicate isBarrierOut(DataFlow::Node node) { strictSanitizingPrefixEdge(node, _) }
30-
31-
private predicate isBarrierGuard(DataFlow::BarrierGuardNode nd) {
32-
nd instanceof IntegerCheck or
33-
nd instanceof ValidatorCheck or
34-
nd instanceof TernaryOperatorSanitizerGuard
35-
}
36-
37-
private module Guards = DataFlow::MakeLegacyBarrierGuard<isBarrierGuard/1>;
3831
}
3932

4033
module SsrfFlow = TaintTracking::Global<SsrfConfig>;
@@ -87,6 +80,12 @@ class TernaryOperatorSanitizer extends RequestForgery::Sanitizer {
8780
}
8881
}
8982

83+
/** A barrier guard for this SSRF query. */
84+
abstract class BarrierGuard extends DataFlow::Node {
85+
/** Holds if flow through `e` should be blocked, provided this evaluates to `outcome`. */
86+
abstract predicate blocksExpr(boolean outcome, Expr e);
87+
}
88+
9089
/**
9190
* This sanitizer guard is another way of modeling the example from above
9291
* In this case:
@@ -101,24 +100,22 @@ class TernaryOperatorSanitizer extends RequestForgery::Sanitizer {
101100
* Thats why we model this sanitizer guard which says that
102101
* the result of the ternary operator execution is a sanitizer guard.
103102
*/
104-
class TernaryOperatorSanitizerGuard extends TaintTracking::SanitizerGuardNode {
105-
TaintTracking::SanitizerGuardNode originalGuard;
103+
class TernaryOperatorSanitizerGuard extends BarrierGuard {
104+
TaintTracking::AdditionalBarrierGuard originalGuard;
106105

107106
TernaryOperatorSanitizerGuard() {
108107
this.getAPredecessor+().asExpr().(BooleanLiteral).mayHaveBooleanValue(false) and
109108
this.getAPredecessor+() = originalGuard and
110109
not this.asExpr() instanceof LogicalBinaryExpr
111110
}
112111

113-
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
114-
115-
predicate blocksExpr(boolean outcome, Expr e) {
112+
override predicate blocksExpr(boolean outcome, Expr e) {
116113
not this.asExpr() instanceof LogNotExpr and
117-
originalGuard.sanitizes(outcome, e)
114+
originalGuard.blocksExpr(outcome, e)
118115
or
119116
exists(boolean originalOutcome |
120117
this.asExpr() instanceof LogNotExpr and
121-
originalGuard.sanitizes(originalOutcome, e) and
118+
originalGuard.blocksExpr(originalOutcome, e) and
122119
(
123120
originalOutcome = true and outcome = false
124121
or
@@ -131,12 +128,10 @@ class TernaryOperatorSanitizerGuard extends TaintTracking::SanitizerGuardNode {
131128
/**
132129
* A call to Number.isInteger seen as a sanitizer guard because a number can't be used to exploit a SSRF.
133130
*/
134-
class IntegerCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
131+
class IntegerCheck extends DataFlow::CallNode, BarrierGuard {
135132
IntegerCheck() { this = DataFlow::globalVarRef("Number").getAMemberCall("isInteger") }
136133

137-
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
138-
139-
predicate blocksExpr(boolean outcome, Expr e) {
134+
override predicate blocksExpr(boolean outcome, Expr e) {
140135
outcome = true and
141136
e = this.getArgument(0).asExpr()
142137
}
@@ -147,7 +142,7 @@ class IntegerCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode
147142
* validator is a library which has a variety of input-validation functions. We are interesed in
148143
* checking that source is a number (any type of number) or an alphanumeric value.
149144
*/
150-
class ValidatorCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
145+
class ValidatorCheck extends DataFlow::CallNode, BarrierGuard {
151146
ValidatorCheck() {
152147
exists(DataFlow::SourceNode mod, string method |
153148
mod = DataFlow::moduleImport("validator") and
@@ -159,9 +154,7 @@ class ValidatorCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNo
159154
)
160155
}
161156

162-
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
163-
164-
predicate blocksExpr(boolean outcome, Expr e) {
157+
override predicate blocksExpr(boolean outcome, Expr e) {
165158
outcome = true and
166159
e = this.getArgument(0).asExpr()
167160
}

0 commit comments

Comments
 (0)