Skip to content

Commit 1e9f745

Browse files
author
Alvaro Muñoz
authored
Merge pull request #31 from GitHubSecurityLab/improve_uricheck_java_query
Account for JaxRS filters
2 parents a183c21 + e194899 commit 1e9f745

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

java/src/security/CWE-022/UnsafeURICheck.ql

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,81 @@ import java
1313
import semmle.code.java.dataflow.FlowSources
1414
import UnsafeURICheckFlow::PathGraph
1515

16-
// Reference: https://mail-archives.apache.org/mod_mbox/ambari-user/202102.mbox/%3CCAEJYuxEQZ_aPwJdAaSxPu-Dva%3Dhc7zZUx3-pzBORbd23g%2BGH1A%40mail.gmail.com%3E
16+
// Example: https://mail-archives.apache.org/mod_mbox/ambari-user/202102.mbox/%3CCAEJYuxEQZ_aPwJdAaSxPu-Dva%3Dhc7zZUx3-pzBORbd23g%2BGH1A%40mail.gmail.com%3E
1717
class ServletFilterInterface extends Interface {
1818
ServletFilterInterface() { this.hasQualifiedName("javax.servlet", "Filter") }
1919
}
2020

21+
class ContainerRequestFilterInterface extends Interface {
22+
ContainerRequestFilterInterface() {
23+
this.hasQualifiedName("javax.ws.rs.container", "ContainerRequestFilter")
24+
}
25+
}
26+
2127
class ServletRequestInterface extends Interface {
2228
ServletRequestInterface() { this.hasQualifiedName("javax.servlet.http", "HttpServletRequest") }
2329
}
2430

25-
class GetRequestURIMethodAccess extends MethodAccess {
26-
GetRequestURIMethodAccess() {
31+
class UriInfoType extends RefType {
32+
UriInfoType() { this.hasQualifiedName("javax.ws.rs.core", "UriInfo") }
33+
}
34+
35+
abstract class FilterMethod extends Method { }
36+
37+
string getSecurityFilterRegexp() { result = ".*(auth|security|jwt|allow|block|login).*" }
38+
39+
class FilterContainerRequestFilterMethod extends FilterMethod {
40+
FilterContainerRequestFilterMethod() {
41+
exists(Method m |
42+
this.overrides*(m) and
43+
m.getName() = "filter" and
44+
m.getDeclaringType() instanceof ContainerRequestFilterInterface and
45+
this.getDeclaringType().getName().toLowerCase().regexpMatch(getSecurityFilterRegexp())
46+
)
47+
}
48+
}
49+
50+
class DoFilterServletRequestMethod extends FilterMethod {
51+
DoFilterServletRequestMethod() {
52+
exists(Method m |
53+
this.overrides*(m) and
54+
m.getName() = "doFilter" and
55+
m.getDeclaringType() instanceof ServletFilterInterface and
56+
this.getDeclaringType().getName().toLowerCase().regexpMatch(getSecurityFilterRegexp())
57+
)
58+
}
59+
}
60+
61+
abstract class GetUriPathCall extends MethodCall { }
62+
63+
class GetRequestURIMethodCall extends GetUriPathCall {
64+
GetRequestURIMethodCall() {
2765
this.getMethod().getName() = "getRequestURI" and
2866
this.getMethod().getDeclaringType() instanceof ServletRequestInterface
2967
}
3068
}
3169

70+
class UriInfoGetPathMethodCall extends GetUriPathCall {
71+
UriInfoGetPathMethodCall() {
72+
this.getMethod().getName() = "getPath" and
73+
this.getMethod().getDeclaringType() instanceof UriInfoType
74+
}
75+
}
76+
3277
private module UnsafeURICheckConfig implements DataFlow::ConfigSig {
3378
predicate isSource(DataFlow::Node source) {
34-
exists(GetRequestURIMethodAccess ma |
35-
ma.getEnclosingCallable().getDeclaringType().getASourceSupertype*() instanceof
36-
ServletFilterInterface and
37-
source.asExpr() = ma
79+
exists(GetUriPathCall call, FilterMethod m |
80+
source.asExpr() = call and
81+
(
82+
m.polyCalls*(call.getEnclosingCallable()) or
83+
m.polyCalls*(call.getEnclosingCallable().getEnclosingCallable()) or
84+
m.polyCalls*(call.getEnclosingCallable().getEnclosingCallable().getEnclosingCallable())
85+
)
3886
)
3987
}
4088

4189
predicate isSink(DataFlow::Node sink) {
42-
exists(MethodAccess ma |
90+
exists(MethodCall ma |
4391
// java.util.regex.Pattern.matcher("aaaaab");
4492
ma.getMethod().getName() = "matcher" and
4593
ma.getMethod().getDeclaringType().hasQualifiedName("java.util.regex", "Pattern") and
@@ -54,7 +102,7 @@ private module UnsafeURICheckConfig implements DataFlow::ConfigSig {
54102
ma.getMethod().getDeclaringType() instanceof TypeString and
55103
sink.asExpr() = ma.getQualifier()
56104
or
57-
ma.getMethod().getName() = ["startsWith", "endsWith"] and
105+
ma.getMethod().getName() = ["contains", "startsWith", "endsWith"] and
58106
ma.getMethod().getDeclaringType() instanceof TypeString and
59107
not ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "/" and
60108
sink.asExpr() = ma.getQualifier()

0 commit comments

Comments
 (0)