Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

OpenSSH 10.6p2: sshd on musl without PAM accepted any 257 to 1024 byte password for accounts marked *

Portable OpenSSH 10.6p2 shipped on November 5, 2026 with a workaround for a password authentication bypass on Linux systems that use musl libc with PAM disabled. Alpine published fixed packages for 3.16 through edge the same day.

Pl. 94 · section drawing generated from the slug “openssh-10-6p2-musl-password-bypass”

The OpenSSH team released Portable OpenSSH 10.6p2 on November 5, 2026. The release carries a critical workaround for Linux systems that run sshd on musl libc with PAM disabled. Alpine Linux, the most common distribution in that group, published a security advisory and fixed packages for every branch from 3.16 to edge on the same day. Özgün Kültekin of Wakefield reported the bug and published a walkthrough at sshhole.com.

An attacker who can reach your SSH port needs one connection and no valid password. Alpine's advisory says the attack "works every time, and needs no retries."

The mechanism

Without PAM, sshd checks a password by running crypt() on the attempt and comparing the output with the field in /etc/shadow. A key-only account stores * there, a value no hash can equal. Since the fix for CVE-2016-6210, sshd hashes attempts against those accounts anyway, with a salt borrowed from another account, so a timing check can't reveal which users exist.

musl's crypt() rejects keys longer than 256 bytes. The musl developers added that cap in 2012 with SHA-512 crypt, which gets slower as the password grows. On failure, musl returns the string * instead of NULL. Put the pieces together:

  1. You send a password between 257 and 1024 bytes for a key-only user.
  2. sshd borrows the $6$ or $5$ salt of a user who has a real password.
  3. musl rejects the oversized key and returns *.
  4. sshd compares * with the stored * and logs you in.

The OpenSSH notes put the root cause outside sshd, and the team chose to block it in sshd because sshd is the path an attacker reaches.

Are you affected

Alpine lists five conditions. All must hold:

Conditions for the bypass, from the Alpine advisory
ConditionAlpine default
sshd built on muslYes
openssh-server without PAM, or openssh-server-pam with UsePAM noYes, the plain package has no PAM
PasswordAuthentication yesYes, the OpenSSH default
An account with * as its password fieldroot:* since about 3.16, plus key-only users
Another local account with a $5$ or $6$ hashNo, until someone sets a password

The last row matters most. A fresh machine with no passwords set stays safe. Once you set one console password for a break-glass login, every * account opens up.

The official tiny-cloud images (qcow2, VHD and AMI) from 3.18.11 through 3.24.3 ship an alpine user with a * field and passwordless doas. The advisory spells out the chain: a shell as alpine, then root. PermitRootLogin prohibit-password keeps root itself out, but not a user who can doas.

You're safe on glibc distributions, on anything that routes passwords through PAM, on containers that don't run sshd, and on cloud-init images, which write PasswordAuthentication no.

Fix it

Upgrade and restart. The package upgrade leaves the old daemon running.

apk upgrade -U -a
rc-service sshd restart

Alpine 3.21.10, 3.22.8, 3.23.8 and 3.24.4 carry the fixed package. Edge gets 10.6_p2-r0; 3.24 gets 10.3_p1-r2. Alpine also backported patches to 3.16 through 3.21, though those branches no longer get regular updates.

If you can't upgrade today, turn off password logins:

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 works from Alpine 3.19 onward. On older releases, edit /etc/ssh/sshd_config instead, and keep your current session open until a fresh key login succeeds.

Check for a break-in

Search /var/log/messages for Accepted password for lines that name alpine, root or any key-only user. Review doas use, new accounts and recent changes to authorized_keys. Alpine's guidance: if you can't rule out a login, treat the machine as compromised.

This week

  1. List every host and image that runs sshd on Alpine, OpenWrt, Buildroot or Yocto. Include build agents, bastions and the odd container that runs sshd for debugging.
  2. Upgrade openssh and restart sshd, or drop in PasswordAuthentication no until you can.
  3. Rebuild any AMI, VHD or qcow2 image based on a tiny-cloud release older than 3.24.4.
  4. Grep the logs for password logins to accounts that have no password, going back as far as your retention allows.
  5. Note the scp change while you're in the release notes: scp -R now prints a deprecation warning, and a later release will ignore the flag.

Volodymyr Chornous