Skip to main content
Volver a writeups

Writeup técnico

Pasty – Nullcon CTF 2026

---

nullcon CTF 2026

Datos del reto

Campo Valor
CTF Nullcon CTF 2026
Reto Pasty
Categoría Web / Crypto
Flag ENO{cr3at1v3_cr7pt0_c0nstruct5_cr4sh_c4rd5}

Descripción del reto

El servicio era un pastebin que protegía cada paste con una firma "casera". La interfaz solo dejaba ver un paste si id y sig coincidían, así que todo dependía de entender cómo estaba implementada esa firma y por qué se podía falsificar.


Reconocimiento

Al crear un paste, el servidor devolvía una URL de este estilo:

view.php?id=<HEX_ID>&sig=<HEX_SIG>

Eso nos daba exactamente lo que necesitábamos para analizar el esquema: muchos pares válidos (id, sig). La lógica estaba en sig.php, y ahí se veía que la firma no usaba un estándar como HMAC sino una construcción propia a partir de SHA256.


Análisis

El algoritmo derivaba solo 24 bytes efectivos de la clave:

  • m0, m1 y m2, tres bloques de 8 bytes sacados de SHA256(k).

Luego, para cada bloque de la firma, elegía uno de esos subbloques según h[8*i] % 3 y lo mezclaba con el hash del mensaje usando XOR y encadenamiento.

El problema era que, si conocíamos el mensaje firmado y la firma resultante, podíamos sacar cuál era el subbloque usado en cada posición:

  • c0 = b0 XOR o0
  • ci = bi XOR oi XOR o(i-1) para i > 0

Como al crear pastes el mensaje (id) era conocido, también lo era SHA256(id). Reuniendo suficientes firmas válidas, se terminaban recuperando m0, m1 y m2 completos.


Resolución

La estrategia fue:

  1. Crear muchos pastes y guardar cada par (id, sig).
  2. Calcular SHA256(id) para cada uno.
  3. Separar sig en cuatro bloques de 8 bytes.
  4. Despejar qué bloque secreto se usó en cada posición.
  5. Rellenar m0, m1 y m2 hasta tenerlos completos.
  6. Recalcular una firma válida para id = "flag".
  7. Pedir view.php?id=flag&sig=<firma_falsificada>.

Una vez recuperados los tres subbloques de clave, el resto era simplemente reproducir el algoritmo del servidor con un id nuevo.


Flag

ENO{cr3at1v3_cr7pt0_c0nstruct5_cr4sh_c4rd5}