Skip to content

Commit b2469ff

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: add APIs and tests for more recent Spring versions: authorizeHttpRequests, AuthorizeHttpRequestsConfigurer, securityMatcher(s)
1 parent 8dfb920 commit b2469ff

File tree

5 files changed

+306
-17
lines changed

5 files changed

+306
-17
lines changed

java/ql/lib/semmle/code/java/frameworks/spring/SpringSecurity.qll

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ class TypeHttpSecurity extends Class {
1515

1616
/**
1717
* The class
18-
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer`.
18+
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer$AuthorizedUrl`
19+
* or the class
20+
* `org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer$AuthorizedUrl`.
1921
*/
2022
class TypeAuthorizedUrl extends Class {
2123
TypeAuthorizedUrl() {
2224
this.hasQualifiedName("org.springframework.security.config.annotation.web.configurers",
23-
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>")
25+
[
26+
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>",
27+
"AuthorizeHttpRequestsConfigurer<HttpSecurity>$AuthorizedUrl<>"
28+
])
2429
}
2530
}
2631

@@ -34,14 +39,32 @@ class TypeAbstractRequestMatcherRegistry extends Class {
3439
}
3540
}
3641

37-
/** A call to `HttpSecurity.authorizeRequests` method. */
42+
/**
43+
* A call to `HttpSecurity.authorizeRequests` method.
44+
*
45+
* Note: this API is deprecated and scheduled for removal
46+
* in Spring Security 7.0.
47+
*/
3848
class AuthorizeRequestsCall extends MethodCall {
3949
AuthorizeRequestsCall() {
4050
this.getMethod().hasName("authorizeRequests") and
4151
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity
4252
}
4353
}
4454

