OpenSSH has shipped emergency patches for a serious authentication bypass — dubbed 'SSHole' — that affects Linux systems built on musl libc without PAM (Pluggable Authentication Modules). On affected systems, certain accounts will accept any password between 257 and 1024 characters in length. That is not a theoretical crypto weakness or a race condition requiring nation-state tooling — it is a trivially exploitable condition that collapses password authentication on impacted hosts.
The population most at risk is Alpine Linux and other musl-based, minimal distributions — which is exactly what powers a large share of the world's container images, Docker hosts, embedded appliances, and lightweight cloud VMs. If your organization runs Alpine-based containers that expose SSH (jump boxes, CI/CD runners, git servers, vendor appliances built on Alpine base images), you should treat this as an urgent patching event. An attacker who can reach sshd on a vulnerable host and guess a valid username — root, admin, git, or any service account — can try arbitrary long passwords and walk straight in.
This post breaks down the affected configurations, how the flaw works from a defender's perspective, how to hunt for exposure and exploitation, and exactly how to remediate.
Technical Analysis
Affected Products and Platforms
| Component | Detail |
|---|---|
| Vulnerable software | OpenSSH sshd (versions prior to the emergency patch release — verify against the OpenSSH advisory and your distro security tracker) |
| Affected platform condition | Linux distributions using musl libc (not glibc) without PAM compiled in / enabled |
| Typical affected distros | Alpine Linux (default configuration — musl libc, no PAM), and other musl-based/minimal distros, embedded systems, and container base images |
| NOT affected (generally) | glibc-based distributions (Debian, Ubuntu, RHEL, Fedora, SUSE) where PAM handles password verification — but verify, do not assume |
| Attack vector | Network — remote, unauthenticated, requires only TCP reachability to the SSH service |
How the Vulnerability Works (Defender's View)
The root cause sits at the intersection of three conditions:
- musl libc's
crypt()behavior. musl's implementation of the legacycrypt()password-hashing function does not handle certain inputs the way glibc does. Critically,crypt()historically truncates or fails on long passwords, and musl's error/failure semantics differ from glibc's. - No PAM in the path. On mainstream distros, PAM mediates password verification and applies strict length limits and failure handling. When OpenSSH is built and run without PAM (
UsePAM no, or PAM absent at compile time — the default on Alpine),sshdfalls back to callingcrypt()directly and comparing the result against the shadow entry. - A comparison logic flaw. The vulnerable code path fails to properly handle the case where
crypt()returns an error or truncated result for over-length passwords. Instead of failing closed, the comparison can succeed — meaning any password in the 257–1024 character range is accepted for affected accounts.
Exploitation requirements from an attacker's perspective:
- Network access to port 22 (or wherever
sshdlistens) on a vulnerable host. - A valid username of an account in the affected state (accounts with locked or invalid password fields, and accounts using publickey-only auth, are less exposed — but any account with a password hash in
/etc/shadowon a musl/no-PAM system should be considered at risk). - A password string of 257–1024 characters — trivially generated.
No user interaction, no race window, no special tooling. This is the class of bug that gets folded into botnet scanners and opportunistic internet-wide exploitation within days of public disclosure — SSH is one of the most scanned services on the internet.
Exploitation Status
- Public disclosure: Patches were rushed out by the OpenSSH project following disclosure (reported via SecurityWeek).
- Weaponization risk: Very high. The exploitation primitive is simple, deterministic, and requires no special conditions beyond a vulnerable platform. Assume rapid incorporation into SSH scanning tooling and brute-force botnets.
- CVE / KEV status: Verify the assigned CVE identifier and CISA KEV listing against the OpenSSH official advisory and your distribution's security tracker — do not wait for KEV inclusion to act on an internet-facing SSH authentication bypass.
Detection & Response
The realistic detection surface here is twofold: (1) identifying vulnerable hosts in your estate (musl libc + sshd without PAM + unpatched OpenSSH), and (2) detecting suspicious SSH password authentications — particularly password logins to accounts that should be key-only, and authentication patterns consistent with long-password probes.
Sigma Rules
---
title: SSH Password Authentication Accepted on Potentially Non-PAM musl Host
description: Detects successful SSH password-based logins. On musl libc systems without PAM affected by the 'SSHole' OpenSSH bypass, any 257-1024 character password is accepted, so unexpected 'Accepted password' events — especially for accounts that should authenticate via publickey only — are a high-fidelity signal of exploitation.
author: Security Arsenal
date: 2026/04/06
status: experimental
references:
- https://www.securityweek.com/openssh-rushes-patches-for-sshole-authentication-bypass/
- https://attack.mitre.org/techniques/T1078/
logsource:
product: linux
service: sshd
detection:
selection:
Message|contains:
- 'Accepted password for'
filter_valid_accounts:
Message|contains:
- 'Accepted password for deploy'
- 'Accepted password for backup'
condition: selection and not filter_valid_accounts
falsepositives:
- Legitimate interactive password logins by administrators
- Inventory expected password-authenticating accounts and tune the filter accordingly
level: high
---
title: SSH Brute Force or Long-Password Probing Pattern Against sshd
description: Detects a burst of failed SSH password attempts followed by a success from the same source, consistent with an attacker probing the 'SSHole' authentication bypass (trying arbitrary long passwords against musl/no-PAM hosts) until one is accepted.
author: Security Arsenal
date: 2026/04/06
status: experimental
references:
- https://www.securityweek.com/openssh-rushes-patches-for-sshole-authentication-bypass/
- https://attack.mitre.org/techniques/T1110/
logsource:
product: linux
service: sshd
detection:
selection_failures:
Message|contains:
- 'Failed password for'
condition: selection_failures | count() by SourceIP > 5
timeframe: 10m
falsepositives:
- Users mistyping passwords
- Misconfigured automation with stale credentials
level: medium
KQL (Microsoft Sentinel — via Syslog/CEF ingestion)
If you forward Linux auth logs into Sentinel (via the Syslog/AMA connector), this hunt identifies successful password authentications on Alpine/musl hosts and correlates them with preceding failure bursts — the exploitation signature of SSHole probing.
// Hunt 1: Successful SSH password logins on Alpine/musl hosts with recent failure bursts from the same source
let lookback = 24h;
let SshFailures = Syslog
| where TimeGenerated > ago(lookback)
| where Facility =~ "auth" or Facility =~ "authpriv"
| where SyslogMessage has "Failed password"
| extend SourceIP = extract(@"from ([0-9a-fA-F\.\:]+)", 1, SyslogMessage)
| summarize FailCount = count() by Computer, SourceIP, bin(TimeGenerated, 10m)
| where FailCount >= 5;
Syslog
| where TimeGenerated > ago(lookback)
| where SyslogMessage has "Accepted password"
| extend SourceIP = extract(@"from ([0-9a-fA-F\.\:]+)", 1, SyslogMessage)
| extend TargetUser = extract(@"Accepted password for (invalid user )?([^ ]+)", 2, SyslogMessage)
| join kind=inner SshFailures on Computer, SourceIP
| project TimeGenerated, Computer, TargetUser, SourceIP, FailCount, SyslogMessage
| order by TimeGenerated desc;
// Hunt 2: Any password-auth success for accounts expected to be key-only (tune the account list)
Syslog
| where TimeGenerated > ago(24h)
| where SyslogMessage has "Accepted password for"
| where SyslogMessage has_any ("root", "git", "admin", "alpine")
| project TimeGenerated, Computer, SyslogMessage, HostIP, ProcessName
| order by TimeGenerated desc;
Velociraptor VQL
Use this artifact to triage Linux endpoints at scale for exposure — musl libc presence, sshd running without PAM, and an unpatched OpenSSH build.
-- SSHole exposure triage: identify musl libc hosts running sshd without PAM
-- Collect sshd process, libc linkage, and UsePAM configuration in one pass
LET sshd_procs = SELECT Pid, Name, CommandLine, Exe, Username
FROM pslist()
WHERE Name =~ 'sshd'
LET pam_config = SELECT
read_file(filename='/etc/ssh/sshd_config') AS SshdConfig
FROM scope()
LET libc_check = SELECT
read_file(filename='/usr/bin/ldd') AS LddPresence,
stat(filename='/lib/ld-musl-x86_64.so.1') AS MuslLoader
FROM scope()
SELECT * FROM sshd_procs
For a server-side fleet hunt, wrap the logic in a SELECT ... FROM foreach(row=...) over your client list, and post-process the sshd_config content for UsePAM no (or absence of the directive on a non-PAM build) plus confirmation of the musl loader at /lib/ld-musl-*.so.1. A host with musl + sshd + no PAM is your priority patching queue.
Remediation / Verification Script (Bash)
Run this on suspected Linux hosts (or bake it into your configuration management / EDR remote shell) to determine exposure and apply mitigations:
#!/bin/bash
# SSHole (OpenSSH musl/no-PAM auth bypass) — exposure check and mitigation
# Run as root. Tested for Alpine/musl systems; safe to run on glibc hosts.
echo "=== [1] libc identification ==="
if ldd --version 2>&1 | grep -qi musl; then
echo "[!] musl libc DETECTED — host is in the potentially affected class"
MUSL=1
else
echo "[+] glibc (or other) libc detected — likely not affected, verify anyway"
MUSL=0
fi
echo "=== [2] OpenSSH version ==="
ssh -V 2>&1
sshd -V 2>&1 || /usr/sbin/sshd -? 2>&1 | head -1
echo "=== [3] PAM status ==="
if grep -Eq '^\s*UsePAM\s+yes' /etc/ssh/sshd_config 2>/dev/null; then
echo "[+] UsePAM yes — PAM mediates password auth (lower risk)"
else
echo "[!] UsePAM is NOT enabled — direct crypt() path may be in use"
fi
ldd /usr/sbin/sshd 2>/dev/null | grep -i pam || echo "[!] sshd binary not linked against libpam"
echo "=== [4] Password-authenticating accounts (shadow entries) ==="
awk -F: '($2 !~ /^[!*]/ && $2 != "") {print $1" has a password hash set"}' /etc/shadow
echo "=== [5] Recent successful password logins (review for anomalies) ==="
grep -h "Accepted password" /var/log/auth.log /var/log/messages /var/log/secure 2>/dev/null | tail -20
echo "=== [6] Mitigation options ==="
echo " a) PATCH FIRST: apk update && apk upgrade openssh (Alpine)"
echo " b) Interim: disable password auth entirely ->"
echo " sed -i 's/^#\\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config && rc-service sshd restart"
echo " c) Lock unused password accounts: passwd -l <user>"
echo " d) Restrict exposure: firewall sshd to known management IPs"
Remediation
- Patch immediately. Apply the emergency OpenSSH update from your distribution. On Alpine:
apk update && apk upgrade openssh, then restart sshd (rc-service sshd restart). Track the exact fixed version in the OpenSSH security page and your distro advisory — do not consider a host remediated until the patched version is confirmed running (ssh -V). - Inventory your musl exposure. Alpine and musl-based images hide in container base images, embedded appliances, and vendor tooling. Scan your image registry and asset inventory for Alpine-based hosts exposing TCP/22. This class of bug is a strong argument for maintaining a libc/distro attribute in your CMDB.
- Disable password authentication wherever possible.
PasswordAuthentication noinsshd_configeliminates the vulnerable code path entirely. Public-key-only SSH should already be your baseline for any internet- or DMZ-facing host — this incident is the case study for why. - Lock dormant password accounts. Any account with a hash in
/etc/shadowthat doesn't need interactive login should be locked (passwd -l) or have its shell set to/sbin/nologin. - Reduce network exposure. sshd should never be internet-reachable without compensating controls: source IP allowlisting, VPN/bastion-only access, or at minimum fail2ban-style rate limiting. Treat any currently internet-exposed Alpine sshd as presumed probed and review auth logs retroactively.
- Hunt retroactively. Review 30+ days of auth logs for
Accepted passwordevents on musl hosts — especially successes for service accounts, successes preceded by failure bursts, or logins from sources with no business touching SSH. A successful 'SSHole' login looks like a normal password login in logs; context is your only discriminator. - Rebuild vulnerable container images. Patching a running container is not remediation — update the base image, redeploy, and verify no long-lived containers are still running the vulnerable sshd build.
Bottom Line
'SSHole' is a reminder that edge-case platform combinations — musl libc, no PAM, a specific crypt() code path — can produce catastrophic, low-skill authentication bypasses in the internet's most ubiquitous remote access daemon. The defensive playbook is straightforward but time-sensitive: find every musl-based host running sshd, patch OpenSSH, kill password authentication, and hunt your auth logs for password logins that should never have succeeded. If you do nothing else this week, confirm whether your container estate and embedded fleet run Alpine with SSH exposed — that is where this bug lives.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.