Parte: 2 — Criptografía aplicada · Fuente: Serious Cryptography (Aumasson) y Cryptography Engineering (Ferguson/Schneier/Kohno) ⏱️ Duración estimada: 120 min · Nivel: Avanzado
Entender que la mayoría de los sistemas criptográficos no se rompen atacando el algoritmo, sino explotando su implementación. El alumno estudiará dos familias emblemáticas: el ataque de padding oracle (descifrar sin la clave abusando de mensajes de error de padding en CBC) y los ataques de canal lateral por tiempo (deducir secretos midiendo cuánto tarda una operación). Ambos se practican solo en un servicio de laboratorio propio.
⚠️ Nota ética: estos ataques se ejecutan exclusivamente contra un oráculo/servidor montado por ti en tu laboratorio. Aplicarlos a sistemas de terceros sin autorización explícita es ilegal.
Al finalizar, el alumno podrá:
| # | Tema | Por qué importa |
|---|---|---|
| 1 | Ataques a la implementación | Donde ocurren las brechas reales |
| 2 | Padding PKCS#7 y su verificación | Origen del oráculo |
| 3 | Padding oracle paso a paso | Descifrado sin clave |
| 4 | Ataques de timing | Canal lateral temporal |
| 5 | Comparación en tiempo constante | Mitigación clave |
| 6 | AEAD como defensa | Elimina el oráculo |
| 7 | Casos reales (POODLE, Lucky13) | Impacto histórico |
Nadie ha roto AES. Sin embargo, se descifran mensajes protegidos con AES continuamente, y la razón es que un sistema criptográfico no es solo un algoritmo: es también el código que lo ejecuta, los mensajes de error que devuelve y el tiempo que tarda en devolverlos. Un canal lateral es cualquier información que se filtra por esos aspectos no previstos en el modelo matemático —tiempo, consumo eléctrico, comportamiento de la caché, radiación electromagnética, o simplemente un mensaje de error distinto—. Esta clase enseña a verlos, y es la más importante de la parte para escribir código real.
La receta necesita dos ingredientes que estuvieron en todas partes durante veinte años: CBC con relleno PKCS#7 y ningún control de integridad. El descifrado en CBC hace XOR del bloque descifrado con el bloque cifrado anterior; y como el atacante controla ese bloque anterior, controla directamente el resultado del XOR. Si además el sistema le dice —con un error distinto, un código HTTP distinto o simplemente tardando distinto— si el relleno resultante era válido, tiene un oráculo.
Con eso, descifra el último byte probando los 256 valores posibles hasta que el relleno
sea válido (lo que revela que ese byte descifrado vale 0x01, y por tanto revela el byte
intermedio, y por tanto el byte del texto claro real). Repite para el penúltimo forzando
relleno 0x02 0x02, y así hasta el bloque entero: 256 intentos por byte, sin conocer
jamás la clave. Vaudenay lo describió en 2002 y en 2010 se convirtió en explotación
masiva contra ASP.NET.
Un ataque de timing explota que el código tarde distinto según datos secretos. La forma más común es la comparación de bytes que sale en el primer fallo: si verificar un token tarda un poco más cuando los tres primeros bytes son correctos, el atacante reconstruye el token byte a byte con unos miles de peticiones, en lugar de los 2^128 intentos que exigiría adivinarlo entero. La mitigación es la comparación en tiempo constante, que recorre siempre toda la longitud acumulando diferencias.
El principio se generaliza: ninguna operación sobre datos secretos debe tener un tiempo —ni un patrón de acceso a memoria— que dependa de esos datos. De ahí que las implementaciones serias eviten ramas condicionales y accesos a tabla indexados por secretos, y de ahí también que las tablas de AES en software puro sean delicadas (Lucky13 midió microsegundos en la verificación MAC-then-encrypt de TLS, y varios ataques por caché han recuperado claves AES observando qué líneas de caché se tocaban). La objeción habitual —"la red añade tanto ruido que eso no es explotable"— es falsa: con suficientes muestras y estadística, diferencias de nanosegundos se distinguen a través de Internet.
Las defensas son concretas y componen entre sí. Usar AEAD (clase 059) elimina el
padding oracle porque el tag se verifica antes de tocar el relleno. Devolver un error
único para cualquier fallo de descifrado, sin distinguir causa, elimina el oráculo por
mensaje. Comparar en tiempo constante con hmac.compare_digest o equivalente elimina
el oráculo por tiempo. Usar bibliotecas maduras en lugar de implementar primitivas
propias hereda años de endurecimiento contra canales laterales. Y limitar la tasa de
intentos encarece un ataque que necesita miles o millones de peticiones.
El caso POODLE cierra la lección con una vuelta de tuerca: el ataque no explotaba TLS sino SSL 3.0, y funcionaba porque el atacante podía forzar un downgrade a esa versión antigua. Mantener protocolos obsoletos "por compatibilidad" es, en criptografía, mantener sus vulnerabilidades vivas.
| Término | Definición concisa |
|---|---|
| Canal lateral | Fuga por tiempo, consumo, caché o mensajes de error |
| Oráculo | Cualquier respuesta del sistema que revele algo sobre el secreto |
| Padding oracle | Oráculo que revela si el relleno era válido; descifra sin clave |
| PKCS#7 | Relleno cuya validez se puede comprobar y por tanto filtrar |
| Vaudenay (2002) | Descripción original del ataque de padding oracle |
| Ataque de timing | Explota que el tiempo dependa de datos secretos |
| Comparación en tiempo constante | Recorre toda la longitud sin salir antes |
| Lucky13 | Timing sobre MAC-then-encrypt en TLS |
| Bleichenbacher | Oráculo análogo sobre el relleno PKCS#1 v1.5 de RSA |
| POODLE | Downgrade a SSL 3.0 para explotar su relleno |
| Ataque por caché | Recuperar claves observando accesos a memoria |
| Error genérico | Respuesta única que no distingue la causa del fallo |
| Limitación de tasa | Encarece los ataques que necesitan muchas peticiones |
| Defensa en profundidad | AEAD + error único + tiempo constante + límites |
pip install cryptography flask requests
Monta el oráculo en localhost. No apuntes las herramientas a ningún host externo.
Monta un oráculo vulnerable (laboratorio propio). Un pequeño servicio Flask descifra AES-CBC y responde "padding OK" o "padding inválido". Ese comportamiento distinguible es el oráculo.
Ataque de padding oracle. Implementa el ataque clásico: para cada bloque, manipula el bloque previo byte a byte hasta que el oráculo indique padding válido; despeja el "intermediate value" y recupera el texto plano. Recupera un mensaje completo sin conocer la clave.
Mitígalo con AEAD. Reescribe el servicio con AES-GCM: ahora cualquier manipulación falla con InvalidTag de forma uniforme y el ataque deja de funcionar.
Timing en comparación de tokens. Implementa una comparación byte a byte con salida temprana y mide (con muchas repeticiones) que un token con más prefijo correcto tarda un poco más. Sustitúyela por hmac.compare_digest y comprueba que la diferencia desaparece.
Documenta las mitigaciones: AEAD, errores uniformes, comparación constante, y no exponer distinciones de fallo.
Toma un oráculo de padding de laboratorio y recupera un texto plano completo sin la clave; luego aplica una mitigación (migrar a AEAD) y demuestra que el mismo ataque ya no recupera nada. Criterio de aceptación: entregas el texto plano recuperado en la versión vulnerable y muestras que, tras migrar a AES-GCM, el atacante solo obtiene InvalidTag sin información útil.
| Síntoma / mensaje | Causa y cómo arreglar |
|---|---|
| Mensajes de error distintos para padding vs MAC | Crea un oráculo; unifica errores |
| Comparación de tags con salida temprana | Timing; usa compare_digest |
| CBC sin autenticación | Vulnerable a padding oracle; usa AEAD |
| Logs que revelan la causa del fallo | Fuga; registra sin distinguir para el cliente |
| Descifrar antes de verificar integridad | Procesas datos manipulables; verifica primero |
❓ ¿Basta con "esconder" los mensajes de error? No; el timing u otros canales siguen filtrando. La solución real es AEAD y tiempo constante, no ocultar síntomas.
❓ ¿Por qué AEAD elimina el padding oracle? Porque verifica el tag antes de tocar el padding y falla de forma uniforme, sin revelar validez de relleno.
❓ ¿Los ataques de timing son realistas por red? Sí; con suficientes mediciones y estadística se explotan incluso a través de la red (Lucky 13 lo demostró).
Clase 059 — Cifrado autenticado (AEAD)