FlawOpen
● CWE-502 / Unsafe Deserialization

Desserialização insegura: riscos e correção

Riscos do pickle, Java Serialization e PHP unserialize com dados não confiáveis, e como substituí-los ou restringi-los.

💡 Explicação em linguagem simples (ELI5)

Serializar é como enviar pelo correio instruções para montar um modelo. Desserializar segue essas instruções para reconstruir os dados. Alguns formatos também podem indicar classes ou chamar hooks durante a reconstrução; aceitar instruções não confiáveis pode acionar comportamentos que o receptor não pretendia. O impacto depende do formato, runtime, classes disponíveis e contexto da aplicação.

Core Concepts & Key Terms

Serialização / desserialização
Converter dados ou objetos em uma representação para armazenar ou transmitir e depois analisá-los ou reconstruí-los no programa.
Hooks de desserialização
Callbacks como Python __reduce__, Java readObject ou PHP __wakeup / __unserialize que podem rodar ao reconstruir objetos.
Gadget chain
Sequência de comportamentos de bibliotecas já presentes que pode ser encadeada para gerar um efeito não intencional. A disponibilidade depende da aplicação e da versão.
Filtro de desserialização
Política que restringe classes e métricas do grafo ao ler um stream de objetos. Reduz o risco, mas não torna streams nativos não confiáveis uma boa escolha.

How Unsafe Deserialization Can Become an Exploit Chain

Step 1

Bytes não confiáveis chegam ao decodificador

Um cookie, corpo de API, mensagem de fila ou registro contém dados que um atacante pode influenciar.

Step 2

A aplicação chama um formato de objeto nativo

O código passa os bytes a um decodificador como Python pickle, Java ObjectInputStream ou PHP unserialize().

Step 3

A reconstrução aciona comportamento específico do formato

Conforme o formato e as classes acessíveis, construtores, hooks, autoloading ou métodos de biblioteca podem rodar antes da validação da aplicação.

Step 4

O impacto depende do comportamento alcançável

Um gadget ou hook utilizável pode causar efeitos não autorizados; outras entradas podem apenas falhar ou consumir recursos. Execução de código não é automática em todo formato ou aplicação.

Python / Flask: carregamento inseguro de objetos vs. validação de JSON primitivo

PADRÃO VULNERÁVEL
# VULNERABLE: pickle can execute behavior during unpickling.
from flask import Flask, request
import pickle

app = Flask(__name__)

@app.post("/api/session")
def load_session():
    # Never deserialize attacker-controlled bytes with pickle.
    session = pickle.loads(request.get_data())
    return {"user_id": session.user_id}
VALIDAÇÃO MAIS SEGURA
# SAFER: parse JSON primitives, then validate expected shape.
from flask import Flask, abort, request

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024

@app.post("/api/session")
def load_session():
    payload = request.get_json()
    if not isinstance(payload, dict):
        abort(400, "Expected a JSON object")

    user_id = payload.get("user_id")
    if type(user_id) is not int or user_id <= 0:
        abort(400, "Invalid user_id")

    # Resolve authorization and session state server-side.
    return {"user_id": user_id}

Checklist de proteção de engenharia

Para limitar o impacto, JSON ainda exige validação de tamanho e estrutura. Para formatos de objetos legados, não confie em listas de classes como fronteira única; autentique os bytes exatos antes da desserialização e mantenha as chaves protegidas. MAC não cifra os dados nem evita replay.

← Navegar pelo diretório completo de segurança Explorar guias de vulnerabilidades →