mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Merge pull request #18793 from jcogs33/jcogs33/java/spring-boot-actuators-promo
Java: Promote Spring Boot Actuators query from experimental
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Provides classes for working with Spring classes and interfaces from
|
||||
* `org.springframework.boot.*`.
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* The class `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest`.
|
||||
*/
|
||||
class SpringEndpointRequest extends Class {
|
||||
SpringEndpointRequest() {
|
||||
this.hasQualifiedName("org.springframework.boot.actuate.autoconfigure.security.servlet",
|
||||
"EndpointRequest")
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `EndpointRequest.toAnyEndpoint` method. */
|
||||
class SpringToAnyEndpointCall extends MethodCall {
|
||||
SpringToAnyEndpointCall() {
|
||||
this.getMethod().hasName("toAnyEndpoint") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringEndpointRequest
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Provides classes for working with Spring classes and interfaces from
|
||||
* `org.springframework.security.*`.
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/** The class `org.springframework.security.config.annotation.web.builders.HttpSecurity`. */
|
||||
class SpringHttpSecurity extends Class {
|
||||
SpringHttpSecurity() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web.builders",
|
||||
"HttpSecurity")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class
|
||||
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer$AuthorizedUrl`
|
||||
* or the class
|
||||
* `org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer$AuthorizedUrl`.
|
||||
*/
|
||||
class SpringAuthorizedUrl extends Class {
|
||||
SpringAuthorizedUrl() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web.configurers",
|
||||
[
|
||||
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>",
|
||||
"AuthorizeHttpRequestsConfigurer<HttpSecurity>$AuthorizedUrl<>"
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
|
||||
*/
|
||||
class SpringAbstractRequestMatcherRegistry extends Class {
|
||||
SpringAbstractRequestMatcherRegistry() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web",
|
||||
"AbstractRequestMatcherRegistry<AuthorizedUrl<>>")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `HttpSecurity.authorizeRequests` method.
|
||||
*
|
||||
* Note: this method is deprecated and scheduled for removal
|
||||
* in Spring Security 7.0.
|
||||
*/
|
||||
class SpringAuthorizeRequestsCall extends MethodCall {
|
||||
SpringAuthorizeRequestsCall() {
|
||||
this.getMethod().hasName("authorizeRequests") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `HttpSecurity.authorizeHttpRequests` method.
|
||||
*
|
||||
* Note: the no-argument version of this method is deprecated
|
||||
* and scheduled for removal in Spring Security 7.0.
|
||||
*/
|
||||
class SpringAuthorizeHttpRequestsCall extends MethodCall {
|
||||
SpringAuthorizeHttpRequestsCall() {
|
||||
this.getMethod().hasName("authorizeHttpRequests") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `HttpSecurity.requestMatcher` method.
|
||||
*
|
||||
* Note: this method was removed in Spring Security 6.0.
|
||||
* It was replaced by `securityMatcher`.
|
||||
*/
|
||||
class SpringRequestMatcherCall extends MethodCall {
|
||||
SpringRequestMatcherCall() {
|
||||
this.getMethod().hasName("requestMatcher") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `HttpSecurity.requestMatchers` method.
|
||||
*
|
||||
* Note: this method was removed in Spring Security 6.0.
|
||||
* It was replaced by `securityMatchers`.
|
||||
*/
|
||||
class SpringRequestMatchersCall extends MethodCall {
|
||||
SpringRequestMatchersCall() {
|
||||
this.getMethod().hasName("requestMatchers") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `HttpSecurity.securityMatcher` method. */
|
||||
class SpringSecurityMatcherCall extends MethodCall {
|
||||
SpringSecurityMatcherCall() {
|
||||
this.getMethod().hasName("securityMatcher") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `HttpSecurity.securityMatchers` method. */
|
||||
class SpringSecurityMatchersCall extends MethodCall {
|
||||
SpringSecurityMatchersCall() {
|
||||
this.getMethod().hasName("securityMatchers") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `AuthorizedUrl.permitAll` method. */
|
||||
class SpringPermitAllCall extends MethodCall {
|
||||
SpringPermitAllCall() {
|
||||
this.getMethod().hasName("permitAll") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringAuthorizedUrl
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `AbstractRequestMatcherRegistry.anyRequest` method. */
|
||||
class SpringAnyRequestCall extends MethodCall {
|
||||
SpringAnyRequestCall() {
|
||||
this.getMethod().hasName("anyRequest") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringAbstractRequestMatcherRegistry
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/** Provides classes and predicates to reason about exposed actuators in Spring Boot. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.frameworks.spring.SpringSecurity
|
||||
private import semmle.code.java.frameworks.spring.SpringBoot
|
||||
|
||||
/**
|
||||
* A call to an `HttpSecurity` matcher method with argument
|
||||
* `EndpointRequest.toAnyEndpoint()`.
|
||||
*/
|
||||
private class HttpSecurityMatcherCall extends MethodCall {
|
||||
HttpSecurityMatcherCall() {
|
||||
(
|
||||
this instanceof SpringRequestMatcherCall or
|
||||
this instanceof SpringSecurityMatcherCall
|
||||
) and
|
||||
this.getArgument(0) instanceof SpringToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to an `HttpSecurity` matchers method with lambda
|
||||
* argument `EndpointRequest.toAnyEndpoint()`.
|
||||
*/
|
||||
private class HttpSecurityMatchersCall extends MethodCall {
|
||||
HttpSecurityMatchersCall() {
|
||||
(
|
||||
this instanceof SpringRequestMatchersCall or
|
||||
this instanceof SpringSecurityMatchersCall
|
||||
) and
|
||||
this.getArgument(0).(LambdaExpr).getExprBody() instanceof SpringToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to an `AbstractRequestMatcherRegistry.requestMatchers` method with
|
||||
* argument `EndpointRequest.toAnyEndpoint()`.
|
||||
*/
|
||||
private class RegistryRequestMatchersCall extends MethodCall {
|
||||
RegistryRequestMatchersCall() {
|
||||
this.getMethod().hasName("requestMatchers") and
|
||||
this.getMethod().getDeclaringType() instanceof SpringAbstractRequestMatcherRegistry and
|
||||
this.getAnArgument() instanceof SpringToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to an `HttpSecurity` method that authorizes requests. */
|
||||
private class AuthorizeCall extends MethodCall {
|
||||
AuthorizeCall() {
|
||||
this instanceof SpringAuthorizeRequestsCall or
|
||||
this instanceof SpringAuthorizeHttpRequestsCall
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `permitAllCall` is called on request(s) mapped to actuator endpoint(s). */
|
||||
predicate permitsSpringBootActuators(SpringPermitAllCall permitAllCall) {
|
||||
exists(AuthorizeCall authorizeCall |
|
||||
// .requestMatcher(EndpointRequest).authorizeRequests([...]).[...]
|
||||
authorizeCall.getQualifier() instanceof HttpSecurityMatcherCall
|
||||
or
|
||||
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
|
||||
authorizeCall.getQualifier() instanceof HttpSecurityMatchersCall
|
||||
|
|
||||
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
|
||||
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
|
||||
authorizeCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
|
||||
(
|
||||
permitAllCall.getQualifier() instanceof SpringAnyRequestCall or
|
||||
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
|
||||
)
|
||||
or
|
||||
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
|
||||
// [...].authorizeRequests().anyRequest().permitAll()
|
||||
authorizeCall.getNumArgument() = 0 and
|
||||
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
|
||||
registryRequestMatchersCall.getQualifier() = authorizeCall and
|
||||
permitAllCall.getQualifier() = registryRequestMatchersCall
|
||||
)
|
||||
or
|
||||
exists(SpringAnyRequestCall anyRequestCall |
|
||||
anyRequestCall.getQualifier() = authorizeCall and
|
||||
permitAllCall.getQualifier() = anyRequestCall
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(AuthorizeCall authorizeCall |
|
||||
// http.authorizeRequests([...]).[...]
|
||||
authorizeCall.getQualifier() instanceof VarAccess
|
||||
|
|
||||
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
|
||||
authorizeCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
|
||||
permitAllCall.getQualifier() instanceof RegistryRequestMatchersCall
|
||||
or
|
||||
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
|
||||
authorizeCall.getNumArgument() = 0 and
|
||||
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
|
||||
registryRequestMatchersCall.getQualifier() = authorizeCall and
|
||||
permitAllCall.getQualifier() = registryRequestMatchersCall
|
||||
)
|
||||
or
|
||||
exists(Variable v, HttpSecurityMatcherCall matcherCall |
|
||||
// http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
// http.authorizeRequests([...].permitAll())
|
||||
v.getAnAccess() = authorizeCall.getQualifier() and
|
||||
v.getAnAccess() = matcherCall.getQualifier() and
|
||||
authorizeCall.getArgument(0).(LambdaExpr).getExprBody() = permitAllCall and
|
||||
permitAllCall.getQualifier() instanceof SpringAnyRequestCall
|
||||
)
|
||||
)
|
||||
}
|
||||
25
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.java
Normal file
25
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.java
Normal file
@@ -0,0 +1,25 @@
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class CustomSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// BAD: Unauthenticated access to Spring Boot actuator endpoints is allowed
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class CustomSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// GOOD: only users with ENDPOINT_ADMIN role are allowed to access the actuator endpoints
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
36
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.qhelp
Normal file
36
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.qhelp
Normal file
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Spring Boot includes features called actuators that let you monitor and interact with your
|
||||
web application. Exposing unprotected actuator endpoints can lead to information disclosure or
|
||||
even to remote code execution.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Since actuator endpoints may contain sensitive information, carefully consider when to expose them,
|
||||
and secure them as you would any sensitive URL. Actuators are secured by default when using Spring
|
||||
Security without a custom configuration. If you wish to define a custom security configuration,
|
||||
consider only allowing users with certain roles to access these endpoints.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the first example, the custom security configuration allows unauthenticated access to all
|
||||
actuator endpoints. This may lead to sensitive information disclosure and should be avoided.</p>
|
||||
|
||||
<p>In the second example, only users with <code>ENDPOINT_ADMIN</code> role are allowed to access
|
||||
the actuator endpoints.</p>
|
||||
|
||||
<sample src="SpringBootActuators.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Spring Boot Reference Documentation:
|
||||
<a href="https://docs.spring.io/spring-boot/reference/actuator/endpoints.html">Endpoints</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
20
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.ql
Normal file
20
java/ql/src/Security/CWE/CWE-200/SpringBootActuators.ql
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name Exposed Spring Boot actuators
|
||||
* @description Exposing Spring Boot actuators may lead to information leak from the internal application,
|
||||
* or even to remote code execution.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.5
|
||||
* @precision high
|
||||
* @id java/spring-boot-exposed-actuators
|
||||
* @tags security
|
||||
* external/cwe/cwe-200
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.SpringSecurity
|
||||
import semmle.code.java.security.SpringBootActuatorsQuery
|
||||
|
||||
from SpringPermitAllCall permitAllCall
|
||||
where permitsSpringBootActuators(permitAllCall)
|
||||
select permitAllCall, "Unauthenticated access to Spring Boot actuator is allowed."
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* The query `java/spring-boot-exposed-actuators` has been promoted from experimental to the main query pack. Its results will now appear by default, and the query itself will be removed from the [CodeQL Community Packs](https://github.com/GitHubSecurityLab/CodeQL-Community-Packs). This query was originally submitted as an experimental query [by @ggolawski](https://github.com/github/codeql/pull/2901).
|
||||
@@ -1,22 +0,0 @@
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class SpringBootActuators extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// BAD: Unauthenticated access to Spring Boot actuator endpoints is allowed
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
|
||||
requests.anyRequest().permitAll());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// GOOD: only users with ENDPOINT_ADMIN role are allowed to access the actuator endpoints
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
|
||||
requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
|
||||
http.httpBasic();
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Spring Boot includes a number of additional features called actuators that let you monitor
|
||||
and interact with your web application. Exposing unprotected actuator endpoints via JXM or HTTP
|
||||
can, however, lead to information disclosure or even to remote code execution vulnerability.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Since actuator endpoints may contain sensitive information, careful consideration should be
|
||||
given about when to expose them. You should take care to secure exposed HTTP endpoints in the same
|
||||
way that you would any other sensitive URL. If Spring Security is present, endpoints are secured by
|
||||
default using Spring Security’s content-negotiation strategy. If you wish to configure custom
|
||||
security for HTTP endpoints, for example, only allow users with a certain role to access them,
|
||||
Spring Boot provides some convenient <code>RequestMatcher</code> objects that can be used in
|
||||
combination with Spring Security.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the first example, the custom security configuration allows unauthenticated access to all
|
||||
actuator endpoints. This may lead to sensitive information disclosure and should be avoided.</p>
|
||||
<p>In the second example, only users with <code>ENDPOINT_ADMIN</code> role are allowed to access
|
||||
the actuator endpoints.</p>
|
||||
|
||||
<sample src="SpringBootActuators.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Spring Boot documentation:
|
||||
<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html">Actuators</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.veracode.com/blog/research/exploiting-spring-boot-actuators">Exploiting Spring Boot Actuators</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @name Exposed Spring Boot actuators
|
||||
* @description Exposing Spring Boot actuators may lead to internal application's information leak
|
||||
* or even to remote code execution.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/spring-boot-exposed-actuators
|
||||
* @tags security
|
||||
* experimental
|
||||
* external/cwe/cwe-16
|
||||
*/
|
||||
|
||||
import java
|
||||
deprecated import SpringBootActuators
|
||||
|
||||
deprecated query predicate problems(PermitAllCall permitAllCall, string message) {
|
||||
permitAllCall.permitsSpringBootActuators() and
|
||||
message = "Unauthenticated access to Spring Boot actuator is allowed."
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
deprecated module;
|
||||
|
||||
import java
|
||||
|
||||
/** The class `org.springframework.security.config.annotation.web.builders.HttpSecurity`. */
|
||||
class TypeHttpSecurity extends Class {
|
||||
TypeHttpSecurity() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web.builders",
|
||||
"HttpSecurity")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class
|
||||
* `org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer`.
|
||||
*/
|
||||
class TypeAuthorizedUrl extends Class {
|
||||
TypeAuthorizedUrl() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web.configurers",
|
||||
"ExpressionUrlAuthorizationConfigurer<HttpSecurity>$AuthorizedUrl<>")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
|
||||
*/
|
||||
class TypeAbstractRequestMatcherRegistry extends Class {
|
||||
TypeAbstractRequestMatcherRegistry() {
|
||||
this.hasQualifiedName("org.springframework.security.config.annotation.web",
|
||||
"AbstractRequestMatcherRegistry<AuthorizedUrl<>>")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest`.
|
||||
*/
|
||||
class TypeEndpointRequest extends Class {
|
||||
TypeEndpointRequest() {
|
||||
this.hasQualifiedName("org.springframework.boot.actuate.autoconfigure.security.servlet",
|
||||
"EndpointRequest")
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `EndpointRequest.toAnyEndpoint` method. */
|
||||
class ToAnyEndpointCall extends MethodCall {
|
||||
ToAnyEndpointCall() {
|
||||
this.getMethod().hasName("toAnyEndpoint") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeEndpointRequest
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `HttpSecurity.requestMatcher` method with argument `RequestMatcher.toAnyEndpoint()`.
|
||||
*/
|
||||
class RequestMatcherCall extends MethodCall {
|
||||
RequestMatcherCall() {
|
||||
this.getMethod().hasName("requestMatcher") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
|
||||
this.getArgument(0) instanceof ToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `HttpSecurity.requestMatchers` method with lambda argument
|
||||
* `RequestMatcher.toAnyEndpoint()`.
|
||||
*/
|
||||
class RequestMatchersCall extends MethodCall {
|
||||
RequestMatchersCall() {
|
||||
this.getMethod().hasName("requestMatchers") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity and
|
||||
this.getArgument(0).(LambdaExpr).getExprBody() instanceof ToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `HttpSecurity.authorizeRequests` method. */
|
||||
class AuthorizeRequestsCall extends MethodCall {
|
||||
AuthorizeRequestsCall() {
|
||||
this.getMethod().hasName("authorizeRequests") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeHttpSecurity
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `AuthorizedUrl.permitAll` method. */
|
||||
class PermitAllCall extends MethodCall {
|
||||
PermitAllCall() {
|
||||
this.getMethod().hasName("permitAll") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeAuthorizedUrl
|
||||
}
|
||||
|
||||
/** Holds if `permitAll` is called on request(s) mapped to actuator endpoint(s). */
|
||||
predicate permitsSpringBootActuators() {
|
||||
exists(AuthorizeRequestsCall authorizeRequestsCall |
|
||||
// .requestMatcher(EndpointRequest).authorizeRequests([...]).[...]
|
||||
authorizeRequestsCall.getQualifier() instanceof RequestMatcherCall
|
||||
or
|
||||
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
|
||||
authorizeRequestsCall.getQualifier() instanceof RequestMatchersCall
|
||||
|
|
||||
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
|
||||
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
|
||||
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = this and
|
||||
(
|
||||
this.getQualifier() instanceof AnyRequestCall or
|
||||
this.getQualifier() instanceof RegistryRequestMatchersCall
|
||||
)
|
||||
or
|
||||
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
|
||||
// [...].authorizeRequests().anyRequest().permitAll()
|
||||
authorizeRequestsCall.getNumArgument() = 0 and
|
||||
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
|
||||
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
|
||||
this.getQualifier() = registryRequestMatchersCall
|
||||
)
|
||||
or
|
||||
exists(AnyRequestCall anyRequestCall |
|
||||
anyRequestCall.getQualifier() = authorizeRequestsCall and
|
||||
this.getQualifier() = anyRequestCall
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(AuthorizeRequestsCall authorizeRequestsCall |
|
||||
// http.authorizeRequests([...]).[...]
|
||||
authorizeRequestsCall.getQualifier() instanceof VarAccess
|
||||
|
|
||||
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
|
||||
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = this and
|
||||
this.getQualifier() instanceof RegistryRequestMatchersCall
|
||||
or
|
||||
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
|
||||
authorizeRequestsCall.getNumArgument() = 0 and
|
||||
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
|
||||
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
|
||||
this.getQualifier() = registryRequestMatchersCall
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `AbstractRequestMatcherRegistry.anyRequest` method. */
|
||||
class AnyRequestCall extends MethodCall {
|
||||
AnyRequestCall() {
|
||||
this.getMethod().hasName("anyRequest") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `AbstractRequestMatcherRegistry.requestMatchers` method with an argument
|
||||
* `RequestMatcher.toAnyEndpoint()`.
|
||||
*/
|
||||
class RegistryRequestMatchersCall extends MethodCall {
|
||||
RegistryRequestMatchersCall() {
|
||||
this.getMethod().hasName("requestMatchers") and
|
||||
this.getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry and
|
||||
this.getAnArgument() instanceof ToAnyEndpointCall
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
| SpringBootActuators.java:6:88:6:120 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:10:5:10:137 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:14:5:14:149 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:18:5:18:101 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:22:5:22:89 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:26:40:26:108 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
| SpringBootActuators.java:30:5:30:113 | permitAll(...) | Unauthenticated access to Spring Boot actuator is allowed. |
|
||||
@@ -1,104 +0,0 @@
|
||||
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
public class SpringBootActuators {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests(requests -> requests.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configure2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll();
|
||||
}
|
||||
|
||||
protected void configure3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll();
|
||||
}
|
||||
|
||||
protected void configure4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configure5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll();
|
||||
}
|
||||
|
||||
protected void configure6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll());
|
||||
}
|
||||
|
||||
protected void configure7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOk1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOk2(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOk3(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOk4(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(authz -> authz.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeRequests(requests -> requests.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health")).authorizeRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.to("health", "info")).permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests(requests -> requests.anyRequest());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()));
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest();
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE/CWE-016/SpringBootActuators.ql
|
||||
@@ -0,0 +1,281 @@
|
||||
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
public class SpringBootActuatorsTest {
|
||||
// Spring security version 5.2.3 used `authorizeRequests` and `requestMatcher(s)`
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configureOk1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOk2(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOk3(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOk4(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(authz -> authz.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeRequests(requests -> requests.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health")).authorizeRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.to("health", "info")).permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll1(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests(requests -> requests.anyRequest());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll2(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll3(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll4(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll5(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll6(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()));
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll7(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeRequests().anyRequest();
|
||||
}
|
||||
|
||||
// Spring security version 5.5.0 introduced `authorizeHttpRequests`
|
||||
protected void configure_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure2_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure3_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure4_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure5_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure6_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure7_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configureOk3_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOk4_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints1_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests(requests -> requests.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints2_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints3_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints4_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints5_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints6_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.to("health", "info")).permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints7_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll1_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll2_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll3_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll4_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll5_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll6_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests(requests -> requests.requestMatchers(EndpointRequest.toAnyEndpoint()));
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll7_authorizeHttpRequests(HttpSecurity http) throws Exception {
|
||||
http.requestMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
|
||||
}
|
||||
|
||||
// Spring security version 5.8.0 introduced `securityMatcher(s)`
|
||||
protected void configure_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure2_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure3_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure4_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configure7_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest().permitAll(); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
protected void configureOk1_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOk2_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints1_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests(requests -> requests.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints2_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.to("health")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints3_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().requestMatchers(EndpointRequest.to("health", "info")).permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints4_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkSafeEndpoints7_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.to("health", "info")).authorizeHttpRequests().anyRequest().permitAll();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll1_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests(requests -> requests.anyRequest());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll2_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll3_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().requestMatchers(EndpointRequest.toAnyEndpoint());
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll4_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
|
||||
}
|
||||
|
||||
protected void configureOkNoPermitAll7_securityMatchers(HttpSecurity http) throws Exception {
|
||||
http.securityMatchers(matcher -> EndpointRequest.toAnyEndpoint()).authorizeHttpRequests().anyRequest();
|
||||
}
|
||||
|
||||
// QHelp Bad example
|
||||
public void securityFilterChain1(HttpSecurity http) throws Exception {
|
||||
// BAD: Unauthenticated access to Spring Boot actuator endpoints is allowed
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll()); // $ hasExposedSpringBootActuator
|
||||
}
|
||||
|
||||
// QHelp Good example
|
||||
public void securityFilterChain2(HttpSecurity http) throws Exception {
|
||||
// GOOD: only users with ENDPOINT_ADMIN role are allowed to access the actuator endpoints
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import java
|
||||
import semmle.code.java.frameworks.spring.SpringSecurity
|
||||
import semmle.code.java.security.SpringBootActuatorsQuery
|
||||
import utils.test.InlineExpectationsTest
|
||||
|
||||
module SpringBootActuatorsTest implements TestSig {
|
||||
string getARelevantTag() { result = "hasExposedSpringBootActuator" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasExposedSpringBootActuator" and
|
||||
exists(SpringPermitAllCall permitAllCall | permitsSpringBootActuators(permitAllCall) |
|
||||
permitAllCall.getLocation() = location and
|
||||
element = permitAllCall.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<SpringBootActuatorsTest>
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../../stubs/springframework-5.3.8
|
||||
@@ -9,6 +9,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
|
||||
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
|
||||
@@ -18,6 +19,14 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpSecurity securityMatcher(RequestMatcher requestMatcher) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpSecurity securityMatcher(String... patterns) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpSecurity authorizeRequests(
|
||||
Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer)
|
||||
throws Exception {
|
||||
@@ -29,6 +38,17 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSecurity authorizeHttpRequests(
|
||||
Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer)
|
||||
throws Exception {
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry authorizeHttpRequests()
|
||||
throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSecurity requestMatchers(Customizer<RequestMatcherConfigurer> requestMatcherCustomizer) {
|
||||
return this;
|
||||
}
|
||||
@@ -37,6 +57,14 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpSecurity securityMatchers(Customizer<RequestMatcherConfigurer> requestMatcherCustomizer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestMatcherConfigurer securityMatchers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CsrfConfigurer<HttpSecurity> csrf() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
|
||||
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractHttpConfigurer<AuthorizeHttpRequestsConfigurer<H>, H> {
|
||||
|
||||
public final class AuthorizationManagerRequestMatcherRegistry extends
|
||||
AbstractRequestMatcherRegistry<AuthorizedUrl> {
|
||||
}
|
||||
|
||||
public class AuthorizedUrl {
|
||||
public AuthorizationManagerRequestMatcherRegistry permitAll() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,9 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
public ExpressionInterceptUrlRegistry permitAll() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ExpressionInterceptUrlRegistry hasRole(String role) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user