@@ -8,6 +8,7 @@ import semmle.code.java.frameworks.JaxWS
88import semmle.code.java.frameworks.javase.Http
99import semmle.code.java.dataflow.DataFlow
1010import semmle.code.java.frameworks.Properties
11+ private import semmle.code.java.controlflow.Guards
1112private import semmle.code.java.dataflow.StringPrefixes
1213private import semmle.code.java.dataflow.ExternalFlow
1314private import semmle.code.java.security.Sanitizers
@@ -83,3 +84,79 @@ private class HostnameSanitizingPrefix extends InterestingPrefix {
8384private class HostnameSantizer extends RequestForgerySanitizer {
8485 HostnameSantizer ( ) { this .asExpr ( ) = any ( HostnameSanitizingPrefix hsp ) .getAnAppendedExpression ( ) }
8586}
87+
88+ /**
89+ * An argument to a call to `List.contains()` that is a sanitizer for URL redirects.
90+ */
91+ private predicate isContainsUrlSanitizer ( Guard guard , Expr e , boolean branch ) {
92+ guard =
93+ any ( MethodCall method |
94+ method .getMethod ( ) .getName ( ) = "contains" and
95+ e = method .getArgument ( 0 ) and
96+ branch = true
97+ )
98+ }
99+
100+ /**
101+ * An URL argument to a call to `.contains()` that is a sanitizer for URL redirects.
102+ *
103+ * This `contains` method is usually called on a list, but the sanitizer matches any call to a method
104+ * called `contains`, so other methods with the same name will also be considered sanitizers.
105+ */
106+ class ContainsUrlSanitizer extends RequestForgerySanitizer {
107+ ContainsUrlSanitizer ( ) {
108+ this = DataFlow:: BarrierGuard< isContainsUrlSanitizer / 3 > :: getABarrierNode ( )
109+ }
110+ }
111+
112+ /**
113+ * A check that the URL is relative, and therefore safe for URL redirects.
114+ */
115+ private predicate isRelativeUrlSanitizer ( Guard guard , Expr e , boolean branch ) {
116+ guard =
117+ any ( MethodCall call |
118+ exists ( Method method |
119+ call .getMethod ( ) = method and
120+ method .getName ( ) = "isAbsolute" and
121+ method .getDeclaringType ( ) .hasQualifiedName ( "java.net" , "URI" )
122+ ) and
123+ e = call .getQualifier ( ) and
124+ branch = false
125+ )
126+ }
127+
128+ /**
129+ * A check that the URL is relative, and therefore safe for URL redirects.
130+ */
131+ class RelativeUrlSanitizer extends RequestForgerySanitizer {
132+ RelativeUrlSanitizer ( ) {
133+ this = DataFlow:: BarrierGuard< isRelativeUrlSanitizer / 3 > :: getABarrierNode ( )
134+ }
135+ }
136+
137+ /**
138+ * A comparison on the host of a url, that is a sanitizer for URL redirects.
139+ * E.g. `"example.org".equals(url.getHost())"`
140+ */
141+ private predicate isHostComparisonSanitizer ( Guard guard , Expr e , boolean branch ) {
142+ guard =
143+ any ( MethodCall equalsCall |
144+ equalsCall .getMethod ( ) .getName ( ) = "equals" and
145+ branch = true and
146+ exists ( MethodCall hostCall |
147+ hostCall = [ equalsCall .getQualifier ( ) , equalsCall .getArgument ( 0 ) ] and
148+ hostCall .getMethod ( ) .getName ( ) = "getHost" and
149+ hostCall .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.net" , "URI" ) and
150+ e = hostCall .getQualifier ( )
151+ )
152+ )
153+ }
154+
155+ /**
156+ * A comparison on the `Host` property of a url, that is a sanitizer for URL redirects.
157+ */
158+ class HostComparisonSanitizer extends RequestForgerySanitizer {
159+ HostComparisonSanitizer ( ) {
160+ this = DataFlow:: BarrierGuard< isHostComparisonSanitizer / 3 > :: getABarrierNode ( )
161+ }
162+ }
0 commit comments