🚀 New: chi (χ) — an open-source autoresearch harness for fleets of LLM coding agents. Read the announcement.

OpenSSH Accepted a 300-Byte Password for Accounts With No Password. The Bug Is in musl and Alpine's Shadow File

CVE-2026-123158 (sshole): on musl systems without PAM, a 257 to 1024 byte password logs in to any account whose shadow field is '*'. How two old behaviors combine, who is exposed, and why upgrading the package is not enough.

Contents

A password of 257 to 1024 bytes will log in to any account whose /etc/shadow field is *, on an sshd that is linked against musl and runs without PAM. That is CVE-2026-123158, nicknamed “sshole” by its reporter, Özgün Kültekin of Wakefield. OpenSSH shipped 10.6p2 on November 5 with a workaround, and Alpine published fixed packages for every branch from 3.16 to edge the same day.

The interesting part is that no single component is wrong in isolation. Two decisions made years apart agree on one character.

The two behaviors

When sshd has no PAM, it verifies a password itself: hash the attempt with crypt() using the stored salt, then compare to the shadow field. An account with no password has * there, which no real hash can equal.

The first behavior is in OpenSSH. According to the researcher’s write-up, a 2016 change (commit 9286875a7) handles invalid users by hashing against a fake salt, so that the response time does not reveal whether an account exists. The write-up says this path also applies to real users whose field is *. The attempt is hashed using another account’s salt, and the result is compared to the stored field.

The second is in musl. Per the same write-up, musl’s crypt() returns the string * on failure instead of NULL, and its SHA-256 and SHA-512 implementations reject keys longer than 256 bytes (KEY_MAX). Both date from 2012.

Put them together. A password over 256 bytes makes musl’s SHA-512 crypt fail, crypt() returns *, and sshd compares * to a stored *. They match. The login is accepted. The attacker never needs to know anything about the account.

One more condition comes from the Alpine advisory: sshd borrows a salt from another account, and the exploit needs at least one local account with a $5$ or $6$ hash for that to work. Almost every real system has one.

Who is reachable

Alpine’s advisory lists the conditions, and all must hold:

  • PasswordAuthentication yes, which is the OpenSSH default.
  • A non-PAM sshd build, or openssh-server-pam with UsePAM no.
  • An account with * as its password field.
  • At least one local account with a $5$ or $6$ hash.

The third condition is wider than it sounds. Alpine’s advisory names root:* in base images since about 3.16, key-only users created with adduser without a password or usermod -p '*', directory-service users via musl-nscd, and the alpine user in tiny-cloud images (3.18.11 through 3.24.3). The write-up traces the * on root to an Alpine change in 3.16 that switched root from ! to * so key login keeps working without PAM.

That detail explains why locked accounts are not affected. A field of ! is never produced by a failed crypt. The convention that makes key-only login work on a no-PAM system is the same one that makes this exploitable.

Root is protected by default, because PermitRootLogin prohibit-password refuses password logins regardless. It is exposed with PermitRootLogin yes, or indirectly: the researcher notes the alpine cloud user has passwordless doas, which makes it effectively root.

Not affected, per the researcher: glibc distributions that authenticate through PAM, Dropbear and OpenBSD. The researcher says sshd builds across glibc and musl, with and without PAM and shadow, were tested with about 17,600 crafted logins, and only musl without PAM disagreed with the others. That is the researcher’s result and I have not reproduced it. The write-up also names OpenWrt, Buildroot and Yocto as musl environments to check, and Alpine-based Docker images only matter if they run sshd.

What 10.6p2 changes

The OpenSSH release notes call it a workaround for a password authentication bypass affecting some Linux systems built without PAM and using musl, and state that the root cause lies outside sshd but sshd can be hardened against it. I read only the first part of that page, so I cannot describe the exact patch. The notes do not say sshd now rejects oversized passwords, so I will not claim it does.

This matters for the fix path. Alpine’s stable-branch packages carry a patch for the same problem rather than a version jump: 3.22 gets 10.0_p1-r11, 3.23 gets 10.2_p1-r1, 3.24 gets 10.3_p1-r2, and so on. If you pin by version number, a version like 10.3_p1 does not tell you whether you are fixed. The revision does.

Upgrading is not enough

The advisory says directly: “Upgrading the package alone does not replace the running daemon.” sshd keeps running the old binary image until restarted. On Alpine:

apk upgrade -U -a
rc-service sshd restart

The reporting on the exploitation, from Help Net Security citing Previdian, is that the first attempt appeared less than nine hours after CVE publication, and that a honeypot running real Alpine and OpenSSH was rooted. The observed attempts used oversized passwords and ran id, uname and hostname. That is a third-party honeypot report, not something I verified. Its practical meaning is that a patched package on disk and an unrestarted daemon is still an exposed host.

If you cannot update right now, the workaround is to turn passwords off. From Alpine’s advisory:

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

The drop-in directory is read by default from Alpine 3.19 onward. The advisory’s full version also edits /etc/ssh/sshd_config directly. Confirm key login works from a second session before you restart.

Checking whether anyone got in

Alpine’s guidance is to search /var/log/messages for Accepted password for lines that name passwordless accounts, which on a key-only host should never appear at all. Also review doas usage, new users and authorized_keys changes. If you cannot rule out a login, treat the host as compromised.

For fleets, the cheap audit is the shadow file itself. Any field equal to * on a host that exposes sshd with password authentication enabled is a target, whether or not you ever intended password login to exist. PasswordAuthentication no on key-only hosts was already the right setting. This bug is a concrete reason it is not optional hardening.

Sources