@@ -7,41 +7,33 @@ private import semmle.code.configfiles.ConfigFiles
7
7
private import semmle.code.xml.MavenPom
8
8
9
9
/** The parent node of the `org.springframework.boot` group. */
10
- class SpringBootParent extends Parent {
10
+ private class SpringBootParent extends Parent {
11
11
SpringBootParent ( ) { this .getGroup ( ) .getValue ( ) = "org.springframework.boot" }
12
12
}
13
13
14
- /** Class of Spring Boot dependencies. */
14
+ // TODO: private once done with version string debugging in alert msg.
15
+ /** A `Pom` with a Spring Boot parent node. */
15
16
class SpringBootPom extends Pom {
16
17
SpringBootPom ( ) { this .getParentElement ( ) instanceof SpringBootParent }
17
18
18
- /** Holds if the Spring Boot Actuator module `spring-boot-starter-actuator` is used in the project. */
19
- predicate isSpringBootActuatorUsed ( ) {
20
- this .getADependency ( ) .getArtifact ( ) .getValue ( ) = "spring-boot-starter-actuator"
21
- }
22
-
23
- /**
24
- * Holds if the Spring Boot Security module is used in the project, which brings in other security
25
- * related libraries.
26
- */
19
+ /** Holds if the Spring Boot Security module is used in the project. */
27
20
predicate isSpringBootSecurityUsed ( ) {
28
21
this .getADependency ( ) .getArtifact ( ) .getValue ( ) = "spring-boot-starter-security"
29
22
}
30
23
}
31
24
32
- /** The properties file `application.properties`. */
33
- class ApplicationPropertiesFile extends File {
34
- ApplicationPropertiesFile ( ) { this .getBaseName ( ) = "application.properties" }
35
- }
36
-
37
- /** A name-value pair stored in an `application.properties` file. */
38
- class ApplicationPropertiesConfigPair extends ConfigPair {
39
- ApplicationPropertiesConfigPair ( ) { this .getFile ( ) instanceof ApplicationPropertiesFile }
25
+ /** A dependency with artifactId `spring-boot-starter-actuator`. */
26
+ class SpringBootStarterActuatorDependency extends Dependency {
27
+ SpringBootStarterActuatorDependency ( ) {
28
+ this .getArtifact ( ) .getValue ( ) = "spring-boot-starter-actuator"
29
+ }
40
30
}
41
31
42
- /** The configuration property `management.security.enabled`. */
43
- class ManagementSecurityConfig extends ApplicationPropertiesConfigPair {
44
- ManagementSecurityConfig ( ) { this .getNameElement ( ) .getName ( ) = "management.security.enabled" }
32
+ /** The Spring Boot configuration property `management.security.enabled`. */
33
+ private class ManagementSecurityEnabledProperty extends JavaProperty {
34
+ ManagementSecurityEnabledProperty ( ) {
35
+ this .getNameElement ( ) .getName ( ) = "management.security.enabled"
36
+ }
45
37
46
38
/** Gets the whitespace-trimmed value of this property. */
47
39
string getValue ( ) { result = this .getValueElement ( ) .getValue ( ) .trim ( ) }
@@ -50,9 +42,9 @@ class ManagementSecurityConfig extends ApplicationPropertiesConfigPair {
50
42
predicate hasSecurityDisabled ( ) { this .getValue ( ) = "false" }
51
43
}
52
44
53
- /** The configuration property `management.endpoints.web.exposure.include`. */
54
- class ManagementEndPointInclude extends ApplicationPropertiesConfigPair {
55
- ManagementEndPointInclude ( ) {
45
+ /** The Spring Boot configuration property `management.endpoints.web.exposure.include`. */
46
+ private class ManagementEndpointsIncludeProperty extends JavaProperty {
47
+ ManagementEndpointsIncludeProperty ( ) {
56
48
this .getNameElement ( ) .getName ( ) = "management.endpoints.web.exposure.include"
57
49
}
58
50
@@ -62,13 +54,13 @@ class ManagementEndPointInclude extends ApplicationPropertiesConfigPair {
62
54
63
55
private newtype TOption =
64
56
TNone ( ) or
65
- TSome ( ApplicationPropertiesConfigPair ap )
57
+ TSome ( JavaProperty jp )
66
58
67
59
/**
68
60
* An option type that is either a singleton `None` or a `Some` wrapping
69
- * the `ApplicationPropertiesConfigPair ` type.
61
+ * the `JavaProperty ` type.
70
62
*/
71
- class ApplicationPropertiesOption extends TOption {
63
+ class JavaPropertyOption extends TOption {
72
64
/** Gets a textual representation of this element. */
73
65
string toString ( ) {
74
66
this = TNone ( ) and result = "(none)"
@@ -80,48 +72,50 @@ class ApplicationPropertiesOption extends TOption {
80
72
Location getLocation ( ) { result = this .asSome ( ) .getLocation ( ) }
81
73
82
74
/** Gets the wrapped element, if any. */
83
- ApplicationPropertiesConfigPair asSome ( ) { this = TSome ( result ) }
75
+ JavaProperty asSome ( ) { this = TSome ( result ) }
84
76
85
77
/** Holds if this option is the singleton `None`. */
86
78
predicate isNone ( ) { this = TNone ( ) }
87
79
}
88
80
89
81
/**
90
- * Holds if `ApplicationProperties` ap of a repository managed by `SpringBootPom` pom
91
- * has a vulnerable configuration of Spring Boot Actuator management endpoints.
82
+ * Holds if `JavaPropertyOption` jpOption of a repository using `SpringBootStarterActuatorDependency`
83
+ * d exposes sensitive Spring Boot Actuator endpoints.
92
84
*/
93
- predicate hasConfidentialEndPointExposed ( SpringBootPom pom , ApplicationPropertiesOption apOption ) {
94
- pom .isSpringBootActuatorUsed ( ) and
95
- not pom .isSpringBootSecurityUsed ( ) and
96
- exists ( ApplicationPropertiesFile apFile |
97
- apFile
85
+ predicate exposesSensitiveEndpoint (
86
+ SpringBootStarterActuatorDependency d , JavaPropertyOption jpOption
87
+ ) {
88
+ exists ( PropertiesFile propFile , SpringBootPom pom |
89
+ d = pom .getADependency ( ) and
90
+ not pom .isSpringBootSecurityUsed ( ) and
91
+ propFile
98
92
.getParentContainer ( )
99
93
.getAbsolutePath ( )
100
94
.matches ( pom .getFile ( ) .getParentContainer ( ) .getAbsolutePath ( ) + "%" ) and // in the same sub-directory
101
95
exists ( string springBootVersion |
102
96
springBootVersion = pom .getParentElement ( ) .getVersionString ( )
103
97
|
104
98
springBootVersion .regexpMatch ( "1\\.[0-4].*" ) and // version 1.0, 1.1, ..., 1.4
105
- not exists ( ManagementSecurityConfig me | me .getFile ( ) = apFile ) and
106
- apOption .isNone ( )
99
+ not exists ( ManagementSecurityEnabledProperty ep | ep .getFile ( ) = propFile ) and
100
+ jpOption .isNone ( )
107
101
or
108
102
springBootVersion .regexpMatch ( "1\\.[0-5].*" ) and // version 1.0, 1.1, ..., 1.5
109
- exists ( ManagementSecurityConfig me |
110
- me .hasSecurityDisabled ( ) and me .getFile ( ) = apFile and me = apOption .asSome ( )
103
+ exists ( ManagementSecurityEnabledProperty ep |
104
+ ep .hasSecurityDisabled ( ) and ep .getFile ( ) = propFile and ep = jpOption .asSome ( )
111
105
)
112
106
or
113
107
springBootVersion .matches ( [ "2.%" , "3.%" ] ) and //version 2.x and 3.x
114
- exists ( ManagementEndPointInclude mi |
115
- mi .getFile ( ) = apFile and
116
- mi = apOption .asSome ( ) and
108
+ exists ( ManagementEndpointsIncludeProperty ip |
109
+ ip .getFile ( ) = propFile and
110
+ ip = jpOption .asSome ( ) and
117
111
(
118
- mi .getValue ( ) = "*" // all endpoints are enabled
112
+ ip .getValue ( ) = "*" // all endpoints are exposed
119
113
or
120
- mi .getValue ( )
114
+ ip .getValue ( )
121
115
.matches ( [
122
116
"%dump%" , "%trace%" , "%logfile%" , "%shutdown%" , "%startup%" , "%mappings%" ,
123
117
"%env%" , "%beans%" , "%sessions%"
124
- ] ) // confidential endpoints to check although all endpoints apart from '/health' are considered sensitive by Spring
118
+ ] ) // sensitive endpoints to check although all endpoints apart from '/health' are considered sensitive by Spring
125
119
)
126
120
)
127
121
)
0 commit comments