@@ -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
4033module 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