Padding Oracle en detalle

渗透技巧 11个月前 admin
780 0 0

En criptografía, el ataque de padding oracle consiste en utilizar la validación del padding de un mensaje cifrado para descifrarlo. Con este ataque, además de descifrar, también es posible llegar a cifrar un mensaje sin conocer la clave de cifrado.
在密码学中,填充预言机攻击包括使用加密消息的填充验证来解密它。通过这种攻击,除了解密之外,还可以在不知道加密密钥的情况下加密消息。

El factor clave para determinar si una aplicación es vulnerable a este ataque radica en como se realiza la validación de un mensaje cifrado. Para identificar la vulnerabilidad necesitamos que la aplicación devuelva un mensaje de error especifico que nos indique que se trata de un error en el padding, o que seamos capaces de diferenciar de alguna forma cuando el padding es correcto y cuando es incorrecto.
确定应用程序是否容易受到此攻击的关键因素在于如何验证加密消息。为了识别漏洞,我们需要应用程序返回特定的错误消息,告诉我们这是填充中的错误,或者我们能够以某种方式区分填充是否正确和不正确。

Para entender como funciona la vulnerabilidad de padding oracle debemos conocer como funciona AES, el modo de cifrado en cadena CBC y como se realiza el relleno o padding.
要了解填充预言机漏洞的工作原理,我们必须知道 AES 的工作原理、CBC 链加密模式以及如何执行填充。

AES y CBC AES y CBC

Si estas leyendo esto, ya deberías saber que AES es un algoritmo de cifrado simétrico por bloques. En el modo de operación CBC (Cipher block chaining). a cada bloque de texto se le realiza la operación XOR con el bloque anterior ya cifrado. Además, se utiliza un vector de inicialización (IV) en el primer bloque.
如果您正在阅读本文,您应该已经知道 AES 是一种对称块加密算法。在CBC(密码块链)操作模式下。每个文本块都执行 XOR 操作,前一个块已经加密。此外,在第一个块中使用初始化向量 (IV)。

Padding Oracle en detalle

De forma análoga, en el proceso de descifrado se realiza la operación XOR tras descifrar cada bloque.
同样,在解密过程中,在解密每个块后执行异或操作。

Padding Oracle en detalle

Padding 填充

El padding o relleno se basa en completar el último bloque antes de realizar el cifrado, en AES se utiliza PKCS#7, completando el último bloque con bytes del mismo valor al número de bytes de relleno. Por ejemplo, si para completar el bloque se necesitan 5 bytes, el relleno sería 0505050505. El padding es obligatorio, si el último bloque no necesita relleno, se añade un bloque entero de relleno, para un bloque de 128 bits (16 bytes) se utilizaría 0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f.
填充或填充基于在执行加密之前完成最后一个块,在 AES PKCS # 7 中使用,以与填充字节数相同的字节完成最后一个块。例如,如果需要 5 个字节来完成块,则填充将为 0505050505 。填充是强制性的,如果最后一个块不需要填充,则添加整个填充块,因为将使用 0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 位(16 字节)的块。

Identificando un parámetro vulnerable
识别易受攻击的参数

Esta vulnerabilidad se suele encontrar en el descifrado de algún elemento introducido por el usuario, un token, una cookie, etc. Así que lo primero que debemos identificar es un parámetro que este potencialmente cifrado con AES, como puede ser un valor en hexadecimal o base64. AES utiliza un tamaño de bloque de 128 bits, lo que significa que los datos deben ser múltiples de 16 bytes, o 32 caracteres en hexadecimal.
此漏洞通常存在于用户输入的某些元素、令牌、cookie 等的解密中。因此,我们必须确定的第一件事是可能使用 AES 加密的参数,例如十六进制或 base64 的值。AES 使用 128 位的块大小,这意味着数据必须是多个 16 字节或十六进制的 32 个字符。

Por ejemplo el siguiente texto en hexadecimal de 64 caracteres corresponde a 2 bloques cifrados con AES. 20f78bc84c2df7cdd77ea7732ea04420a8beeafefac8f31ff70b7a84ce52bd7c
例如,以下 64 个字符的十六进制文本对应于使用 AES 加密的 2 个块。 20f78bc84c2df7cdd77ea7732ea04420a8beeafefac8f31ff70b7a84ce52bd7c

En este ejemplo tenemos un JSON cifrado con AES y codificado en base64. al revertir la codificación en base64 obtenemos 160 bytes (320 carácteres en hexadecimal), lo que corresponde a 10 bloques.
在此示例中,我们有一个使用 AES 加密并以 base64 编码的 JSON。通过恢复 Base64 编码,我们得到 160 个字节(十六进制 320 个字符),对应于 10 个块。

Padding Oracle en detalle

Si modificamos la longitud del parámetro, la aplicación nos devuelve un error indicando que la entrada debe tener una longitud múltiple de 16 bytes.
如果我们修改参数的长度,应用程序将返回一个错误,指示输入必须具有 16 个字节的多个长度。

