-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathInsecureSpringActuatorConfig.ql
More file actions
118 lines (103 loc) · 4.69 KB
/
InsecureSpringActuatorConfig.ql
File metadata and controls
118 lines (103 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* @name Insecure Spring Boot Actuator Configuration
* @description Exposed Spring Boot Actuator through configuration files without declarative or procedural
* security enforcement leads to information leak or even remote code execution.
* @kind problem
* @problem.severity error
* @precision high
* @id githubsecuritylab/java/insecure-spring-actuator-config
* @tags security
* external/cwe/cwe-016
*/
/*
* Note this query requires properties files to be indexed before it can produce results.
* If creating your own database with the CodeQL CLI, you should run
* `codeql database index-files --language=properties ...`
* If using lgtm.com, you should add `properties_files: true` to the index block of your
* lgtm.yml file (see https://lgtm.com/help/lgtm/java-extraction)
*/
import java
import semmle.code.configfiles.ConfigFiles
import semmle.code.xml.MavenPom
/** The parent node of the `org.springframework.boot` group. */
class SpringBootParent extends Parent {
SpringBootParent() { this.getGroup().getValue() = "org.springframework.boot" }
}
/** Class of Spring Boot dependencies. */
class SpringBootPom extends Pom {
SpringBootPom() { this.getParentElement() instanceof SpringBootParent }
/** Holds if the Spring Boot Actuator module `spring-boot-starter-actuator` is used in the project. */
predicate isSpringBootActuatorUsed() {
this.getADependency().getArtifact().getValue() = "spring-boot-starter-actuator"
}
/**
* Holds if the Spring Boot Security module is used in the project, which brings in other security
* related libraries.
*/
predicate isSpringBootSecurityUsed() {
this.getADependency().getArtifact().getValue() = "spring-boot-starter-security"
}
}
/** The properties file `application.properties`. */
class ApplicationProperties extends ConfigPair {
ApplicationProperties() { this.getFile().getBaseName() = "application.properties" }
}
/** The configuration property `management.security.enabled`. */
class ManagementSecurityConfig extends ApplicationProperties {
ManagementSecurityConfig() { this.getNameElement().getName() = "management.security.enabled" }
/** Gets the whitespace-trimmed value of this property. */
string getValue() { result = this.getValueElement().getValue().trim() }
/** Holds if `management.security.enabled` is set to `false`. */
predicate hasSecurityDisabled() { this.getValue() = "false" }
/** Holds if `management.security.enabled` is set to `true`. */
predicate hasSecurityEnabled() { this.getValue() = "true" }
}
/** The configuration property `management.endpoints.web.exposure.include`. */
class ManagementEndPointInclude extends ApplicationProperties {
ManagementEndPointInclude() {
this.getNameElement().getName() = "management.endpoints.web.exposure.include"
}
/** Gets the whitespace-trimmed value of this property. */
string getValue() { result = this.getValueElement().getValue().trim() }
}
/**
* Holds if `ApplicationProperties` ap of a repository managed by `SpringBootPom` pom
* has a vulnerable configuration of Spring Boot Actuator management endpoints.
*/
predicate hasConfidentialEndPointExposed(SpringBootPom pom, ApplicationProperties ap) {
pom.isSpringBootActuatorUsed() and
not pom.isSpringBootSecurityUsed() and
ap.getFile()
.getParentContainer()
.getAbsolutePath()
.matches(pom.getFile().getParentContainer().getAbsolutePath() + "%") and // in the same sub-directory
exists(string springBootVersion | springBootVersion = pom.getParentElement().getVersionString() |
springBootVersion.regexpMatch("1\\.[0-4].*") and // version 1.0, 1.1, ..., 1.4
not exists(ManagementSecurityConfig me |
me.hasSecurityEnabled() and me.getFile() = ap.getFile()
)
or
springBootVersion.matches("1.5%") and // version 1.5
exists(ManagementSecurityConfig me | me.hasSecurityDisabled() and me.getFile() = ap.getFile())
or
springBootVersion.matches("2.%") and //version 2.x
exists(ManagementEndPointInclude mi |
mi.getFile() = ap.getFile() and
(
mi.getValue() = "*" // all endpoints are enabled
or
mi.getValue()
.matches([
"%dump%", "%trace%", "%logfile%", "%shutdown%", "%startup%", "%mappings%", "%env%",
"%beans%", "%sessions%"
]) // confidential endpoints to check although all endpoints apart from '/health' and '/info' are considered sensitive by Spring
)
)
)
}
from SpringBootPom pom, ApplicationProperties ap, Dependency d
where
hasConfidentialEndPointExposed(pom, ap) and
d = pom.getADependency() and
d.getArtifact().getValue() = "spring-boot-starter-actuator"
select d, "Insecure configuration of Spring Boot Actuator exposes sensitive endpoints."