@@ -7,9 +7,37 @@ import semmle.code.java.frameworks.spring.SpringWeb
7
7
import semmle.code.java.security.RequestForgery
8
8
private import semmle.code.java.dataflow.StringPrefixes
9
9
10
- /** A sanitizer for unsafe url forward vulnerabilities. */
10
+ /** A sink for unsafe URL forward vulnerabilities. */
11
+ abstract class UnsafeUrlForwardSink extends DataFlow:: Node { }
12
+
13
+ /** A sanitizer for unsafe URL forward vulnerabilities. */
11
14
abstract class UnsafeUrlForwardSanitizer extends DataFlow:: Node { }
12
15
16
+ /** A barrier guard that protects against URL forward vulnerabilities. */
17
+ abstract class UnsafeUrlForwardBarrierGuard extends DataFlow:: BarrierGuard { }
18
+
19
+ /** An argument to `getRequestDispatcher`. */
20
+ private class RequestDispatcherSink extends UnsafeUrlForwardSink {
21
+ RequestDispatcherSink ( ) {
22
+ exists ( MethodAccess ma |
23
+ ma .getMethod ( ) instanceof GetRequestDispatcherMethod and
24
+ ma .getArgument ( 0 ) = this .asExpr ( )
25
+ )
26
+ }
27
+ }
28
+
29
+ /** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
30
+ private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
31
+ SpringModelAndViewSink ( ) {
32
+ exists ( ClassInstanceExpr cie |
33
+ cie .getConstructedType ( ) instanceof ModelAndView and
34
+ cie .getArgument ( 0 ) = this .asExpr ( )
35
+ )
36
+ or
37
+ exists ( SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc .getArgument ( 0 ) = this .asExpr ( ) )
38
+ }
39
+ }
40
+
13
41
private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer {
14
42
PrimitiveSanitizer ( ) {
15
43
this .getType ( ) instanceof PrimitiveType or
@@ -31,74 +59,6 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
31
59
FollowsSanitizingPrefix ( ) { this .asExpr ( ) = any ( SanitizingPrefix fp ) .getAnAppendedExpression ( ) }
32
60
}
33
61
34
- /** A barrier guard that protects against URL forward vulnerabilities. */
35
- abstract class UnsafeUrlForwardBarrierGuard extends DataFlow:: BarrierGuard { }
36
-
37
- /**
38
- * Holds if `ma` is a call to a method that checks a path string.
39
- */
40
- private predicate isStringPathMatch ( MethodAccess ma ) {
41
- ma .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
42
- ma .getMethod ( ) .getName ( ) =
43
- [ "contains" , "startsWith" , "matches" , "regionMatches" , "indexOf" , "lastIndexOf" ]
44
- }
45
-
46
- /**
47
- * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
48
- */
49
- private predicate isFilePathMatch ( MethodAccess ma ) {
50
- ma .getMethod ( ) .getDeclaringType ( ) instanceof TypePath and
51
- ma .getMethod ( ) .getName ( ) = "startsWith"
52
- }
53
-
54
- /** A complementary guard that protects against path traversal, by looking for the literal `..`. */
55
- private class PathTraversalGuard extends Guard instanceof MethodAccess {
56
- Expr checked ;
57
-
58
- PathTraversalGuard ( ) {
59
- this .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
60
- this .getMethod ( ) .hasName ( [ "contains" , "indexOf" ] ) and
61
- this .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = ".." and
62
- this .controls ( checked .getBasicBlock ( ) , false )
63
- }
64
-
65
- predicate checks ( Expr e ) { checked = e }
66
- }
67
-
68
- /** A complementary sanitizer that protects against path traversal using path normalization. */
69
- private class PathNormalizeSanitizer extends MethodAccess {
70
- PathNormalizeSanitizer ( ) {
71
- this .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.nio.file" , "Path" ) and
72
- this .getMethod ( ) .hasName ( "normalize" )
73
- }
74
- }
75
-
76
- /** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
77
- private class UrlEncodingGuard extends Guard instanceof MethodAccess {
78
- Expr checked ;
79
-
80
- UrlEncodingGuard ( ) {
81
- this .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
82
- this .getMethod ( ) .hasName ( [ "contains" , "indexOf" ] ) and
83
- this .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = "%" and
84
- this .controls ( checked .getBasicBlock ( ) , false )
85
- }
86
-
87
- predicate checks ( Expr e ) { checked = e }
88
- }
89
-
90
- /** A complementary sanitizer that protects against double URL encoding using URL decoding. */
91
- private class UrlDecodeSanitizer extends MethodAccess {
92
- UrlDecodeSanitizer ( ) {
93
- this .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.net" , "URLDecoder" ) and
94
- this .getMethod ( ) .hasName ( "decode" )
95
- }
96
- }
97
-
98
- private predicate isDisallowedWord ( CompileTimeConstantExpr word ) {
99
- word .getStringValue ( ) .matches ( [ "%WEB-INF%" , "%META-INF%" , "%..%" ] )
100
- }
101
-
102
62
/**
103
63
* A guard that considers safe a string being exactly compared to a trusted value.
104
64
*/
@@ -176,27 +136,68 @@ private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceo
176
136
}
177
137
}
178
138
179
- abstract class UnsafeUrlForwardSink extends DataFlow:: Node { }
139
+ /**
140
+ * Holds if `ma` is a call to a method that checks a path string.
141
+ */
142
+ private predicate isStringPathMatch ( MethodAccess ma ) {
143
+ ma .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
144
+ ma .getMethod ( ) .getName ( ) =
145
+ [ "contains" , "startsWith" , "matches" , "regionMatches" , "indexOf" , "lastIndexOf" ]
146
+ }
180
147
181
- /** An argument to `getRequestDispatcher`. */
182
- private class RequestDispatcherSink extends UnsafeUrlForwardSink {
183
- RequestDispatcherSink ( ) {
184
- exists ( MethodAccess ma |
185
- ma .getMethod ( ) instanceof GetRequestDispatcherMethod and
186
- ma .getArgument ( 0 ) = this .asExpr ( )
187
- )
148
+ /**
149
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
150
+ */
151
+ private predicate isFilePathMatch ( MethodAccess ma ) {
152
+ ma .getMethod ( ) .getDeclaringType ( ) instanceof TypePath and
153
+ ma .getMethod ( ) .getName ( ) = "startsWith"
154
+ }
155
+
156
+ private predicate isDisallowedWord ( CompileTimeConstantExpr word ) {
157
+ word .getStringValue ( ) .matches ( [ "%WEB-INF%" , "%META-INF%" , "%..%" ] )
158
+ }
159
+
160
+ /** A complementary guard that protects against path traversal, by looking for the literal `..`. */
161
+ private class PathTraversalGuard extends Guard instanceof MethodAccess {
162
+ Expr checked ;
163
+
164
+ PathTraversalGuard ( ) {
165
+ this .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
166
+ this .getMethod ( ) .hasName ( [ "contains" , "indexOf" ] ) and
167
+ this .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = ".." and
168
+ this .controls ( checked .getBasicBlock ( ) , false )
188
169
}
170
+
171
+ predicate checks ( Expr e ) { checked = e }
189
172
}
190
173
191
- /** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
192
- private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
193
- SpringModelAndViewSink ( ) {
194
- exists ( ClassInstanceExpr cie |
195
- cie .getConstructedType ( ) instanceof ModelAndView and
196
- cie .getArgument ( 0 ) = this .asExpr ( )
197
- )
198
- or
199
- exists ( SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc .getArgument ( 0 ) = this .asExpr ( ) )
174
+ /** A complementary sanitizer that protects against path traversal using path normalization. */
175
+ private class PathNormalizeSanitizer extends MethodAccess {
176
+ PathNormalizeSanitizer ( ) {
177
+ this .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.nio.file" , "Path" ) and
178
+ this .getMethod ( ) .hasName ( "normalize" )
179
+ }
180
+ }
181
+
182
+ /** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
183
+ private class UrlEncodingGuard extends Guard instanceof MethodAccess {
184
+ Expr checked ;
185
+
186
+ UrlEncodingGuard ( ) {
187
+ this .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
188
+ this .getMethod ( ) .hasName ( [ "contains" , "indexOf" ] ) and
189
+ this .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = "%" and
190
+ this .controls ( checked .getBasicBlock ( ) , false )
191
+ }
192
+
193
+ predicate checks ( Expr e ) { checked = e }
194
+ }
195
+
196
+ /** A complementary sanitizer that protects against double URL encoding using URL decoding. */
197
+ private class UrlDecodeSanitizer extends MethodAccess {
198
+ UrlDecodeSanitizer ( ) {
199
+ this .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.net" , "URLDecoder" ) and
200
+ this .getMethod ( ) .hasName ( "decode" )
200
201
}
201
202
}
202
203
0 commit comments