Padding Oracle en detalle

Identificando un error de padding
识别填充错误

En el caso de que la aplicación nos devuelva un error descriptivo indicando que el error se debe al padding podemos dar por confirmada la existencia de la vulnerabilidad. Para obtener un error de padding, debemos modificar un byte del último bloque o el último byte del penúltimo bloque.
如果应用程序返回描述性错误,指示错误是由于填充引起的,我们可以确认漏洞的存在。要获得填充错误,我们必须修改最后一个块的字节或倒数第二个块的最后一个字节。

Por ejemplo, esta aplicación devuelve el error “PaddingException” al modificar un parámetro cifrado con AES.
例如,此应用程序在修改使用 AES 加密的参数时返回错误“填充异常”。

Padding Oracle en detalle

En cambio, si el padding es correcto obtenemos un resultado correcto, u otro tipo de mensajes de error relacionados con el contenido del mensaje, pero no con la función de descifrado.
另一方面,如果填充正确,我们会得到正确的结果,或者其他类型的错误消息与消息内容相关,但与解密功能无关。

Padding Oracle en detalle

Padding Oracle en detalle

Descifrar un byte 解密字节

Para verificar que podemos obtener un error de padding de forma voluntaria, debemos modificar el mensaje cifrado de forma que el último byte del mensaje descifrado termine con el padding 01. Para ello, modificamos el último byte del texto cifrado del bloque anterior, dado que no conocemos el contenido del mensaje deberemos realizar 256 intentos, o solo 16 si este byte ya es un byte de padding con un valor entre 00 y 0f. En el caso de no encontrar “otro” resultado con padding correcto, supondremos que el último byte es un byte de padding con el valor 01 y repetiremos el proceso con el penúltimo byte.
为了验证我们可以自愿获得填充错误,我们必须修改加密消息,以便解密消息的最后一个字节以 01 填充 .为此,我们修改了前一个块密文的最后一个字节,因为我们不知道消息的内容,我们将不得不进行 256 次尝试,或者如果该字节已经是值介于 和 0f 之间的 00 填充字节,则只有 16 次尝试。在没有找到具有正确填充的“另一个”结果的情况下,我们将假设最后一个字节是带有该值 01 的填充字节,并使用倒数第二个字节重复该过程。

Pongamos como ejemplo el siguiente texto cifrado con 5 bytes de padding.
让我们以以下带有 5 个字节填充的密文为例。

Padding Oracle en detalle

Al modificar el último byte del penúltimo bloque obtenemos un último bloque con padding válido 01, aunque de esta forma se corrompe el plaintext del penúltimo bloque. Además, podemos conocer cual era el byte sin cifrar utilizando la operación XOR: 0x20 ⊕ 0x24 ⊕ 0x01 = 0x05
通过修改倒数第二个块的最后一个字节,我们获得了具有有效 01 填充的最后一个块,尽管以这种方式倒数第二个块的明文已损坏。此外,我们可以知道未加密的字节使用 XOR 操作是什么:0x20 ⊕ 0x24 ⊕ 0x01 = 0x05

Padding Oracle en detalle

Descifrar los datos de un bloque
解密块中的数据

Una vez hemos obtenido el último byte del mensaje, repetimos el proceso para el resto de bytes del bloque.
一旦我们获得了消息的最后一个字节,我们就对块的其余字节重复该过程。

Para el siguiente byte realizamos la iteración buscando el padding 0202, como ya hemos obtenido el último byte, calculamos con XOR que ciphertext debemos introducir: 0x20 ⊕ 0x05 ⊕ 0x02 = 0x27. Por tanto, solo realizaremos 256 iteraciones con el penúltimo byte hasta encontrar el resultado válido.
对于下一个字节,我们迭代寻找填充 0202 ,因为我们已经获得了最后一个字节,我们使用 XOR 计算我们必须输入的密文:0x20 ⊕ 0x05 ⊕ 0x02 = 0x27。因此,我们只会用倒数第二个字节执行 256 次迭代,直到找到有效结果。

Padding Oracle en detalle

Continuamos el descifrado del resto de bytes automatizando el proceso.
我们通过自动化该过程继续解密其余字节。

Padding Oracle en detalle

Descifrar el resto de bloques
解密其余块

Como hemos visto en los ejemplos anteriores, para cada bloque a descifrar, necesitamos también el bloque anterior.Esto implica que no podemos descifrar el primer bloque de la secuencia. Dependiendo de la implementación realizada en la aplicación, el primer bloque suele contener el vector de inicialización (IV), aunque también puede haber un IV prefijado en el código.
正如我们在前面的例子中看到的,对于要破译的每个块,我们还需要前一个块。这意味着我们无法破译序列的第一个块。根据应用程序中的实现,第一个块通常包含初始化向量 (IV),尽管代码中也可以有一个前缀为 IV。

Generar un bloque cifrado
生成加密块

