
On November 5, 2026, OpenSSH shipped 10.6p2 to close an authentication bypass in sshd on musl-based Linux. On an affected machine, an account that should never accept a password will accept almost any password between 257 and 1,024 bytes long. It takes one connection and works every time.
The bug was reported by Özgün Kültekin of Wakefield, who wrote it up with a great timeline at sshhole.com. Here's the short version for developers.
How it works
Nothing here is a single mistake. Four old, reasonable decisions line up:
*means "no password". In/etc/shadow, a field that is just*can never match any hash. This is how key-only users and many service accounts are marked.sshd borrows a salt. Without PAM, sshd checks a password by hashing it with
crypt()and comparing the result to the stored field. Since the 2016 fix for a user-enumeration timing leak (CVE-2016-6210), if that field is too short to contain a salt, sshd borrows another account's salt so the check takes as long as a real one.musl's
crypt()returns*on failure. Where POSIX says to return a null pointer on error, musl returns*. Its$5$and$6$implementations refuse keys longer than 256 bytes (a DoS limit), so an oversized password makescrypt()fail, and fail with*.Compare
*to*. sshd sees that the "hash" it computed equals the stored field, and lets you in.
sequenceDiagram
participant A as Attacker
participant S as sshd
participant C as musl crypt()
A->>S: Password login as a * user, 300 characters
S->>C: crypt(password, borrowed salt)
C-->>S: * (error, key is over 256 bytes)
S-->>A: Stored * equals *, login acceptedWho is affected
All of these must be true, per Alpine's advisory:
sshd runs on musl without PAM: Alpine's
openssh-server, oropenssh-server-pamwithUsePAM noPasswordAuthenticationisyes, which is the OpenSSH defaultAn account's password field is exactly
*: key-only users (created withadduserand no password, orusermod -p '*'), directory users coming through musl-nscd, root (Alpine shipsroot:*, but the defaultPermitRootLogin prohibit-passwordprotects it), and thealpineuser in tiny-cloud imagesAt least one other local account has a
$5$or$6$hash. One is enough, and it makes every password-less account reachable
Not affected: locked accounts (!), systems with PasswordAuthentication no, openssh-server-pam with UsePAM yes, containers that don't run sshd, glibc systems, and Dropbear.
The cloud images deserve a closer look. Official tiny-cloud images from 3.18.11 through 3.24.3 ship the alpine user with passwordless doas. They are safe on first boot, but become exploitable as soon as any $6$ hash exists on the machine, for example after someone sets a console password or user-data adds a user with hashed_passwd. From there it's a password bypass, then doas to root.
What to do
Update, then restart. Upgrading the package does not restart a running sshd:
apk upgrade -U -a
rc-service sshd restartFixed openssh packages exist for edge and every branch back to 3.16 (for example 10.0_p1-r11 on 3.22 and 9.9_p2-r1 on 3.21). The full table is in the advisory.
If you can't update yet, turn off password logins. Keep your current session open and confirm key login works first:
mkdir -p /etc/ssh/sshd_config.d
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
sshd -t && rc-service sshd restart
sshd -T | grep -i passwordauthentication # expect: passwordauthentication noThe default config reads sshd_config.d only from 3.19 onward, and existing PasswordAuthentication lines in sshd_config, including inside Match blocks, can still win. The advisory has a sed variant that covers those cases, and the final sshd -T line tells you whether it worked.
Then check for signs of abuse. On Alpine, look for Accepted password for lines in /var/log/messages that name an account with no password:
grep "Accepted password for" /var/log/messagesIf you find one you can't explain, treat the host as compromised: review doas use, new users, changed files, and authorized_keys.
The takeaway
OpenSSH's release notes call 10.6p2 a workaround in sshd and say the root cause sits outside it. The advisory said no CVE had been assigned yet; CVE-2026-123158 has since been widely reported, so check NVD for the current record.
The lesson goes beyond SSH: an error return should never be able to look like valid data.
Comments(0)
Join the discussion by logging into your account.
No comments yet. Be the first to comment!