| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| /** Provides classes and predicates to reason about Spring Boot actuators exposed in configuration files. */ | ||
| overlay[local?] | ||
| module; | ||
|
|
||
| import java | ||
| private import semmle.code.configfiles.ConfigFiles | ||
| private import semmle.code.xml.MavenPom | ||
|
|
||
| /** The parent node of the `org.springframework.boot` group. */ | ||
| private class SpringBootParent extends Parent { | ||
| SpringBootParent() { this.getGroup().getValue() = "org.springframework.boot" } | ||
| } | ||
|
|
||
| /** A `Pom` with a Spring Boot parent node. */ | ||
| private class SpringBootPom extends Pom { | ||
| SpringBootPom() { this.getParentElement() instanceof SpringBootParent } | ||
|
|
||
| /** Holds if the Spring Boot Security module is used in the project. */ | ||
| predicate isSpringBootSecurityUsed() { | ||
| this.getADependency().getArtifact().getValue() = "spring-boot-starter-security" | ||
| } | ||
| } | ||
|
|
||
| /** A dependency with artifactId `spring-boot-starter-actuator`. */ | ||
| class SpringBootStarterActuatorDependency extends Dependency { | ||
| SpringBootStarterActuatorDependency() { | ||
| this.getArtifact().getValue() = "spring-boot-starter-actuator" | ||
| } | ||
| } | ||
|
|
||
| /** The Spring Boot configuration property `management.security.enabled`. */ | ||
| private class ManagementSecurityEnabledProperty extends JavaProperty { | ||
| ManagementSecurityEnabledProperty() { | ||
| 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" } | ||
| } | ||
|
|
||
| /** | ||
| * The Spring Boot configuration property `management.endpoints.web.exposure.include` | ||
| * or `management.endpoints.web.expose`. | ||
| */ | ||
| private class ManagementEndpointsExposeProperty extends JavaProperty { | ||
| ManagementEndpointsExposeProperty() { | ||
| this.getNameElement().getName() = "management.endpoints.web." + ["exposure.include", "expose"] | ||
| } | ||
|
|
||
| /** Gets the whitespace-trimmed value of this property. */ | ||
| string getValue() { result = this.getValueElement().getValue().trim() } | ||
| } | ||
|
|
||
| private newtype TOption = | ||
| TNone() or | ||
| TSome(JavaProperty jp) | ||
|
|
||
| /** | ||
| * An option type that is either a singleton `None` or a `Some` wrapping | ||
| * the `JavaProperty` type. | ||
| */ | ||
| class JavaPropertyOption extends TOption { | ||
| /** Gets a textual representation of this element. */ | ||
| string toString() { | ||
| this = TNone() and result = "(none)" | ||
| or | ||
| result = this.asSome().toString() | ||
| } | ||
|
|
||
| /** Gets the location of this element. */ | ||
| Location getLocation() { result = this.asSome().getLocation() } | ||
|
|
||
| /** Gets the wrapped element, if any. */ | ||
| JavaProperty asSome() { this = TSome(result) } | ||
|
|
||
| /** Holds if this option is the singleton `None`. */ | ||
| predicate isNone() { this = TNone() } | ||
| } | ||
|
|
||
| /** | ||
| * Holds if `JavaPropertyOption` jpOption of a repository using `SpringBootStarterActuatorDependency` | ||
| * d exposes sensitive Spring Boot Actuator endpoints. | ||
| */ | ||
| predicate exposesSensitiveEndpoint( | ||
| SpringBootStarterActuatorDependency d, JavaPropertyOption jpOption | ||
| ) { | ||
| exists(PropertiesFile propFile, SpringBootPom pom | | ||
| d = pom.getADependency() and | ||
| not pom.isSpringBootSecurityUsed() and | ||
| propFile | ||
| .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(ManagementSecurityEnabledProperty ep | ep.getFile() = propFile) and | ||
| jpOption.isNone() | ||
| or | ||
| springBootVersion.regexpMatch("1\\.[0-5].*") and // version 1.0, 1.1, ..., 1.5 | ||
| exists(ManagementSecurityEnabledProperty ep | | ||
| ep.hasSecurityDisabled() and ep.getFile() = propFile and ep = jpOption.asSome() | ||
| ) | ||
| or | ||
| springBootVersion.matches(["2.%", "3.%"]) and //version 2.x and 3.x | ||
| exists(ManagementEndpointsExposeProperty ep | | ||
| ep.getFile() = propFile and | ||
| ep = jpOption.asSome() and | ||
| ( | ||
| // all endpoints are exposed | ||
| ep.getValue() = "*" | ||
| or | ||
| // version 2.x: exposes health and info only by default | ||
| springBootVersion.matches("2.%") and | ||
| not ep.getValue() = ["health", "info"] | ||
| or | ||
| // version 3.x: exposes health only by default | ||
| springBootVersion.matches("3.%") and | ||
| not ep.getValue() = "health" | ||
| ) | ||
| ) | ||
| ) | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| <!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 through configuration files 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. If you need to expose actuator endpoints, use Spring | ||
| Security, which secures actuators by default, or define a custom security configuration. | ||
| </p> | ||
| </recommendation> | ||
|
|
||
| <example> | ||
| <p>The following examples show <code>application.properties</code> configurations that expose sensitive | ||
| actuator endpoints.</p> | ||
| <sample src="application_bad.properties" /> | ||
|
|
||
| <p>The below configurations ensure that sensitive actuator endpoints are not exposed.</p> | ||
| <sample src="application_good.properties" /> | ||
|
|
||
| <p>To use Spring Security, which secures actuators by default, add the <code>spring-boot-starter-security</code> | ||
| dependency in your Maven <code>pom.xml</code> file.</p> | ||
| <sample src="pom_good.xml" /> | ||
| </example> | ||
|
|
||
| <references> | ||
| <li> | ||
| Spring Boot Reference Documentation: | ||
| <a href="https://docs.spring.io/spring-boot/reference/actuator/endpoints.html">Endpoints</a>. | ||
| </li> | ||
| <li> | ||
| HackerOne Report: | ||
| <a href="https://hackerone.com/reports/862589">Spring Actuator endpoints publicly available, leading to account takeover</a> | ||
| </li> | ||
| </references> | ||
| </qhelp> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /** | ||
| * @name Exposed Spring Boot actuators in configuration file | ||
| * @description Exposing Spring Boot actuators through configuration files 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-config | ||
|
Comment thread
Copy link
Copy Markdown
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityDo we need a @previous-id java/insecure-spring-actuator-config tag as well?
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI don't think we are using @previous-id when promoting experimental queries. Only when porting queries from a different query pack.
Sorry, something went wrong.
michaelnebel and jcogs33 reacted with thumbs up emoji
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality
This was my understanding as well.
Sorry, something went wrong.
michaelnebel reacted with thumbs up emoji
All reactions
|
||
| * @tags security | ||
| * external/cwe/cwe-200 | ||
| */ | ||
|
|
||
| import java | ||
| import semmle.code.xml.MavenPom | ||
| import semmle.code.java.security.SpringBootActuatorsConfigQuery | ||
|
|
||
| from SpringBootStarterActuatorDependency d, JavaPropertyOption jpOption | ||
| where exposesSensitiveEndpoint(d, jpOption) | ||
| select d, "Insecure Spring Boot actuator $@ exposes sensitive endpoints.", jpOption, "configuration" | ||
|
Comment thread
jcogs33 marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # vulnerable configuration (Spring Boot 1.0 - 1.4): exposes endpoints by default | ||
|
|
||
| # vulnerable configuration (Spring Boot 1.5): false value exposes endpoints | ||
| management.security.enabled=false | ||
|
|
||
| # vulnerable configuration (Spring Boot 2.x): exposes all endpoints | ||
| management.endpoints.web.exposure.include=* | ||
|
|
||
| # vulnerable configuration (Spring Boot 3.x): exposes all endpoints | ||
| management.endpoints.web.exposure.include=* |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # safe configuration (Spring Boot 1.0 - 1.4) | ||
| management.security.enabled=true | ||
|
|
||
| # safe configuration (Spring Boot 1.5+) | ||
| management.security.enabled=true | ||
|
|
||
| # safe configuration (Spring Boot 2.x): exposes health and info only by default | ||
| management.endpoints.web.exposure.include=health,info | ||
|
|
||
| # safe configuration (Spring Boot 3.x): exposes health only by default | ||
| management.endpoints.web.exposure.include=health |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| ... | ||
| <dependency> | ||
| <groupId>org.springframework.boot</groupId> | ||
| <artifactId>spring-boot-starter-actuator</artifactId> | ||
| </dependency> | ||
|
|
||
| <!-- GOOD: Enable Spring Security --> | ||
| <dependency> | ||
| <groupId>org.springframework.boot</groupId> | ||
| <artifactId>spring-boot-starter-security</artifactId> | ||
| </dependency> | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: newQuery | ||
| --- | ||
| * The query `java/insecure-spring-actuator-config` has been promoted from experimental to the main query pack as `java/spring-boot-exposed-actuators-config`. Its results will now appear by default. This query detects exposure of Spring Boot actuators through configuration files. It was originally submitted as an experimental query [by @luchua-bc](https://github.com/github/codeql/pull/5384). |
This file was deleted.
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.