@@ -58,12 +58,13 @@ private class UrlPathBarrier extends UrlForwardBarrier instanceof PathInjectionS
5858 UrlPathBarrier ( ) {
5959 this instanceof ExactPathMatchSanitizer
6060 or
61- this instanceof NoEncodingBarrier
61+ this instanceof NoUrlEncodingBarrier
6262 or
63- this instanceof FullyDecodesBarrier
63+ this instanceof FullyDecodesUrlBarrier
6464 }
6565}
6666
67+ /** A call to a method that decodes a URL. */
6768abstract class UrlDecodeCall extends MethodCall { }
6869
6970private class DefaultUrlDecodeCall extends UrlDecodeCall {
@@ -73,77 +74,69 @@ private class DefaultUrlDecodeCall extends UrlDecodeCall {
7374 }
7475}
7576
76- // TODO: this can probably be named/designed better...
77- abstract class RepeatedStmt extends Stmt { }
77+ /** A repeated call to a method that decodes a URL. */
78+ abstract class RepeatedUrlDecodeCall extends MethodCall { }
7879
79- private class DefaultRepeatedStmt extends RepeatedStmt instanceof LoopStmt { }
80-
81- abstract class CheckEncodingCall extends MethodCall { }
82-
83- private class DefaultCheckEncodingCall extends CheckEncodingCall {
84- DefaultCheckEncodingCall ( ) {
85- // TODO: indexOf?, etc.
86- this .getMethod ( ) .hasQualifiedName ( "java.lang" , "String" , "contains" ) and // TODO: reuse existing class? Or make this a class?
87- this .getArgument ( 0 ) .( CompileTimeConstantExpr ) .getStringValue ( ) = "%"
80+ private class DefaultRepeatedUrlDecodeCall extends RepeatedUrlDecodeCall {
81+ DefaultRepeatedUrlDecodeCall ( ) {
82+ this instanceof UrlDecodeCall and
83+ this .getAnEnclosingStmt ( ) instanceof LoopStmt
8884 }
8985}
9086
91- // TODO: better naming?
92- // TODO: check if any URL decoding implementations _fully_ decode... or if all need to be called in a loop?
93- // TODO: make this extendable instead of `RepeatedStmt`?
94- private class RepeatedUrlDecodeCall extends MethodCall {
95- RepeatedUrlDecodeCall ( ) {
96- this instanceof UrlDecodeCall and
97- this .getAnEnclosingStmt ( ) instanceof RepeatedStmt
87+ /** A method call that checks a string for URL encoding. */
88+ abstract class CheckUrlEncodingCall extends MethodCall { }
89+
90+ private class DefaultCheckUrlEncodingCall extends CheckUrlEncodingCall {
91+ DefaultCheckUrlEncodingCall ( ) {
92+ this . getMethod ( ) instanceof StringContainsMethod and
93+ this .getArgument ( 0 ) . ( CompileTimeConstantExpr ) . getStringValue ( ) = "%"
9894 }
9995}
10096
101- private class CheckEncodingGuard extends Guard instanceof MethodCall , CheckEncodingCall {
97+ private class CheckUrlEncodingGuard extends Guard instanceof CheckUrlEncodingCall {
10298 Expr getCheckedExpr ( ) { result = this .( MethodCall ) .getQualifier ( ) }
10399}
104100
105- private predicate noEncodingGuard ( Guard g , Expr e , boolean branch ) {
106- g instanceof CheckEncodingGuard and
107- e = g .( CheckEncodingGuard ) .getCheckedExpr ( ) and
101+ private predicate noUrlEncodingGuard ( Guard g , Expr e , boolean branch ) {
102+ g instanceof CheckUrlEncodingGuard and
103+ e = g .( CheckUrlEncodingGuard ) .getCheckedExpr ( ) and
108104 branch = false
109105 or
110- // branch = false and
111- // g instanceof AssignExpr and // AssignExpr
112- // exists(CheckEncodingCall call | g.(AssignExpr).getSource() = call | e = call.getQualifier())
113106 branch = false and
114- g .( Expr ) .getType ( ) instanceof BooleanType and // AssignExpr
107+ g .( Expr ) .getType ( ) instanceof BooleanType and // TODO: remove debugging comment: // AssignExpr
115108 (
116- exists ( CheckEncodingCall call , AssignExpr ae |
109+ exists ( CheckUrlEncodingCall call , AssignExpr ae |
117110 ae .getSource ( ) = call and
118111 e = call .getQualifier ( ) and
119112 g = ae .getDest ( )
120113 )
121114 or
122- exists ( CheckEncodingCall call , LocalVariableDeclExpr vde |
115+ exists ( CheckUrlEncodingCall call , LocalVariableDeclExpr vde |
123116 vde .getInitOrPatternSource ( ) = call and
124117 e = call .getQualifier ( ) and
125118 g = vde .getAnAccess ( ) //and
126119 //vde.getVariable() = g
120+ // TODO: remove debugging comments above
127121 )
128122 )
129123}
130124
131- // TODO: check edge case of !contains(%), make sure that behaves as expected at least.
132- private class NoEncodingBarrier extends DataFlow:: Node {
133- NoEncodingBarrier ( ) { this = DataFlow:: BarrierGuard< noEncodingGuard / 3 > :: getABarrierNode ( ) }
125+ private class NoUrlEncodingBarrier extends DataFlow:: Node {
126+ NoUrlEncodingBarrier ( ) { this = DataFlow:: BarrierGuard< noUrlEncodingGuard / 3 > :: getABarrierNode ( ) }
134127}
135128
136- private predicate fullyDecodesGuard ( Expr e ) {
137- exists ( CheckEncodingGuard g , RepeatedUrlDecodeCall decodeCall |
129+ private predicate fullyDecodesUrlGuard ( Expr e ) {
130+ exists ( CheckUrlEncodingGuard g , RepeatedUrlDecodeCall decodeCall |
138131 e = g .getCheckedExpr ( ) and
139132 g .controls ( decodeCall .getBasicBlock ( ) , true )
140133 )
141134}
142135
143- private class FullyDecodesBarrier extends DataFlow:: Node {
144- FullyDecodesBarrier ( ) {
136+ private class FullyDecodesUrlBarrier extends DataFlow:: Node {
137+ FullyDecodesUrlBarrier ( ) {
145138 exists ( Variable v , Expr e | this .asExpr ( ) = v .getAnAccess ( ) |
146- fullyDecodesGuard ( e ) and
139+ fullyDecodesUrlGuard ( e ) and
147140 e = v .getAnAccess ( ) and
148141 e .getBasicBlock ( ) .bbDominates ( this .asExpr ( ) .getBasicBlock ( ) )
149142 )
0 commit comments