Por la forma que se construye la cadena de bloques, si conocemos el plaintext del primer bloque, podemos alterar el IV para generar un bloque cifrado: NewIV = IV ⊕ Plaintext ⊕ NewPlaintext Usando este método solo podemos modificar un único bloque con un máximo de 15 bytes de datos y uno de padding.
由于区块链的构建方式,如果我们知道第一个区块的明文,我们可以更改 IV 以生成加密区块: NewIV = IV ⊕ Plaintext ⊕ NewPlaintext 使用这种方法,我们只能修改最多 15 个字节的数据和一个填充的单个块。

En este ejemplo procedemos a modificar el parámetro ID del JSON calculando un nuevo IV.
在此示例中,我们通过计算新的 IV 来继续修改 JSON 的 ID 参数。

Padding Oracle en detalle

Generar varios bloques cifrados
生成多个密码块

Combinando las técnicas anteriores, podemos generar un texto cifrado que por su tamaño necesite varios bloques. Utilizaremos padding oracle para descifrar los bloques y XOR para modificar estos bloques por el contenido deseado.
结合以前的技术,我们可以生成一个密文,由于其大小需要多个块。我们将使用填充预言机来解密块,并使用 XOR 来修改这些块以获得所需的内容。

Para explicar el procedimiento, usaremos el siguiente ejemplo para “cifrar” el JSON {"id":"1","key":"RYxUB!nb6e2NKkHpkdPZHA~~"}
为了解释该过程,我们将使用以下示例来“加密”JSON {"id":"1","key":"RYxUB!nb6e2NKkHpkdPZHA~~"} 。

  • Descifrar un bloque, por ejemplo 00000000000000000000000000000000, o utilizar un bloque del que conozcamos su plaintext y ciphertext.
    解密一个块,例如 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  • Hacemos XOR del bloque descifrado con el ultimo bloque en claro que deseamos inyectar, el resultado se utilizará como ciphertext del penúltimo bloque.
    我们使用要注入的最后一个清除块对解密块进行 XOR,结果将用作倒数第二个块的密文。
  • Repetimos los pasos anteriores hasta obtener el primer bloque, que se corresponde con el IV. De igual forma, desciframos cada bloque, hacemos XOR con el texto en claro deseado y el resultado se utiliza como ciphertext del bloque anterior.
    重复前面的步骤,直到我们得到第一个块,对应于 IV。以同样的方式,我们破译每个块,我们使用所需的明文进行 XOR,结果用作前一个块的密文。

Padding Oracle en detalle

Automatizando la extracción
自动化提取

Podemos automatizar la extracción de datos con el script https://github.com/mpgn/Padding-oracle-attack/
我们可以使用 https://github.com/mpgn/Padding-oracle-attack/ 脚本自动提取数据

Obtener el valor de un IV hardcodeado
获取硬编码 IV 的值

En algunas aplicaciones, el vector de inicialización (IV) esta fijado en el código y no se muestra al usuario. Cuando esto ocurre, no podemos descifrar el primer bloque. Para descubrir el IV necesitamos conseguir el plaintext del primer bloque y de esta forma utilizar la función XOR.
在某些应用程序中,初始化向量(IV)固定在代码中,不会向用户显示。发生这种情况时,我们无法破译第一个块。为了发现 IV,我们需要获取第一个块的明文,从而使用 XOR 函数。

En el siguiente ejemplo, tenemos el bloque cifrado 6159c28d3019a62eb96180dced387011. Para descifrarlo realizamos el ataque de padding oracle con los bloques 00000000000000000000000000000000 6159c28d3019a62eb96180dced387011 obteniendo el bloque descifrado 6dffba1163080ffc7c84f24f350d8634. Si conocemos que el texto cifrado es “PATATASFRITAS”, realizamos la operación XOR y obtenemos el IV.
在下面的示例中,我们有 加密 6159c28d3019a62eb96180dced387011 块 .为了解密它,我们使用获得解密 6dffba1163080ffc7c84f24f350d8634 块的块 00000000000000000000000000000000 6159c28d3019a62eb96180dced387011 执行填充预言机攻击。如果我们知道密文是“PATATASFRITAS”,我们执行异或操作并获得 IV。

Padding Oracle en detalle

Al ser el IV fijo, a partir de este momento podemos descifrar el primer bloque de cualquier mensaje.
作为固定的IV,从这一刻起,我们可以破译任何消息的第一个块。

Reto para practicar 对实践的挑战

En el reto Encrypted Pastebin del CTF de hackerone se pueden probar las tecnicas explicadas en este articulo. Para acceder es necesario estar registrado en hackerone.
在黑客CTF加密粘贴挑战中,您可以测试本文中介绍的技术。要访问它,必须在hackerone中注册。

Referencias 引用

原文始发于Jesús Antón:Padding Oracle en detalle

版权声明:admin 发表于 2023年8月21日 上午9:09。
转载请注明:Padding Oracle en detalle | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...