GHSA-9C48-W39G-HM26

regreSSHion: The Return of the Signal Handler Nightmare

Alon Barad
Alon Barad
Software Engineer

Jan 6, 2026·5 min read

Executive Summary (TL;DR)

OpenSSH server (sshd) contains a race condition in its signal handling logic. By winning a race against the `LoginGraceTime` timer, an unauthenticated attacker can interrupt the heap manager in an inconsistent state, leading to heap corruption and eventual Remote Code Execution (RCE) as root. It affects default configurations of OpenSSH versions 8.5p1 through 9.7p1 on glibc-based Linux systems.

A signal handler race condition in OpenSSH's sshd allows unauthenticated remote code execution (RCE) as root on glibc-based Linux systems. This is a regression of a vulnerability originally fixed in 2006 (CVE-2006-5051).

The Hook: Time is a Flat Circle

If you've been in this industry long enough, you start to see the same ghosts haunting the same hallways. In 2006, Mark Dowd discovered a signal handler race condition in OpenSSH (CVE-2006-5051). It was patched, we all applauded, and we moved on. Fast forward to 2024, and the Qualys Threat Research Unit has found that we somehow managed to un-fix it.

Meet regreSSHion (CVE-2024-6387). It is essentially the same bug class, reintroduced into OpenSSH version 8.5p1 nearly four years ago. The vulnerability lies in sshd, the ubiquitous daemon that likely secures the very server you are using to read this.

The premise is simple yet terrifying: an unauthenticated attacker can exploit a race condition in the signal handler to corrupt the heap and execute arbitrary code as root. Yes, that root. No credentials required, just network access and a lot of patience.

The Flaw: Async-Signal-Safety (Or Lack Thereof)

The root cause here is a violation of one of the golden rules of systems programming: never call async-signal-unsafe functions inside a signal handler.

When sshd receives a connection, it sets a timer via SIGALRM defined by LoginGraceTime (usually 120 seconds). If you don't authenticate within that window, the alarm fires, the signal handler catches it, and it kills the connection. Simple, right?

The problem arises when the signal handler decides to perform logging. In the affected versions, the handler calls syslog(). The syslog() function is not async-signal-safe. Why? Because strictly speaking, syslog() often internally calls malloc() or free() to manage message buffers.

If the signal interrupts the main execution flow while the program is already inside malloc() or free() (manipulating the heap), and then the signal handler calls syslog() (which calls malloc() again), you get re-entrancy into the heap allocator. The allocator's internal structures (like the arena locks or free lists) are left in an inconsistent state, leading to heap corruption. It’s like trying to reorganize a library, and halfway through, someone pauses time, moves the shelves around, and tells you to keep working.

The Code: The Smoking Gun

Let's look at where the logic failed. The regression was introduced in October 2020 (OpenSSH 8.5p1) when the logging logic was refactored.

In the vulnerable code, the SIGALRM handler eventually routes to a function that looks something like this (simplified):

// Inside the signal handler context
void grace_alarm_handler(int sig) {
    // ... setup context ...
    
    // FATAL ERROR: syslog is NOT async-signal-safe
    syslog(LOG_CRIT, "Timeout before authentication for %s", user);
    
    _exit(1);
}

The fix is technically simple but architecturally strict: do not perform complex operations in the handler. The patch moves the logging logic out of the async-signal context or ensures only safe primitives are used.

[!NOTE] In the patched version (9.8p1), the logic was altered to avoid the unsafe syslog call entirely during the async signal handling, restoring the safety guarantees present in versions prior to 8.5p1.

The Exploit: Grooming the Heap

Exploiting this is not a "point-and-click" adventure; it's a statistical war of attrition. To trigger the corruption, the attacker must disconnect strictly when sshd is in the middle of a heap operation (like processing a public key).

  1. Heap Feng Shui: The attacker sends specific payloads (public keys) to fragment the heap and groom it into a predictable layout.

  2. The Race: The attacker initiates a connection and waits for the LoginGraceTime to expire. The goal is to have the SIGALRM interrupt the code execution exactly when sshd is inside a free() call handling the cleanup of a previous packet.

  3. The Corruption: If timed perfectly, the syslog() call inside the handler invokes malloc(), which tries to use the heap structures that free() was currently modifying. This allows the attacker to overwrite glibc's tcache or fastbin chunks.

  4. ASLR Bypass: Since modern Linux uses Address Space Layout Randomization (ASLR), the attacker doesn't know where the heap or libc is. However, because sshd forks a child process for every connection, the memory layout (and ASLR offset) remains consistent if the parent server doesn't restart. The attacker can brute-force the timing and memory layout over thousands of attempts (taking ~6-8 hours on average).

The Impact: Root Shell

If the exploit succeeds, the impact is total compromise.

  • Privilege Level: The vulnerable process runs as root because authentication hasn't happened yet (sshd needs root privileges to bind the port and eventually switch users).

  • Scope: The attacker gains full control over the server. They can install persistent backdoors, steal data, or pivot to internal networks.

  • Constraints: This specifically targets glibc-based Linux systems. OpenBSD is not affected (different security mechanisms), and Windows/macOS implementations vary. However, considering the vast majority of cloud infrastructure runs on Linux/glibc, the target surface is massive.

The Fix: Remediation

If you manage Linux servers, you have two options: patch now, or apply the config workaround.

1. The Patch: Upgrade to OpenSSH 9.8p1. This version fixes the regression by removing the unsafe logging from the signal handler.

2. The Workaround (Immediate): If you cannot patch immediately, you can mitigate the race condition by setting the LoginGraceTime to 0 in your sshd_config.

# /etc/ssh/sshd_config
LoginGraceTime 0

[!WARNING] Setting LoginGraceTime 0 exposes you to a different risk: Denial of Service. Without a timeout, an attacker can exhaust all available connection slots by opening connections and never completing the handshake. However, a DoS is infinitely better than a root RCE. Pick your poison.

Fix Analysis (1)

Technical Appendix

CVSS Score
8.1/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
4.50%

Affected Systems

Linux systems using glibcOpenSSH 8.5p1OpenSSH 8.6p1OpenSSH 8.7p1OpenSSH 8.8p1OpenSSH 8.9p1OpenSSH 9.0p1OpenSSH 9.1p1OpenSSH 9.2p1OpenSSH 9.3p1OpenSSH 9.4p1OpenSSH 9.5p1OpenSSH 9.6p1OpenSSH 9.7p1

Affected Versions Detail

Product
Affected Versions
Fixed Version
OpenSSH
OpenBSD
>= 8.5p1, < 9.8p19.8p1
AttributeDetail
CWE IDCWE-364
Attack VectorNetwork
CVSS8.1 (High)
ImpactRemote Code Execution (Root)
Architecturex86 (glibc), amd64 (glibc)
ComplexityHigh (Race Condition)
CWE-364
Signal Handler Race Condition

Vulnerability Timeline

Original bug (CVE-2006-5051) patched
2006-09-28
Regression introduced in OpenSSH 8.5p1
2020-10-01
Qualys discloses CVE-2024-6387 (regreSSHion)
2024-07-01
OpenSSH 9.8p1 released with fix
2024-07-01

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.