1
+ /** Provides classes related to unsafe URL forwarding in Java. */
2
+
1
3
import java
2
4
private import semmle.code.java.dataflow.ExternalFlow
3
5
private import semmle.code.java.dataflow.FlowSources
4
6
private import semmle.code.java.dataflow.StringPrefixes
5
- private import semmle.code.java.frameworks.javaee.ejb.EJBRestrictions
6
7
7
8
/** A sink for unsafe URL forward vulnerabilities. */
8
9
abstract class UnsafeUrlForwardSink extends DataFlow:: Node { }
9
10
10
- /** A sanitizer for unsafe URL forward vulnerabilities. */
11
- abstract class UnsafeUrlForwardSanitizer extends DataFlow:: Node { }
12
-
13
11
/** A default sink representing methods susceptible to unsafe URL forwarding. */
14
12
private class DefaultUnsafeUrlForwardSink extends UnsafeUrlForwardSink {
15
13
DefaultUnsafeUrlForwardSink ( ) { sinkNode ( this , "url-forward" ) }
16
14
}
17
15
16
+ /**
17
+ * An expression appended (perhaps indirectly) to `"forward:"`, and which
18
+ * is reachable from a Spring entry point.
19
+ */
20
+ private class SpringUrlForwardSink extends UnsafeUrlForwardSink {
21
+ SpringUrlForwardSink ( ) {
22
+ // TODO: check if can use MaD "Annotated" for `SpringRequestMappingMethod` or if too complicated for MaD (probably too complicated).
23
+ any ( SpringRequestMappingMethod sqmm ) .polyCalls * ( this .getEnclosingCallable ( ) ) and
24
+ this .asExpr ( ) = any ( ForwardPrefix fp ) .getAnAppendedExpression ( )
25
+ }
26
+ }
27
+
28
+ // TODO: should this potentially be "include:" as well? Or does that not work similarly?
29
+ private class ForwardPrefix extends InterestingPrefix {
30
+ ForwardPrefix ( ) { this .getStringValue ( ) = "forward:" }
31
+
32
+ override int getOffset ( ) { result = 0 }
33
+ }
34
+
35
+ /** A sanitizer for unsafe URL forward vulnerabilities. */
36
+ abstract class UnsafeUrlForwardSanitizer extends DataFlow:: Node { }
37
+
18
38
private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer {
19
39
PrimitiveSanitizer ( ) {
20
40
this .getType ( ) instanceof PrimitiveType or
@@ -23,6 +43,11 @@ private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer {
23
43
}
24
44
}
25
45
46
+ // TODO: double-check this sanitizer (and should I switch all "sanitizer" naming to "barrier" instead?)
47
+ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
48
+ FollowsSanitizingPrefix ( ) { this .asExpr ( ) = any ( SanitizingPrefix fp ) .getAnAppendedExpression ( ) }
49
+ }
50
+
26
51
private class SanitizingPrefix extends InterestingPrefix {
27
52
SanitizingPrefix ( ) {
28
53
not this .getStringValue ( ) .matches ( "/WEB-INF/%" ) and
@@ -31,24 +56,3 @@ private class SanitizingPrefix extends InterestingPrefix {
31
56
32
57
override int getOffset ( ) { result = 0 }
33
58
}
34
-
35
- private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
36
- FollowsSanitizingPrefix ( ) { this .asExpr ( ) = any ( SanitizingPrefix fp ) .getAnAppendedExpression ( ) }
37
- }
38
-
39
- private class ForwardPrefix extends InterestingPrefix {
40
- ForwardPrefix ( ) { this .getStringValue ( ) = "forward:" }
41
-
42
- override int getOffset ( ) { result = 0 }
43
- }
44
-
45
- /**
46
- * An expression appended (perhaps indirectly) to `"forward:"`, and which
47
- * is reachable from a Spring entry point.
48
- */
49
- private class SpringUrlForwardSink extends UnsafeUrlForwardSink {
50
- SpringUrlForwardSink ( ) {
51
- any ( SpringRequestMappingMethod sqmm ) .polyCalls * ( this .getEnclosingCallable ( ) ) and
52
- this .asExpr ( ) = any ( ForwardPrefix fp ) .getAnAppendedExpression ( )
53
- }
54
- }
0 commit comments