Skip to content

Commit 0129b2a

Browse files
committed
Java: Add source code for experimental queries as is.
1 parent 046dfe7 commit 0129b2a

File tree

235 files changed

+11282
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

235 files changed

+11282
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
<overview>
4+
<p>Spring Boot is a popular framework that facilitates the development of stand-alone applications
5+
and micro services. Spring Boot Actuator helps to expose production-ready support features against
6+
Spring Boot applications.</p>
7+
8+
<p>Endpoints of Spring Boot Actuator allow to monitor and interact with a Spring Boot application.
9+
Exposing unprotected actuator endpoints through configuration files can lead to information disclosure
10+
or even remote code execution vulnerability.</p>
11+
12+
<p>Rather than programmatically permitting endpoint requests or enforcing access control, frequently
13+
developers simply leave management endpoints publicly accessible in the application configuration file
14+
<code>application.properties</code> without enforcing access control through Spring Security.</p>
15+
</overview>
16+
17+
<recommendation>
18+
<p>Declare the Spring Boot Starter Security module in XML configuration or programmatically enforce
19+
security checks on management endpoints using Spring Security. Otherwise accessing management endpoints
20+
on a different HTTP port other than the port that the web application is listening on also helps to
21+
improve the security.</p>
22+
</recommendation>
23+
24+
<example>
25+
<p>The following examples show both 'BAD' and 'GOOD' configurations. In the 'BAD' configuration,
26+
no security module is declared and sensitive management endpoints are exposed. In the 'GOOD' configuration,
27+
security is enforced and only endpoints requiring exposure are exposed.</p>
28+
<sample src="pom_good.xml" />
29+
<sample src="pom_bad.xml" />
30+
<sample src="application.properties" />
31+
</example>
32+
33+
<references>
34+
<li>
35+
Spring Boot documentation:
36+
<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html">Spring Boot Actuator: Production-ready Features</a>
37+
</li>
38+
<li>
39+
VERACODE Blog:
40+
<a href="https://www.veracode.com/blog/research/exploiting-spring-boot-actuators">Exploiting Spring Boot Actuators</a>
41+
</li>
42+
<li>
43+
HackerOne Report:
44+
<a href="https://hackerone.com/reports/862589">Spring Actuator endpoints publicly available, leading to account takeover</a>
45+
</li>
46+
</references>
47+
</qhelp>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* @name Insecure Spring Boot Actuator Configuration
3+
* @description Exposed Spring Boot Actuator through configuration files without declarative or procedural
4+
* security enforcement leads to information leak or even remote code execution.
5+
* @kind problem
6+
* @problem.severity error
7+
* @precision high
8+
* @id java/insecure-spring-actuator-config
9+
* @tags security
10+
* experimental
11+
* external/cwe/cwe-016
12+
*/
13+
14+
/*
15+
* Note this query requires properties files to be indexed before it can produce results.
16+
* If creating your own database with the CodeQL CLI, you should run
17+
* `codeql database index-files --language=properties ...`
18+
* If using lgtm.com, you should add `properties_files: true` to the index block of your
19+
* lgtm.yml file (see https://lgtm.com/help/lgtm/java-extraction)
20+
*/
21+
22+
import java
23+
import semmle.code.configfiles.ConfigFiles
24+
import semmle.code.xml.MavenPom
25+
26+
/** The parent node of the `org.springframework.boot` group. */
27+
class SpringBootParent extends Parent {
28+
SpringBootParent() { this.getGroup().getValue() = "org.springframework.boot" }
29+
}
30+
31+
/** Class of Spring Boot dependencies. */
32+
class SpringBootPom extends Pom {
33+
SpringBootPom() { this.getParentElement() instanceof SpringBootParent }
34+
35+
/** Holds if the Spring Boot Actuator module `spring-boot-starter-actuator` is used in the project. */
36+
predicate isSpringBootActuatorUsed() {
37+
this.getADependency().getArtifact().getValue() = "spring-boot-starter-actuator"
38+
}
39+
40+
/**
41+
* Holds if the Spring Boot Security module is used in the project, which brings in other security
42+
* related libraries.
43+
*/
44+
predicate isSpringBootSecurityUsed() {
45+
this.getADependency().getArtifact().getValue() = "spring-boot-starter-security"
46+
}
47+
}
48+
49+
/** The properties file `application.properties`. */
50+
class ApplicationProperties extends ConfigPair {
51+
ApplicationProperties() { this.getFile().getBaseName() = "application.properties" }
52+
}
53+
54+
/** The configuration property `management.security.enabled`. */
55+
class ManagementSecurityConfig extends ApplicationProperties {
56+
ManagementSecurityConfig() { this.getNameElement().getName() = "management.security.enabled" }
57+
58+
/** Gets the whitespace-trimmed value of this property. */
59+
string getValue() { result = this.getValueElement().getValue().trim() }
60+
61+
/** Holds if `management.security.enabled` is set to `false`. */
62+
predicate hasSecurityDisabled() { this.getValue() = "false" }
63+
64+
/** Holds if `management.security.enabled` is set to `true`. */
65+
predicate hasSecurityEnabled() { this.getValue() = "true" }
66+
}
67+
68+
/** The configuration property `management.endpoints.web.exposure.include`. */
69+
class ManagementEndPointInclude extends ApplicationProperties {
70+
ManagementEndPointInclude() {
71+
this.getNameElement().getName() = "management.endpoints.web.exposure.include"
72+
}
73+
74+
/** Gets the whitespace-trimmed value of this property. */
75+
string getValue() { result = this.getValueElement().getValue().trim() }
76+
}
77+
78+
/**
79+
* Holds if `ApplicationProperties` ap of a repository managed by `SpringBootPom` pom
80+
* has a vulnerable configuration of Spring Boot Actuator management endpoints.
81+
*/
82+
predicate hasConfidentialEndPointExposed(SpringBootPom pom, ApplicationProperties ap) {
83+
pom.isSpringBootActuatorUsed() and
84+
not pom.isSpringBootSecurityUsed() and
85+
ap.getFile()
86+
.getParentContainer()
87+
.getAbsolutePath()
88+
.matches(pom.getFile().getParentContainer().getAbsolutePath() + "%") and // in the same sub-directory
89+
exists(string springBootVersion | springBootVersion = pom.getParentElement().getVersionString() |
90+
springBootVersion.regexpMatch("1\\.[0-4].*") and // version 1.0, 1.1, ..., 1.4
91+
not exists(ManagementSecurityConfig me |
92+
me.hasSecurityEnabled() and me.getFile() = ap.getFile()
93+
)
94+
or
95+
springBootVersion.matches("1.5%") and // version 1.5
96+
exists(ManagementSecurityConfig me | me.hasSecurityDisabled() and me.getFile() = ap.getFile())
97+
or
98+
springBootVersion.matches("2.%") and //version 2.x
99+
exists(ManagementEndPointInclude mi |
100+
mi.getFile() = ap.getFile() and
101+
(
102+
mi.getValue() = "*" // all endpoints are enabled
103+
or
104+
mi.getValue()
105+
.matches([
106+
"%dump%", "%trace%", "%logfile%", "%shutdown%", "%startup%", "%mappings%", "%env%",
107+
"%beans%", "%sessions%"
108+
]) // confidential endpoints to check although all endpoints apart from '/health' and '/info' are considered sensitive by Spring
109+
)
110+
)
111+
)
112+
}
113+
114+
from SpringBootPom pom, ApplicationProperties ap, Dependency d
115+
where
116+
hasConfidentialEndPointExposed(pom, ap) and
117+
d = pom.getADependency() and
118+
d.getArtifact().getValue() = "spring-boot-starter-actuator"
119+
select d, "Insecure configuration of Spring Boot Actuator exposes sensitive endpoints."
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@Configuration(proxyBeanMethods = false)
2+
public class SpringBootActuators extends WebSecurityConfigurerAdapter {
3+
4+
@Override
5+
protected void configure(HttpSecurity http) throws Exception {
6+
// BAD: Unauthenticated access to Spring Boot actuator endpoints is allowed
7+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
8+
requests.anyRequest().permitAll());
9+
}
10+
}
11+
12+
@Configuration(proxyBeanMethods = false)
13+
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
14+
15+
@Override
16+
protected void configure(HttpSecurity http) throws Exception {
17+
// GOOD: only users with ENDPOINT_ADMIN role are allowed to access the actuator endpoints
18+
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
19+
requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
20+
http.httpBasic();
21+
}
22+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Spring Boot includes a number of additional features called actuators that let you monitor
7+
and interact with your web application. Exposing unprotected actuator endpoints via JXM or HTTP
8+
can, however, lead to information disclosure or even to remote code execution vulnerability.</p>
9+
</overview>
10+
11+
<recommendation>
12+
<p>Since actuator endpoints may contain sensitive information, careful consideration should be
13+
given about when to expose them. You should take care to secure exposed HTTP endpoints in the same
14+
way that you would any other sensitive URL. If Spring Security is present, endpoints are secured by
15+
default using Spring Security’s content-negotiation strategy. If you wish to configure custom
16+
security for HTTP endpoints, for example, only allow users with a certain role to access them,
17+
Spring Boot provides some convenient <code>RequestMatcher</code> objects that can be used in
18+
combination with Spring Security.</p>
19+
</recommendation>
20+
21+
<example>
22+
<p>In the first example, the custom security configuration allows unauthenticated access to all
23+
actuator endpoints. This may lead to sensitive information disclosure and should be avoided.</p>
24+
<p>In the second example, only users with <code>ENDPOINT_ADMIN</code> role are allowed to access
25+
the actuator endpoints.</p>
26+
27+
<sample src="SpringBootActuators.java" />
28+
</example>
29+
30+
<references>
31+
<li>
32+
Spring Boot documentation:
33+
<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html">Actuators</a>.
34+
</li>
35+
<li>
36+
<a href="https://www.veracode.com/blog/research/exploiting-spring-boot-actuators">Exploiting Spring Boot Actuators</a>
37+
</li>
38+
</references>
39+
</qhelp>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name Exposed Spring Boot actuators
3+
* @description Exposing Spring Boot actuators may lead to internal application's information leak
4+
* or even to remote code execution.
5+
* @kind problem
6+
* @problem.severity error
7+
* @precision high
8+
* @id java/spring-boot-exposed-actuators
9+
* @tags security
10+
* experimental
11+
* external/cwe/cwe-16
12+
*/
13+
14+
import java
15+
import SpringBootActuators
16+
17+
from PermitAllCall permitAllCall
18+
where permitAllCall.permitsSpringBootActuators()
19+
select permitAllCall, "Unauthenticated access to Spring Boot actuator is allowed."

0 commit comments

Comments
 (0)