El significado del elemento de prueba es bastante simple. Se proporciona un volcado de tráfico, que contiene una clave de cifrado, algo de basura y una bandera cifrada. Necesitamos extraerlos y descifrar la bandera. También se muestra el comando OpenSSL con el que se cifró este indicador. El tráfico es bastante interesante, pero después de 10 líneas de código Python, tenía una clave de cifrado, basura y una bandera cifrada frente a mí. Al parecer, ¿qué podría salir mal?
La asignación dice que la bandera fue cifrada con aproximadamente el siguiente comando (omití algunos parámetros insignificantes y cambié el algoritmo de cifrado).
echo "FLAG_xxxx…xxxxxx" | openssl enc -e -base64 -aes-256-cbc -nosalt -k $password
Inserté los parámetros obtenidos del tráfico en el comando, lo inicié y ... ¡tengo basura! Intenté de nuevo. Basura otra vez. Intenté reconstruir el tráfico de diferentes formas. No, aparentemente, el tráfico solo se puede recopilar sin ambigüedades. ¡Pero la salida de cifrado es basura de nuevo! Al mismo tiempo, OpenSSL advierte honestamente que obtener una clave de una contraseña en 1 paso es una mala idea ...
echo "ENCRYPTED_FLAG" | openssl enc -d -base64 -aes-256-cbc -nosalt -k $key
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
El día siguiente lo pasé tratando de romper esta locura. Razoné razonablemente que aparentemente había aislado incorrectamente la "basura" indicada en las condiciones y escribí varias opciones para dividir la cadena resultante en "contraseña" y "bandera cifrada" para la "fuerza bruta" posterior. No ayudó ... Empecé a comprender profundamente cada uno de los parámetros.
Como sabemos, AES requiere una clave de cifrado y un IV (vector de inicialización) para funcionar. El parámetro -k nos permite usar una frase de texto, de la cual OpenSSL obtiene la clave requerida y IV. Puede verlos usando el parámetro -p.
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
key=5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
iv =3B02902846FFD32E92FF168B3F5D16B0
C11kA+GcqkU4ocOvZAVr3g==
Este conocimiento tampoco me dio nada. Entonces, sin embargo, decidí volver a la idea más loca que se me ocurrió. A saber: el problema no es mío, pero algo ha cambiado en OpenSSL ... El
tráfico estaba fechado en 2016, así que tomé Ubuntu 14.04 y, sin muchas esperanzas de éxito, simplemente inserté los datos iniciales en él. Y de repente, en lugar de basura, ¡obtuve una BANDERA! La noche dejó de ser lánguida ... Además, el mismo comando con la misma contraseña y el parámetro -p produjo claves de cifrado completamente diferentes y ¡IV!
NUEVO SISTEMA (openssl 1.1.1h)
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
key=5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
iv =3B02902846FFD32E92FF168B3F5D16B0
C11kA+GcqkU4ocOvZAVr3g==
SISTEMA ANTIGUO (openssl 1.0.1f)
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
key=5F4DCC3B5AA765D61D8327DEB882CF992B95990A9151374ABD8FF8C5A7A0FE08
iv =B7B4372CDFBCB3D16A2631B59B509E94
R3N+5v3zOz9QcNt08cwqcA==
Quedó claro que los temores se confirmaron. El algoritmo para generar Key e IV a partir de una frase de contraseña ha cambiado, lo que rompe por completo la capacidad de resolver CTF de frente en las versiones modernas de OpenSSL. En el proceso de buscar los matices de implementación, me encontré con un trabajo muy interesante " Análisis de cifrado OpenSSL basado en contraseña del protocolo de derivación de claves " y todo encajó. En resumen, la versión 1.1.0 agregó un nuevo protocolo para generar claves a partir de una contraseña PBKDF2, pero lo que es más importante, ¡el antiguo algoritmo PBKDF1 cambió el algoritmo hash predeterminado de MD5 a SHA-256! Por lo tanto, la misma contraseña produce una clave y un IV diferentes. Para descifrar los datos previamente cifrados, en las versiones más recientes es necesario utilizar el parámetro -md md5 .
“-Md messagedigest: especifica el resumen del mensaje utilizado para la derivación de claves de md2, md5, sha o sha1 ”
Después de agregar este parámetro, fue posible obtener la bandera en el nuevo OpenSSL. No sé si los desarrolladores de la tarea de prueba realmente tuvieron en cuenta este "matiz" o simplemente no lo probaron en sistemas modernos, pero el hecho es que tuve que profundizar en algunas de las sutilezas de OpenSSL.
PD: A través de mis conocidos, ya les informé a los desarrolladores de la prueba de prueba sobre el problema que encontré, de lo contrario, de repente se sorprenden mucho de que estas personas no vayan a ellos ...