@@ -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,76 @@ 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 a `.contains()` method that is a sanitizer for URL redirects.
90+ *
91+ * Matches any method call where the method is named `contains`.
92+ */
93+ private predicate isContainsUrlSanitizer ( Guard guard , Expr e , boolean branch ) {
94+ guard =
95+ any ( MethodCall method |
96+ method .getMethod ( ) .getName ( ) = "contains" and
97+ e = method .getArgument ( 0 ) and
98+ branch = true
99+ )
100+ }
101+
102+ /**
103+ * An URL argument to a call to `.contains()` that is a sanitizer for URL redirects.
104+ *
105+ * This `contains` method is usually called on a list, but the sanitizer matches any call to a method
106+ * called `contains`, so other methods with the same name will also be considered sanitizers.
107+ */
108+ private class ContainsUrlSanitizer extends RequestForgerySanitizer {
109+ ContainsUrlSanitizer ( ) {
110+ this = DataFlow:: BarrierGuard< isContainsUrlSanitizer / 3 > :: getABarrierNode ( )
111+ }
112+ }
113+
114+ /**
115+ * A check that the URL is relative, and therefore safe for URL redirects.
116+ */
117+ private predicate isRelativeUrlSanitizer ( Guard guard , Expr e , boolean branch ) {
118+ guard =
119+ any ( MethodCall call |
120+ call .getMethod ( ) .hasQualifiedName ( "java.net" , "URI" , "isAbsolute" ) and
121+ e = call .getQualifier ( ) and
122+ branch = false
123+ )
124+ }
125+
126+ /**
127+ * A check that the URL is relative, and therefore safe for URL redirects.
128+ */
129+ private class RelativeUrlSanitizer extends RequestForgerySanitizer {
130+ RelativeUrlSanitizer ( ) {
131+ this = DataFlow:: BarrierGuard< isRelativeUrlSanitizer / 3 > :: getABarrierNode ( )
132+ }
133+ }
134+
135+ /**
136+ * A comparison on the host of a url, that is a sanitizer for URL redirects.
137+ * E.g. `"example.org".equals(url.getHost())"`
138+ */
139+ private predicate isHostComparisonSanitizer ( Guard guard , Expr e , boolean branch ) {
140+ guard =
141+ any ( MethodCall equalsCall |
142+ equalsCall .getMethod ( ) .getName ( ) = "equals" and
143+ branch = true and
144+ exists ( MethodCall hostCall |
145+ hostCall = [ equalsCall .getQualifier ( ) , equalsCall .getArgument ( 0 ) ] and
146+ hostCall .getMethod ( ) .hasQualifiedName ( "java.net" , "URI" , "getHost" ) and
147+ e = hostCall .getQualifier ( )
148+ )
149+ )
150+ }
151+
152+ /**
153+ * A comparison on the `Host` property of a url, that is a sanitizer for URL redirects.
154+ */
155+ private class HostComparisonSanitizer extends RequestForgerySanitizer {
156+ HostComparisonSanitizer ( ) {
157+ this = DataFlow:: BarrierGuard< isHostComparisonSanitizer / 3 > :: getABarrierNode ( )
158+ }
159+ }
0 commit comments