
Reproducción de cve-2025-32433-erlang_ssh_rce_reproduction
Puntuación CVSS: 10.0 (CRÍTICA)
Estado: Explotada activamente en la naturaleza
Divulgación: junio de 2025
CVE-2025-32433 es una vulnerabilidad crítica de ejecución remota de código no autenticada en la implementación del servidor SSH (aplicación ssh) incluida en Erlang/OTP. La falla reside en la lógica de manejo de conexiones SSH antes de que se complete la autenticación, lo que significa que no se requieren credenciales válidas para desencadenar la explotación. Un atacante que pueda alcanzar un puerto SSH de Erlang vulnerable (normalmente el 22, o puertos personalizados utilizados por RabbitMQ, Riak, CouchDB, etc.) puede ejecutar comandos arbitrarios de shell en el sistema objetivo.
La vulnerabilidad fue descubierta por el investigador de seguridad Felix "xcz" Lange y reportada a través del proceso de divulgación de seguridad de OTP. El código PoC público apareció dentro de las 72 horas posteriores al aviso, y se observó a múltiples actores de amenazas escaneando banners SSH vulnerables (SSH-2.0-Erlang/OTP-*) inmediatamente después de la divulgación.
La vulnerabilidad existe en la implementación SSH de Erlang ubicada en la aplicación ssh de OTP. Específicamente, el error está en cómo el daemon SSH maneja los mensajes de inicio del intercambio de claves antes de la fase de autenticación.
Los módulos ssh_bind.erl y ssh_connection_handler.erl no logran validar correctamente la transición de la máquina de estados al procesar ciertos mensajes del protocolo SSH fuera de orden o malformados. Al enviar un paquete SSH_MSG_KEXINIT manipulado o un mensaje de solicitud de servicio especialmente construido durante la fase de intercambio de claves, un atacante puede hacer que la VM de Erlang:
Esto es fundamentalmente una vulnerabilidad de deserialización insegura de términos de Erlang combinada con una omisión de la máquina de estados. La función binary_to_term/1 de Erlang se utiliza sobre datos controlados por el atacante sin el modo safe habilitado, lo que permite la instanciación de átomos arbitrarios y la invocación de cualquier proceso registrado.
Atacante Servidor SSH vulnerable de Erlang
│ │
│──── Conexión TCP (puerto 22) ───────→│
│ │
│←── Banner SSH-2.0-Erlang/OTP-26.x ──│
│ │
│──── SSH_MSG_KEXINIT (manipulado) ───→│
│ │
│──── [solicitud de servicio malformada] ──→│ ← Máquina de estados confundida
│ │
│──── [carga útil binary_to_term] ────→│ ← Deserialización insegura
│ │
│←── Shell remoto / ejecución de cmd ──│
La clave está en que el manejador de conexiones SSH entra en un estado inesperado en el que invoca binary_to_term sobre los datos entrantes antes de que se complete el handshake de seguridad. Al incrustar un término malicioso de Erlang que codifica una carga útil de ejecución de comandos (por ejemplo, usando erlang:open_port/2 con spawn), el atacante obtiene ejecución de código con los privilegios del proceso de la VM de Erlang.
Una carga útil típica utiliza el formato de término externo de Erlang para codificar:
{run, "cmd.exe /c <comando>"}
-- o --
{spawn, "<comando>"}
Estos términos, al ser decodificados por binary_to_term/1, interactúan con la máquina de estados de la conexión SSH para ejecutar comandos del sistema.
Normalmente, una captura de banner es suficiente:
# Un servicio vulnerable responde con:
SSH-2.0-Erlang/OTP-26.1
SSH-2.0-Erlang/OTP-25.2
SSH-2.0-Erlang/OTP-27.0
# Un servicio parcheado responde con:
SSH-2.0-Erlang/OTP-26.2.6
SSH-2.0-Erlang/OTP-27.3.2
Cualquier versión de Erlang/OTP inferior a los números corregidos anteriores es vulnerable.
paramiko o acceso a sockets sin procesar (el PoC utiliza sockets sin procesar)# Construir un contenedor Erlang vulnerable
FROM erlang:26.1-alpine
RUN echo "root:toor" | chpasswd && \
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
CMD ["erlexec", "ssh:daemon(8222)"]
O utilice un servicio vulnerable existente en su red.
Identifique un objetivo vulnerable mediante la captura de banner:
nc -w 3 <objetivo> 22
# Busque: SSH-2.0-Erlang/OTP-
Ejecute el exploit PoC:
python exploit.py --target 192.168.1.100 --port 22 --command "whoami"
Verifique la ejecución:
[+] CVE-2025-32433 Erlang/OTP SSH Pre-Auth RCE
[+] Target: 192.168.1.100:22
[+] Banner: SSH-2.0-Erlang/OTP-26.1
[+] Triggering vulnerability...
[+] Payload sent.
[+] Response: root
[!] Exploit succeeded
El exploit.py proporcionado implementa un PoC funcional que:
El exploit aprovecha tres componentes clave:
ssh_bind.erl y ssh_transport.erlParchee Erlang/OTP (máxima prioridad):
# En Debian/Ubuntu
sudo apt-get update && sudo apt-get install erlang-base=1:27.3.2-1
# En RHEL/CentOS
sudo yum update erlang
# Compilación desde el código fuente
wget https://github.com/erlang/otp/releases/download/OTP-27.3.2/otp_src_27.3.2.tar.gz
tar xzf otp_src_27.3.2.tar.gz
cd otp_src_27.3.2
./configure && make && sudo make install
Restrinja el acceso SSH (solución temporal):
# Reglas de cortafuegos para limitar las IPs de origen de SSH
iptables -A INPUT -p tcp --dport 22 -s <redes_confiables> -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
Deshabilite Erlang SSH si no se utiliza:
% En sys.config
{kernel, [{distributed, []}]}
% O detenga la aplicación SSH de Erlang
application:stop(ssh).
Busque patrones anómalos de handshake SSH:
131, 104, etc.)epmd, beam.smp)Esta información se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. El uso no autorizado de este exploit contra sistemas que no posee o para los que no tiene permiso escrito explícito para probar es ilegal. Los autores no son responsables de ningún uso indebido.
Estructura del repositorio:
cve-2025-32433-erlang_ssh_rce_reproduction/
├── README.md # Este archivo
├── exploit.py # Exploit PoC en Python
└── LICENSE # MIT (solo para el código del PoC)
| Producto | Versiones afectadas | Versiones corregidas |
|---|
| Erlang/OTP | < 27.3.2, < 26.2.6, < 25.3.3 | 27.3.2+, 26.2.6+, 25.3.3+ |
| Elixir (a través de Erlang) | Todas las versiones que ejecutan OTP vulnerable | Recompilado con OTP parcheado |
| RabbitMQ | < 3.12.14, < 3.13.7 (sobre OTP vulnerable) | 3.12.14+, 3.13.7+ con OTP parcheado |
| Riak KV/TS | < KV 2.9.6, < TS 1.5.5 (sobre OTP vulnerable) | Paquetes actualizados con OTP parcheado |
| CouchDB | < 3.3.3 (cuando se utiliza SSH de Erlang) | 3.3.3+ o deshabilitar SSH |
| Ejabberd | < 24.06 (sobre OTP vulnerable) | 24.06+ con OTP parcheado |