CVE-2024-6387 — regreSSHion OpenSSH unauth RCE

CVE-2024-6387 — regreSSHion OpenSSH unauth RCE

TL;DR: A signal handler race in OpenSSH’s pre-authentication code (sshd) lets an attacker race SIGALRM against cleanup_exit() and call async-signal-unsafe functions (syslog → malloc → free) from inside the handler — a classic heap-state corruption. Reachable unauthenticated against glibc Linux distros running OpenSSH 8.5p1 to 9.7p1. Exploitation is slow (8000 connections, ~6-8 hours on default sshd), but reliable on 32-bit and proven on x86_64 by Qualys. The lesson is to audit signal handlers in security-critical daemons, never to trust “this code path is exit-only.”

What it is

OpenSSH limits authentication time via LoginGraceTime (default 120s). When the timer fires, sshd raises SIGALRM. The handler — installed in 2006 and quietly racy since 8.5p1 when an unrelated commit removed a guard — calls syslog(3) to log the timeout, then _exit(). syslog internally calls localtime_r, malloc, free. Any of those mutating a glibc internal data structure mid-call can race the interrupted allocator state in the main thread. The race is on the heap arena lock and on __nss_database. Win the race at the right moment and an attacker-controlled username (handled in userauth_request) can corrupt heap metadata → glibc free-list manipulation → arbitrary write → RCE.

Affected versions

  • Vulnerable: OpenSSH 8.5p1 through 9.7p1 on glibc-based Linux (Debian, Ubuntu, RHEL, Alpine if glibc).
  • Not vulnerable: OpenBSD (different signal model), musl libc (Alpine default), OpenSSH ≥ 9.8p1.
  • Pre-8.5p1: Also “vulnerable” to the original 2006 bug (CVE-2006-5051) but exploitation has not been demonstrated.

Reachability

  • TCP/22 reachable (or whatever port sshd binds).
  • Default LoginGraceTime 120 (lower = shorter window per connection but more rounds).
  • Default MaxStartups 10:30:100.
  • Glibc.

Tradecraft (red-team)

The Qualys PoC is not publicly released as a working exploit; multiple researchers have rebuilt it. Realistically, in a pentest scenario you confirm version + glibc + reachability, then leave exploitation to a documented PoC (rule of engagement permitting):

1
2
3
4
5
6
7
8
9
10
# Version probe (banner)
nc -w3 target 22 | head -1
# OpenSSH_9.6p1 Ubuntu-3ubuntu13.4   <-- vulnerable

# Distro fingerprint to confirm glibc
curl -s https://shodan.io/host/<ip>  # or scan banners

# Test connection without auth — verify LoginGraceTime
time ssh -o PreferredAuthentications=none -o BatchMode=yes user@target
# Should hang ~120s then close

A practical exploit runs O(8,000) concurrent connections sustained for hours, racing the SIGALRM precisely as syslog is mid-malloc. Defenders observe a massive flood of connection attempts well below an obvious DoS — sshd[NNN]: Timeout before authentication repeatedly. That signature alone justifies blocking IPs.

Several public exploits exist of unclear quality (acrono/CVE-2024-6387-exploit, xaitax/CVE-2024-6387_Check); for defensive validation, treat them as probes only and patch instead of trying to reproduce RCE.

Patch / mitigation (the actual response)

  • Patch: openssh-9.8p1 introduced a strict async-signal-safe handler that no longer calls syslog/free. Distro backports: Ubuntu USN-6859-1, Debian DSA-5724-1, RHEL CVE-2024-6387 errata.
  • Mitigation if patching delayed: set LoginGraceTime 0 in sshd_config (disables the bug at the cost of allowing slow auth DoS). Restart sshd.
  • Network defence: rate-limit inbound TCP/22 to ≤ 10 conn/min per source IP; the exploit needs sustained flood.
  • Detection: alert on > 100 sshd: Timeout before authentication events per minute from a single source.

Source-code lesson

The bug demonstrates the limits of an “exit path is safe” intuition. Audit checklist for any signal handler in a security daemon:

1
2
3
4
5
6
7
void handler(int sig) {
    // ONLY async-signal-safe operations (man 7 signal-safety).
    // NO malloc, NO free, NO syslog, NO printf, NO gettimeofday on glibc.
    // The interrupted thread holds locks you don't see.
    write(STDERR_FILENO, "msg\n", 4);  // OK
    _exit(1);                           // OK
}

man 7 signal-safety lists the ~120 safe functions; syslog is conspicuously absent. The 2006 bug was caught and patched specifically for syslog; the 2024 regression came when someone reintroduced it during refactor.

Detection and defence (broader)

  • Patch every Linux box running sshd to ≥ 9.8p1 or vendor-backport.
  • Default-deny inbound 22; expose via jump host with VPN/Bastion.
  • fail2ban rule on sshd: Timeout before authentication repeated > 5x in 60s.
  • For high-value targets: switch to Match Address + key-only auth and shorten LoginGraceTime to 30s — narrows the window even pre-patch.
  • Consider running sshd under musl distro (Alpine) for exposed jump hosts.

OPSEC pitfalls (for the attacker)

  • A successful exploit chain takes hours; the connection flood is visible in any IDS.
  • The exploit leaves the sshd process crashed or in a strange state; the next admin login often sees coredumpctl artifacts.
  • AppArmor profiles on sshd restrict post-exploit lateral; expect to need a privilege chain.

References

See also: cve-2024-3094-xz-utils-backdoor, cve-2024-23897-jenkins-arbitrary-file-read, kernel-syscall-source-review, ssh-execution