@@ -58,12 +58,13 @@ private class UrlPathBarrier extends UrlForwardBarrier instanceof PathInjectionS
58
58
UrlPathBarrier ( ) {
59
59
this instanceof ExactPathMatchSanitizer
60
60
or
61
- this instanceof NoEncodingBarrier
61
+ this instanceof NoUrlEncodingBarrier
62
62
or
63
- this instanceof FullyDecodesBarrier
63
+ this instanceof FullyDecodesUrlBarrier
64
64
}
65
65
}
66
66
67
+ /** A call to a method that decodes a URL. */
67
68
abstract class UrlDecodeCall extends MethodCall { }
68
69
69
70
private class DefaultUrlDecodeCall extends UrlDecodeCall {
@@ -73,77 +74,69 @@ private class DefaultUrlDecodeCall extends UrlDecodeCall {
73
74
}
74
75
}
75
76
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 { }
78
79
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
88
84
}
89
85
}
90
86
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 ( ) = "%"
98
94
}
99
95
}
100
96
101
- private class CheckEncodingGuard extends Guard instanceof MethodCall , CheckEncodingCall {
97
+ private class CheckUrlEncodingGuard extends Guard instanceof CheckUrlEncodingCall {
102
98
Expr getCheckedExpr ( ) { result = this .( MethodCall ) .getQualifier ( ) }
103
99
}
104
100
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
108
104
branch = false
109
105
or
110
- // branch = false and
111
- // g instanceof AssignExpr and // AssignExpr
112
- // exists(CheckEncodingCall call | g.(AssignExpr).getSource() = call | e = call.getQualifier())
113
106
branch = false and
114
- g .( Expr ) .getType ( ) instanceof BooleanType and // AssignExpr
107
+ g .( Expr ) .getType ( ) instanceof BooleanType and // TODO: remove debugging comment: // AssignExpr
115
108
(
116
- exists ( CheckEncodingCall call , AssignExpr ae |
109
+ exists ( CheckUrlEncodingCall call , AssignExpr ae |
117
110
ae .getSource ( ) = call and
118
111
e = call .getQualifier ( ) and
119
112
g = ae .getDest ( )
120
113
)
121
114
or
122
- exists ( CheckEncodingCall call , LocalVariableDeclExpr vde |
115
+ exists ( CheckUrlEncodingCall call , LocalVariableDeclExpr vde |
123
116
vde .getInitOrPatternSource ( ) = call and
124
117
e = call .getQualifier ( ) and
125
118
g = vde .getAnAccess ( ) //and
126
119
//vde.getVariable() = g
120
+ // TODO: remove debugging comments above
127
121
)
128
122
)
129
123
}
130
124
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 ( ) }
134
127
}
135
128
136
- private predicate fullyDecodesGuard ( Expr e ) {
137
- exists ( CheckEncodingGuard g , RepeatedUrlDecodeCall decodeCall |
129
+ private predicate fullyDecodesUrlGuard ( Expr e ) {
130
+ exists ( CheckUrlEncodingGuard g , RepeatedUrlDecodeCall decodeCall |
138
131
e = g .getCheckedExpr ( ) and
139
132
g .controls ( decodeCall .getBasicBlock ( ) , true )
140
133
)
141
134
}
142
135
143
- private class FullyDecodesBarrier extends DataFlow:: Node {
144
- FullyDecodesBarrier ( ) {
136
+ private class FullyDecodesUrlBarrier extends DataFlow:: Node {
137
+ FullyDecodesUrlBarrier ( ) {
145
138
exists ( Variable v , Expr e | this .asExpr ( ) = v .getAnAccess ( ) |
146
- fullyDecodesGuard ( e ) and
139
+ fullyDecodesUrlGuard ( e ) and
147
140
e = v .getAnAccess ( ) and
148
141
e .getBasicBlock ( ) .bbDominates ( this .asExpr ( ) .getBasicBlock ( ) )
149
142
)
0 commit comments