flagRsa_oracle PicoCTF (Intermediate)

Contexto de la maquina

Trayectoria rsa_oracle

Descripción

Este reto criptográfico plantea la explotación de un RSA Oracle vulnerable a un Chosen Ciphertext Attack (CCA). El escenario describe la interceptación de comunicaciones entre una entidad bancaria y una empresa fintech, proporcionando al atacante:

  • Un mensaje cifrado (secret.enc)

  • Una contraseña cifrada (password.enc)

  • Acceso a un servicio remoto que actúa como oráculo RSA

El objetivo consiste en abusar del comportamiento del oráculo para recuperar la contraseña original y descifrar el mensaje final.

Objetivo del reto

  • Recuperar la contraseña cifrada mediante explotación del oráculo RSA.

  • Utilizar la contraseña obtenida para descifrar el archivo secret.enc.

  • Obtener la flag final.

Tipo de reto

  • Criptografía

  • RSA

  • Chosen Ciphertext Attack (CCA)

  • Oracle Attack

Habilidades y técnicas evaluadas

  • Identificación de esquemas de cifrado

  • Análisis de RSA sin padding (Textbook RSA)

  • Explotación de propiedades homomórficas

  • Chosen Ciphertext Attack (CCA)

  • Uso de herramientas como nc y openssl

  • Manipulación de enteros grandes en Python

Análisis de vulnerabilidades

Despliegue del CTF

Dentro de la propia página del reto, localizaremos el CTF. Al acceder a él, encontraremos un enlace que nos permitirá descargar un archivo que contiene un mensaje cifrado. Además, se nos proporciona una breve descripción con información relevante sobre el reto.

El objetivo principal de este tipo de CTFs es analizar la información proporcionada hasta conseguir obtener la flag final.

Decode Message.enc (Chosen Ciphertext Attack)

En el reto se nos proporciona la siguiente descripción para contextualizar el escenario:

Básicamente nos indican que se han interceptado comunicaciones y que disponemos de dos archivos:

  • Un mensaje cifrado (secret.enc)

  • El password cifrado (password.enc) que fue utilizado para proteger ese mensaje

El objetivo será abusar del oracle RSA para recuperar el password y posteriormente descifrar el mensaje final.

Descarga de los archivos

Procedemos a descargar ambos archivos:

Revisamos su contenido.

secret.enc

password.enc

Análisis de los archivos

  1. secret.enc comienza con "Salted__" → formato típico de OpenSSL cuando cifra con contraseña (usa un salt aleatorio)

  2. password.enc es un número enorme (382 bits) en formato ASCII

Además, nos dan acceso a un oracle en titan.picoctf.net:59965 que permite:

  • E → Cifrar un mensaje (RSA)

  • D → Descifrar un criptograma (RSA), pero no permite descifrar el propio password.enc

Identificación del cifrado

Por el comportamiento de oracle y el tamaño del número, deducimos:

  • password.enc está cifrado con RSA textbook (sin padding)

  • El oráculo implementa RSA:

    • Cifrado: c = m^e mod n

    • Descifrado: m = c^d mod n

  • RSA textbook es homomórfico: E(a) * E(b) = E(a * b)

Esta propiedad es la clave del ataque.

Estrategia de ataque (CCA contra RSA)

Queremos descifrar c (de password.enc) pero oracle rechaza consultas directas sobre c.

Idea: Usar la propiedad homomórfica para engañar a oracle.

  1. Elegimos un mensaje m1 conocido (por ejemplo, "a" = 0x61)

  2. Pedimos al oráculo que cifre m1 → obtenemos c1 = m1^e mod n

  3. Calculamos c2 = c * c1 mod n

    • c2 = (m^e)*(m1^e) = (m * m1)^e mod n

  4. Pedimos al oráculo que descifre c2 (esto sí está permitido porque c2 ≠ c)

    • El oráculo devuelve m2 = m * m1 mod n

  5. Calculamos m = m2 / m1 mod n

Ejecución del ataque

Sabiendo esto vamos a montarnos un script.

decodeMessage.py

Conectar con oracle

Obtener c1 (cifrado de "a")

Elegimos E y enviamos "a":

Nos guardamos el resultado de ciphertext para poder calcular el c2.

Calcular c2

Usando el script decodeMessage.py:

Respuesta:

Obtener m2 de oracle

Volvemos a oracle, elegimos D y enviamos c2:

Obtenemos m2 = 0x148856ba2730 = 22529371560752

Calcular el password

Sabemos que:

  • m2 = m * m1 mod n

  • m1 = 0x61 = 97

Por tanto:

Pero en el script hacen m2 // m1_int y luego convierten a bytes. El resultado es 0x60f50 = 397136.

Esto indica que en realidad m2 no es el producto directo, sino que ya está en rango. Lo importante es que m = 0x60f50 es el password.

Descifrar secret.enc

Una vez obtenido el password 60f50, desciframos secret.enc mediante el script enviando 148856ba2730 para que realice sus calculos y automaticamente nos decodifique el secret.enc:

Con esto ya obtenemos nuestra flag para poder validarla en la pagina, por lo que daremos por terminada este reto.

flag.txt

Last updated