RegreSSHion: the OpenSSH RCE that came back from 2006
A signal-handler race in sshd (sshd(8)) that was fixed in 2006 and then quietly un-fixed. Patch sshd, or apply the mitigations where you cannot reboot immediately.
01 The Big PictureFor leadership · no jargon
Okay, so here's one to ruin your afternoon: OpenSSH — the remote doorkeeper on pretty much every Linux server on the planet — has a remotely exploitable root bug in it. OpenSSH is the thing that lets your engineers log in from across the internet, which means it's exposed by design: it has to answer strangers before it knows who they are. This flaw means an attacker can knock on that door thousands of times, never once prove any identity, and still wander off with the master keys — full administrator control of the machine. Yikes.
In business terms, that's about as bad as it gets for a server. Whoever gets in can steal customer data, plant ransomware, quietly watch traffic, use the box as a launchpad against partners and customers, or just switch it off out of spite. The saving graces: the attack is slow and noisy — researchers needed on average six to eight hours of continuous attempts against a single machine — and it only works against servers the attacker can reach directly over the network.
The vulnerability was found and publicly demonstrated by Qualys in July 2024. It wasn't being exploited in the wild at disclosure, and it's not on CISA's known-exploited list as of this writing — but the full technical details are public, the method is repeatable, and automated scanning for unpatched servers followed within days. So: treat any machine whose login door faces the internet as urgent and patch within days; internal-only servers can follow the normal patch cycle.
Who acts: whoever runs your Linux servers. The fix itself is mercifully routine — a standard package update plus a restart of the remote-login service, minutes per machine, no data loss, and active admin sessions are not dropped. Where a machine genuinely cannot be patched this week, a one-line config change closes the attack path temporarily, at the cost of making the login service easier to overload. More on that trade-off below.
02 Technical BreakdownFor engineers
CVE-2024-6387 ("regreSSHion") is an async-signal-safety bug in the OpenSSH server, sshd. The tl;dr: when a client connects but fails to authenticate within LoginGraceTime (default 120 seconds), sshd's SIGALRM handler fires and calls syslog() — which on glibc systems calls malloc() and free(), neither of which is async-signal-safe. If the alarm lands while the main thread is inside the allocator, the heap is in an inconsistent state, and the attacker gets a controlled heap-corruption primitive inside a process running as root. Neat, in the worst possible way.
And here's the bit that makes this one sting: it's literally a regression. The same class of flaw was fixed in 2006 as CVE-2006-5051 (OpenSSH 4.4) by making the alarm handler signal-safe; then in October 2020 a change that shipped in OpenSSH 8.5p1 accidentally removed the #ifdef DO_LOG_SAFE_IN_SIGHAND guard from the sigdie() path, and the unsafe syslog() call strolled back in. Every portable release from 8.5p1 through 9.7p1 inclusive carries it; 9.8p1 (released 2024-07-01) removes it again. Eighteen years of fix, undone by one guard clause. (It's called "regreSSHion" for a reason.)
Exploitation is a probabilistic race, not a clean trigger. An unauthenticated remote attacker opens batches of connections, withholds authentication, and lets the grace timer expire so the handler fires mid-allocation. Qualys demonstrated a full root shell on 32-bit glibc Linux with ASLR: on average roughly 10,000 attempts, i.e. six to eight hours of sustained connections at the server's maximum accept rate. Exploitation on 64-bit systems was believed possible but not demonstrated at disclosure, and non-glibc systems were not examined — so don't read "not yet demonstrated" as "safe", cos it isn't. The volume is the defender's advantage: thousands of half-open logins are loud in any auth log.
The fix works by making the SIGALRM handler async-signal-safe again, so expiry of the grace timer can never corrupt the heap; Red Hat and other vendors backported that change without bumping the base version (RHEL 9: openssh-8.7p1-38.el9_4.1, RHSA-2024:4312). The LoginGraceTime 0 mitigation works differently: it never arms the alarm at all, so there is no signal to race — at the cost of letting idle unauthenticated connections hold slots until MaxStartups throttles them. Two different ways of closing the same door, then.
03 Affected
Portable OpenSSH 8.5p1 through 9.7p1 inclusive, on glibc-based Linux. Releases 4.4p1 up to 8.5p1 are not affected (the 2006 fix was still in place), and anything older than 4.4p1 is vulnerable unless it carries the 2006 backport. OpenBSD is not vulnerable. musl-based systems such as Alpine were not examined by the researchers — treat them as unknown, not safe.
On Red Hat: RHEL 9 is the only affected RHEL release (it ships openssh 8.7p1); RHEL 6, 7 and 8 ship older, unaffected builds. The fixed RHEL 9 package is openssh-8.7p1-38.el9_4.1 or newer — note the version string stays 8.7p1, so "8.7p1" alone does not mean vulnerable. That trips people up, so it's worth saying twice. Most other current distributions shipped versions in the vulnerable range and issued backported fixes the same week; trust the vendor advisory and the package changelog, not the base version number.
04 Detection
First, what are we even running?
ssh -VClient version only — the daemon is the target, so check the server side separately. Easy trap to fall into.
dpkg -l openssh-server | awk '/^ii/{print $3}'Debian/Ubuntu; anything in 8.5p1–9.7p1 is vulnerable unless the vendor backport is present.
rpm -q openssh-serverRHEL-family; installed daemon build — same vulnerable range, same backport caveat.
ss -tlnp | grep ':22'Confirm sshd is listening and on which interfaces — anything bound to a public address is priority one.
05 Remediation
01 Patch the daemon
RHEL 9's fixed build is openssh-8.7p1-38.el9_4.1 (RHSA-2024:4312, released 2024-07-03); Debian/Ubuntu shipped equivalent backports the same week. Every vendor patched without bumping the base version, so the version string alone does not clear a host — the changelog is the verdict, and we'll get to that in Verification. Install the update, validate the config, then restart the service so the patched binary actually loads.
sudo apt-get update && sudo apt-get install --only-upgrade openssh-serverDebian/Ubuntu; pulls the distro-patched openssh-server build only.
sudo dnf upgrade openssh-server -yRHEL-family; on RHEL 9 expect 8.7p1-38.el9_4.1 or newer.
sudo sshd -tConfig sanity check before the restart; silent output means OK.
sudo systemctl restart sshdRequired — a reload is not enough. Established sessions survive; only the listener restarts, so no, you won't lock yourself out mid-SSH. (The question everyone asks first.)
02 Mitigate if you cannot patch yet
Setting LoginGraceTime 0 disarms the alarm entirely — no timer, no race — and it applies with a plain reload. The trade-off: unauthenticated connections can now sit open indefinitely, so the service becomes easier to exhaust with connection floods; pair it with firewall-level rate limiting or you've swapped one problem for a smaller, different one.
sudo sed -i 's/^#*LoginGraceTime.*/LoginGraceTime 0/' /etc/ssh/sshd_config && sudo systemctl reload sshdThe advisory-grade mitigation from Qualys and Red Hat; revert it once the patch lands.
03 Restrict exposure
Patched or not, sshd rarely needs to answer the entire internet. Limiting port 22 to your management networks at the host firewall shrinks the attack surface close to zero, and honestly it's worth keeping permanently — less internet in your auth logs is never a bad thing.
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.0.2.0/24 port port=22 protocol=tcp accept' && sudo firewall-cmd --reloadSubstitute your real admin range, and remove any broad any-source SSH allow rule.
06 Verification
Right, patched — but let's actually prove it, cos the version string is going to lie to us.
dpkg -l openssh-server | awk '/^ii/{print $3}'Debian/Ubuntu; the base version stays in the vulnerable range even after patching — the changelog check below is the proof.
rpm -q --qf '%{VERSION}\n' openssh-serverExpect 8.7p1 on RHEL 9 — the string does not move, so use the changelog check below as the proof.
The version string alone clears nothing on either family — the package changelog is the verdict:
zgrep -m1 6387 /usr/share/doc/openssh-server/changelog.Debian.gzProves the CVE-2024-6387 backport is installed; expect a dated changelog entry naming the CVE.
rpm -q --changelog openssh-server | grep -m1 6387RHEL-family equivalent; same proof against the rpm changelog.
sudo systemctl is-active sshdExpect "active" after the restart.
sudo sshd -T | grep -i logingracetimeMitigation path only: expect "logingracetime 0", i.e. the timer is disarmed.
07 Rollback
If the patched build misbehaves (rare, but it happens):
sudo apt-get install openssh-server=<previous-version> Debian/Ubuntu pin; take the exact version string from apt-cache policy openssh-server.
sudo dnf downgrade openssh-serverRHEL-family one-step downgrade; only if the patched build breaks authentication — re-check sshd_config and restart afterwards.
sudo sed -i 's/^LoginGraceTime 0/LoginGraceTime 120/' /etc/ssh/sshd_config && sudo systemctl reload sshdUndoes the mitigation by restoring the default two-minute grace timer.
Downgrading re-opens the vulnerability, obviously. Roll back only to buy time for a fix forward, and re-apply the LoginGraceTime 0 mitigation while you are on the old build.
08 References
- NVD — CVE-2024-6387
- Qualys disclosure — regreSSHion
- OpenSSH 9.8 release notes
- Red Hat CVE page — CVE-2024-6387
That's it — if I've got anything wrong or your distro does something daft, corrections and questions are welcome.
Ship the fix. Prove it’s closed.
If this runbook doesn’t fit your stack, send the CVE — an operator writes a verified path, usually within a business day. Or contribute your own and get co-authored credit.