Skip to content

Commit 8dfb920

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: refactor QL, move code to libraries
1 parent 8064e8f commit 8dfb920

File tree

5 files changed

+142
-125
lines changed

5 files changed

+142
-125
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Provides classes for working with Spring classes and interfaces from
3+
* `org.springframework.boot.*`.
4+
*/
5+
6+
import java
7+
8+
/**
9+
* The class `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest`.
10+
*/
11+
class TypeEndpointRequest extends Class {
12+
TypeEndpointRequest() {
13+
this.hasQualifiedName("org.springframework.boot.actuate.autoconfigure.security.servlet",
14+
"EndpointRequest")
15+
}
16+
}
17+
18+
/** A call to `EndpointRequest.toAnyEndpoint` method. */
19+
class ToAnyEndpointCall extends MethodCall {
20+
ToAnyEndpointCall() {
21+
this.getMethod().hasName("toAnyEndpoint") and
22+
this.getMethod().getDeclaringType() instanceof TypeEndpointRequest
23+
}
24+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Provides classes for working with Spring classes and interfaces from
3+
* `org.springframework.security.*`.
4+
*/
5+
6+
import java
7+
8+
/** The class `org.springframework.security.config.annotation.web.builders.HttpSecurity`. */
9+
class TypeHttpSecurity extends Class {
10+
TypeHttpSecurity() {
11+
this.hasQualifiedName("org.springframework.security.config.annotation.web.builders",
12+
"HttpSecurity")
13+
}
14+
}
15+
16+
/**
17+
* The class
18+
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer`.
19+
*/
20+
class TypeAuthorizedUrl extends Class {
21+
TypeAuthorizedUrl() {
22+
this.hasQualifiedName("org.springframework.security.config.annotation.web.configurers",
23+
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>")
24+
}
25+
}
26+
27+
/**
28+
* The class `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
29+
*/
30+
class TypeAbstractRequestMatcherRegistry extends Class {
31+
TypeAbstractRequestMatcherRegistry() {
32+
this.hasQualifiedName("org.springframework.security.config.annotation.web",
33+
"AbstractRequestMatcherRegistry<AuthorizedUrl<>>")
34+
}
35+
}
36+
37+
/** A call to `HttpSecurity.authorizeRequests` method. */
38+
class AuthorizeRequestsCall extends MethodCall {
39+
AuthorizeRequestsCall() {
40+
this.getMethod().hasName("authorizeRequests") and
41+
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity
42+
}
43+
}
44+
45+
/** A call to `AuthorizedUrl.permitAll` method. */
46+
class PermitAllCall extends MethodCall {
47+
PermitAllCall() {
48+
this.getMethod().hasName("permitAll") and
49+
this.getMethod().getDeclaringType() instanceof TypeAuthorizedUrl
50+
}
51+
}
52+
53+
/** A call to `AbstractRequestMatcherRegistry.anyRequest` method. */
54+
class AnyRequestCall extends MethodCall {
55+
AnyRequestCall() {
56+
this.getMethod().hasName("anyRequest") and
57+
this.getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry
58+
}
59+
}
Lines changed: 55 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,14 @@
11
/** Provides classes and predicates to reason about exposed actuators in Spring Boot. */
22

33
import java
4-
5-
/** The class `org.springframework.security.config.annotation.web.builders.HttpSecurity`. */
6-
class TypeHttpSecurity extends Class {
7-
TypeHttpSecurity() {
8-
this.hasQualifiedName("org.springframework.security.config.annotation.web.builders",
9-
"HttpSecurity")
10-
}
11-
}
12-
13-
/**
14-
* The class
15-
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer`.
16-
*/
17-
class TypeAuthorizedUrl extends Class {
18-
TypeAuthorizedUrl() {
19-
this.hasQualifiedName("org.springframework.security.config.annotation.web.configurers",
20-
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>")
21-
}
22-
}
4+
private import semmle.code.java.frameworks.spring.SpringSecurity
5+
private import semmle.code.java.frameworks.spring.SpringBoot
236

247
/**
25-
* The class `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
26-
*/
27-
class TypeAbstractRequestMatcherRegistry extends Class {
28-
TypeAbstractRequestMatcherRegistry() {
29-
this.hasQualifiedName("org.springframework.security.config.annotation.web",
30-
"AbstractRequestMatcherRegistry<AuthorizedUrl<>>")
31-
}
32-
}
33-
34-
/**
35-
* The class `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest`.
36-
*/
37-
class TypeEndpointRequest extends Class {
38-
TypeEndpointRequest() {
39-
this.hasQualifiedName("org.springframework.boot.actuate.autoconfigure.security.servlet",
40-
"EndpointRequest")
41-
}
42-
}
43-
44-
/** A call to `EndpointRequest.toAnyEndpoint` method. */
45-
class ToAnyEndpointCall extends MethodCall {
46-
ToAnyEndpointCall() {
47-
this.getMethod().hasName("toAnyEndpoint") and
48-
this.getMethod().getDeclaringType() instanceof TypeEndpointRequest
49-
}
50-
}
51-
52-
/**
53-
* A call to `HttpSecurity.requestMatcher` method with argument `RequestMatcher.toAnyEndpoint()`.
8+
* A call to `HttpSecurity.requestMatcher` method with argument
9+
* `RequestMatcher.toAnyEndpoint()`.
5410
*/
55-
class RequestMatcherCall extends MethodCall {
11+
private class RequestMatcherCall extends MethodCall {
5612
RequestMatcherCall() {
5713
this.getMethod().hasName("requestMatcher") and
5814
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
@@ -64,94 +20,70 @@ class RequestMatcherCall extends MethodCall {
6420
* A call to `HttpSecurity.requestMatchers` method with lambda argument
6521
* `RequestMatcher.toAnyEndpoint()`.
6622
*/
67-
class RequestMatchersCall extends MethodCall {
23+
private class RequestMatchersCall extends MethodCall {
6824
RequestMatchersCall() {
6925
this.getMethod().hasName("requestMatchers") and
7026
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
7127
this.getArgument(0).(LambdaExpr).getExprBody() instanceof ToAnyEndpointCall
7228
}
7329
}
7430

75-
/** A call to `HttpSecurity.authorizeRequests` method. */
76-
class AuthorizeRequestsCall extends MethodCall {
77-
AuthorizeRequestsCall() {
78-
this.getMethod().hasName("authorizeRequests") and
79-
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity
80-
}
81-
}
82-
83-
/** A call to `AuthorizedUrl.permitAll` method. */
84-
class PermitAllCall extends MethodCall {
85-
PermitAllCall() {
86-
this.getMethod().hasName("permitAll") and
87-
this.getMethod().getDeclaringType() instanceof TypeAuthorizedUrl
88-
}
89-
90-
/** Holds if `permitAll` is called on request(s) mapped to actuator endpoint(s). */
91-
predicate permitsSpringBootActuators() {
92-
exists(AuthorizeRequestsCall authorizeRequestsCall |
93-
// .requestMatcher(EndpointRequest).authorizeRequests([...]).[...]
94-
authorizeRequestsCall.getQualifier() instanceof RequestMatcherCall
95-
or
96-
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
97-
authorizeRequestsCall.getQualifier() instanceof RequestMatchersCall
98-
|
99-
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
100-
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
101-
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = this and
102-
(
103-
this.getQualifier() instanceof AnyRequestCall or
104-
this.getQualifier() instanceof RegistryRequestMatchersCall
105-
)
106-
or
107-
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
108-
// [...].authorizeRequests().anyRequest().permitAll()
109-
authorizeRequestsCall.getNumArgument() = 0 and
110-
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
111-
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
112-
this.getQualifier() = registryRequestMatchersCall
113-
)
114-
or
115-
exists(AnyRequestCall anyRequestCall |
116-
anyRequestCall.getQualifier() = authorizeRequestsCall and
117-
this.getQualifier() = anyRequestCall
118-
)
119-
)
120-
or
121-
exists(AuthorizeRequestsCall authorizeRequestsCall |
122-
// http.authorizeRequests([...]).[...]
123-
authorizeRequestsCall.getQualifier() instanceof VarAccess
124-
|
125-
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
126-
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = this and
127-
this.getQualifier() instanceof RegistryRequestMatchersCall
128-
or
129-
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
130-
authorizeRequestsCall.getNumArgument() = 0 and
131-
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
132-
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
133-
this.getQualifier() = registryRequestMatchersCall
134-
)
135-
)
136-
}
137-
}
138-
139-
/** A call to `AbstractRequestMatcherRegistry.anyRequest` method. */
140-
class AnyRequestCall extends MethodCall {
141-
AnyRequestCall() {
142-
this.getMethod().hasName("anyRequest") and
143-
this.getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry
144-
}
145-
}
146-
14731
/**
14832
* A call to `AbstractRequestMatcherRegistry.requestMatchers` method with an argument
14933
* `RequestMatcher.toAnyEndpoint()`.
15034
*/
151-
class RegistryRequestMatchersCall extends MethodCall {
35+
private class RegistryRequestMatchersCall extends MethodCall {
15236
RegistryRequestMatchersCall() {
15337
this.getMethod().hasName("requestMatchers") and
15438
this.getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry and
15539
this.getAnArgument() instanceof ToAnyEndpointCall
15640
}
15741
}
42+
43+
/** Holds if `permitAllCall` is called on request(s) mapped to actuator endpoint(s). */
44+
predicate permitsSpringBootActuators(PermitAllCall permitAllCall) {
45+
exists(AuthorizeRequestsCall authorizeRequestsCall |
46+
// .requestMatcher(EndpointRequest).authorizeRequests([...]).[...]
47+
authorizeRequestsCall.getQualifier() instanceof RequestMatcherCall
48+
or
49+
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
50+
authorizeRequestsCall.getQualifier() instanceof RequestMatchersCall
51+
|
52+
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
53+
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
54+
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
55+
(
56+
permitAllCall.getQualifier() instanceof AnyRequestCall or
57+
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
58+
)
59+
or
60+
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
61+
// [...].authorizeRequests().anyRequest().permitAll()
62+
authorizeRequestsCall.getNumArgument() = 0 and
63+
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
64+
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
65+
permitAllCall.getQualifier() = registryRequestMatchersCall
66+
)
67+
or
68+
exists(AnyRequestCall anyRequestCall |
69+
anyRequestCall.getQualifier() = authorizeRequestsCall and
70+
permitAllCall.getQualifier() = anyRequestCall
71+
)
72+
)
73+
or
74+
exists(AuthorizeRequestsCall authorizeRequestsCall |
75+
// http.authorizeRequests([...]).[...]
76+
authorizeRequestsCall.getQualifier() instanceof VarAccess
77+
|
78+
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
79+
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
80+
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
81+
or
82+
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
83+
authorizeRequestsCall.getNumArgument() = 0 and
84+
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
85+
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
86+
permitAllCall.getQualifier() = registryRequestMatchersCall
87+
)
88+
)
89+
}

java/ql/src/Security/CWE/CWE-016/SpringBootActuators.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
*/
1313

1414
import java
15+
import semmle.code.java.frameworks.spring.SpringSecurity
1516
import semmle.code.java.security.SpringBootActuatorsQuery
1617

1718
from PermitAllCall permitAllCall
18-
where permitAllCall.permitsSpringBootActuators()
19+
where permitsSpringBootActuators(permitAllCall)
1920
select permitAllCall, "Unauthenticated access to Spring Boot actuator is allowed."

java/ql/test/query-tests/security/CWE-016/SpringBootActuatorsTest.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import java
2+
import semmle.code.java.frameworks.spring.SpringSecurity
23
import semmle.code.java.security.SpringBootActuatorsQuery
34
import utils.test.InlineExpectationsTest
45

@@ -7,7 +8,7 @@ module SpringBootActuatorsTest implements TestSig {
78

89
predicate hasActualResult(Location location, string element, string tag, string value) {
910
tag = "hasExposedSpringBootActuator" and
10-
exists(PermitAllCall permitAllCall | permitAllCall.permitsSpringBootActuators() |
11+
exists(PermitAllCall permitAllCall | permitsSpringBootActuators(permitAllCall) |
1112
permitAllCall.getLocation() = location and
1213
element = permitAllCall.toString() and
1314
value = ""

0 commit comments

Comments
 (0)