55+
/**
56+
* A call to `HttpSecurity.authorizeHttpRequests` method.
57+
*
58+
* Note: the no-argument version of this API is deprecated
59+
* and scheduled for removal in Spring Security 7.0.
60+
*/
61+
class AuthorizeHttpRequestsCall extends MethodCall {
62+
AuthorizeHttpRequestsCall() {
63+
this.getMethod().hasName("authorizeHttpRequests") and
64+
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity
65+
}
66+
}
67+
4568
/** A call to `AuthorizedUrl.permitAll` method. */
4669
class PermitAllCall extends MethodCall {
4770
PermitAllCall() {

java/ql/lib/semmle/code/java/security/SpringBootActuatorsQuery.qll

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ private import semmle.code.java.frameworks.spring.SpringBoot
66

77
/**
88
* A call to `HttpSecurity.requestMatcher` method with argument
9-
* `RequestMatcher.toAnyEndpoint()`.
9+
* `EndpointRequest.toAnyEndpoint()`.
1010
*/
1111
private class RequestMatcherCall extends MethodCall {
1212
RequestMatcherCall() {
@@ -18,7 +18,7 @@ private class RequestMatcherCall extends MethodCall {
1818

1919
/**
2020
* A call to `HttpSecurity.requestMatchers` method with lambda argument
21-
* `RequestMatcher.toAnyEndpoint()`.
21+
* `EndpointRequest.toAnyEndpoint()`.
2222
*/
2323
private class RequestMatchersCall extends MethodCall {
2424
RequestMatchersCall() {
@@ -40,49 +40,106 @@ private class RegistryRequestMatchersCall extends MethodCall {
4040
}
4141
}
4242

43+
/**
44+
* A call to `HttpSecurity.securityMatcher` method with argument
45+
* `EndpointRequest.toAnyEndpoint()`.
46+
*/
47+
private class SecurityMatcherCall extends MethodCall {
48+
SecurityMatcherCall() {
49+
this.getMethod().hasName("securityMatcher") and
50+
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
51+
this.getArgument(0) instanceof ToAnyEndpointCall
52+
}
53+
}
54+
55+
/**
56+
* A call to `HttpSecurity.securityMatchers` method with lambda argument
57+
* `EndpointRequest.toAnyEndpoint()`.
58+
*/
59+
private class SecurityMatchersCall extends MethodCall {
60+
SecurityMatchersCall() {
61+
this.getMethod().hasName("securityMatchers") and
62+
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
63+
this.getArgument(0).(LambdaExpr).getExprBody() instanceof ToAnyEndpointCall
64+
}
65+
}
66+
67+
/**
68+
* A call to a method that authorizes requests, e.g. `authorizeRequests` or
69+
* `authorizeHttpRequests`.
70+
*/
71+
private class AuthorizeCall extends MethodCall {
72+
AuthorizeCall() {
73+
this instanceof AuthorizeRequestsCall or
74+
this instanceof AuthorizeHttpRequestsCall
75+
}
76+
}
77+
78+
/**
79+
* A call to a matcher method with argument
80+
* `EndpointRequest.toAnyEndpoint()`.
81+
*/
82+
private class MatcherCall extends MethodCall {
83+
MatcherCall() {
84+
this instanceof RequestMatcherCall or
85+
this instanceof SecurityMatcherCall
86+
}
87+
}
88+
89+
/**
90+
* A call to a matchers method with argument
91+
* `EndpointRequest.toAnyEndpoint()`.
92+
*/
93+
private class MatchersCall extends MethodCall {
94+
MatchersCall() {
95+
this instanceof RequestMatchersCall or
96+
this instanceof SecurityMatchersCall
97+
}
98+
}
99+
43100
/** Holds if `permitAllCall` is called on request(s) mapped to actuator endpoint(s). */
44101
predicate permitsSpringBootActuators(PermitAllCall permitAllCall) {
45-
exists(AuthorizeRequestsCall authorizeRequestsCall |
102+
exists(AuthorizeCall authorizeCall |
46103
// .requestMatcher(EndpointRequest).authorizeRequests([...]).[...]
47-
authorizeRequestsCall.getQualifier() instanceof RequestMatcherCall
104+
authorizeCall.getQualifier() instanceof MatcherCall
48105
or
49106
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
50-
authorizeRequestsCall.getQualifier() instanceof RequestMatchersCall
107+
authorizeCall.getQualifier() instanceof MatchersCall
51108
|
52109
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
53110
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
54-
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
111+
authorizeCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
55112
(
56113
permitAllCall.getQualifier() instanceof AnyRequestCall or
57114
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
58115
)
59116
or
60117
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
61118
// [...].authorizeRequests().anyRequest().permitAll()
62-
authorizeRequestsCall.getNumArgument() = 0 and
119+
authorizeCall.getNumArgument() = 0 and
63120
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
64-
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
121+
registryRequestMatchersCall.getQualifier() = authorizeCall and
65122
permitAllCall.getQualifier() = registryRequestMatchersCall
66123
)
67124
or
68125
exists(AnyRequestCall anyRequestCall |
69-
anyRequestCall.getQualifier() = authorizeRequestsCall and
126+
anyRequestCall.getQualifier() = authorizeCall and
70127
permitAllCall.getQualifier() = anyRequestCall
71128
)
72129
)
73130
or
74-
exists(AuthorizeRequestsCall authorizeRequestsCall |
131+
exists(AuthorizeCall authorizeCall |
75132
// http.authorizeRequests([...]).[...]
76-
authorizeRequestsCall.getQualifier() instanceof VarAccess
133+
authorizeCall.getQualifier() instanceof VarAccess
77134
|
78135
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
79-
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
136+
authorizeCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
80137
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
81138
or
82139
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
83-
authorizeRequestsCall.getNumArgument() = 0 and
140+
authorizeCall.getNumArgument() = 0 and
84141
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
85-
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
142+
registryRequestMatchersCall.getQualifier() = authorizeCall and
86143
permitAllCall.getQualifier() = registryRequestMatchersCall
87144
)
88145
)

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

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
33

44
public class SpringBootActuatorsTest {
5+
// Spring security version 5.2.3 used `authorizeRequests` and `requestMatcher(s)`
56
protected void configure(HttpSecurity http) throws Exception {
67
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
78
}
@@ -101,4 +102,166 @@ protected void configureOkNoPermitAll6(HttpSecurity http) throws Exception {
101102
protected void configureOkNoPermitAll7(HttpSecurity http) throws Exception {
102103
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest();
103104
}
105+
106+
// Spring security version 5.5.0 introduced `authorizeHttpRequests`
107+
protected void configure_authorizeHttpRequests(HttpSecurity http) throws Exception {
108+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
109+
}
110+
111+
protected void configure2_authorizeHttpRequests(HttpSecurity http) throws Exception {
112+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
113+
}
114+
115+
protected void configure3_authorizeHttpRequests(HttpSecurity http) throws Exception {
116+
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
117+
}
118+
119+
protected void configure4_authorizeHttpRequests(HttpSecurity http) throws Exception {
120+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
121+
}
122+
123+
protected void configure5_authorizeHttpRequests(HttpSecurity http) throws Exception {
124+
http.authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
125+
}
126+
127+
protected void configure6_authorizeHttpRequests(HttpSecurity http) throws Exception {
128+
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()); // $ hasExposedSpringBootActuator
129+
}
130+
131+
protected void configure7_authorizeHttpRequests(HttpSecurity http) throws Exception {
132+
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
133+
}
134+
135+
protected void configureOk3_authorizeHttpRequests(HttpSecurity http) throws Exception {
136+
http.authorizeHttpRequests().anyRequest().permitAll();
137+
}
138+
139+
protected void configureOk4_authorizeHttpRequests(HttpSecurity http) throws Exception {
140+
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
141+
}
142+
143+
protected void configureOkSafeEndpoints1_authorizeHttpRequests(HttpSecurity http) throws Exception {
144+
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests(requests -> requests.anyRequest().permitAll());
145+
}
146+
147+
protected void configureOkSafeEndpoints2_authorizeHttpRequests(HttpSecurity http) throws Exception {
148+
http.requestMatcher(EndpointRequest.to("health")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
149+
}
150+
151+
protected void configureOkSafeEndpoints3_authorizeHttpRequests(HttpSecurity http) throws Exception {
152+
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
153+
}
154+
155+
protected void configureOkSafeEndpoints4_authorizeHttpRequests(HttpSecurity http) throws Exception {
156+
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
157+
}
158+
159+
protected void configureOkSafeEndpoints5_authorizeHttpRequests(HttpSecurity http) throws Exception {
160+
http.authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
161+
}
162+
163+
protected void configureOkSafeEndpoints6_authorizeHttpRequests(HttpSecurity http) throws Exception {
164+
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.to("health", "info")).permitAll());
165+
}
166+
167+
protected void configureOkSafeEndpoints7_authorizeHttpRequests(HttpSecurity http) throws Exception {
168+
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
169+
}
170+
171+
protected void configureOkNoPermitAll1_authorizeHttpRequests(HttpSecurity http) throws Exception {
172+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest());
173+
}
174+
175+
protected void configureOkNoPermitAll2_authorizeHttpRequests(HttpSecurity http) throws Exception {
176+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
177+
}
178+
179+
protected void configureOkNoPermitAll3_authorizeHttpRequests(HttpSecurity http) throws Exception {
180+
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
181+
}
182+
183+
protected void configureOkNoPermitAll4_authorizeHttpRequests(HttpSecurity http) throws Exception {
184+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
185+
}
186+
187+
protected void configureOkNoPermitAll5_authorizeHttpRequests(HttpSecurity http) throws Exception {
188+
http.authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
189+
}
190+
191+
protected void configureOkNoPermitAll6_authorizeHttpRequests(HttpSecurity http) throws Exception {
192+
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()));
193+
}
194+
195+
protected void configureOkNoPermitAll7_authorizeHttpRequests(HttpSecurity http) throws Exception {
196+
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
197+
}
198+
199+
// Spring security version 5.8.0 introduced `securityMatcher(s)`
200+
protected void configure_securityMatchers(HttpSecurity http) throws Exception {
201+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
202+
}
203+
204+
protected void configure2_securityMatchers(HttpSecurity http) throws Exception {
205+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
206+
}
207+
208+
protected void configure3_securityMatchers(HttpSecurity http) throws Exception {
209+
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
210+
}
211+
212+
protected void configure4_securityMatchers(HttpSecurity http) throws Exception {
213+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
214+
}
215+
216+
protected void configure7_securityMatchers(HttpSecurity http) throws Exception {
217+
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
218+
}
219+
220+
protected void configureOk1_securityMatchers(HttpSecurity http) throws Exception {
221+
http.securityMatcher(EndpointRequest.toAnyEndpoint());
222+
}
223+
224+
protected void configureOk2_securityMatchers(HttpSecurity http) throws Exception {
225+
http.securityMatchers().requestMatchers(EndpointRequest.toAnyEndpoint());
226+
}
227+
228+
protected void configureOkSafeEndpoints1_securityMatchers(HttpSecurity http) throws Exception {
229+
http.securityMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests(requests -> requests.anyRequest().permitAll());
230+
}
231+
232+
protected void configureOkSafeEndpoints2_securityMatchers(HttpSecurity http) throws Exception {
233+
http.securityMatcher(EndpointRequest.to("health")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
234+
}
235+
236+
protected void configureOkSafeEndpoints3_securityMatchers(HttpSecurity http) throws Exception {
237+
http.securityMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
238+
}
239+
240+
protected void configureOkSafeEndpoints4_securityMatchers(HttpSecurity http) throws Exception {
241+
http.securityMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
242+
}
243+
244+
protected void configureOkSafeEndpoints7_securityMatchers(HttpSecurity http) throws Exception {
245+
http.securityMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
246+
}
247+
248+
protected void configureOkNoPermitAll1_securityMatchers(HttpSecurity http) throws Exception {
249+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest());
250+
}
251+
252+
protected void configureOkNoPermitAll2_securityMatchers(HttpSecurity http) throws Exception {
253+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
254+
}
255+
256+
protected void configureOkNoPermitAll3_securityMatchers(HttpSecurity http) throws Exception {
257+
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
258+
}
259+
260+
protected void configureOkNoPermitAll4_securityMatchers(HttpSecurity http) throws Exception {
261+
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
262+
}
263+
264+
protected void configureOkNoPermitAll7_securityMatchers(HttpSecurity http) throws Exception {
265+
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
266+
}
104267
}

0 commit comments

Comments
 (0)