Alpine Linux OpenSSH Password Authentication Bypass: One Connection, No Password

One connection, a very long password, and a key-only account on Alpine Linux can be logged into with no valid password at all. Here is the exact condition that triggers it, who is clear, and the two commands that close the hole.

Binary Buddies · 5 min read · 0 views
An open SSH port on an Alpine server at nightA server rack glowing against a dark mountain sky, one open port flagged in signal colour while a long stream of characters pours through it.

If you run sshd on Alpine Linux, the short version is: update openssh now and restart the daemon, or set PasswordAuthentication no and restart it. Either closes a hole that lets anyone who can reach your SSH port log in without knowing a password at all.

The bug is not a brute force or a timing trick. It takes one connection, works every time, and needs no retries. An attacker who knows the name of a key-only account — one whose password field is * — can authenticate as that account as long as the machine has at least one other user with a $5$ or $6$ password hash. A single real password anywhere on the box makes every passwordless account reachable.

Alpine's advisory, published on 5 November 2026, traces it to how sshd built without PAM compares passwords, and to a quirk of musl's crypt(). Details also live in the OpenSSH 10.6p2 release notes. No CVE identifier had been assigned at the time of writing.

Key takeaways

  • Non-PAM sshd on Alpine can be logged into as a passwordless account with no valid password supplied.
  • Two conditions are needed: a target account with * in its password field, and at least one account with a $5$/$6$ hash elsewhere on the machine.
  • Fixed packages ship in 3.21.10, 3.22.8, 3.23.8 and 3.24.4; upgrading does not restart the running daemon, so you must restart it yourself.
  • Containers without sshd, systems with PasswordAuthentication no, and openssh-server-pam with UsePAM yes are not affected.
  • The official tiny-cloud images are safe on first boot but become exploitable the moment any $6$ hash appears.

What actually goes wrong

When sshd is built without PAM, it checks a password by hashing the attempt with the C library's crypt() function and comparing the result to the stored password field. For an account whose stored field is too short to contain a salt — the random prefix that a hash needs — sshd borrows the salt from another account. That is where the trouble begins.

musl's crypt() returns the literal string * as an error indicator when the supplied key is longer than 256 bytes. And * is exactly what the stored password field contains for every account that has no password set. So if an attacker sends a password between 257 and 1024 bytes long, crypt() fails and hands back *, which then compares equal to the stored * — and the login is accepted.

The two ends of the comparison meet in the middle on a value that means "error", not "match". That is why the attack is deterministic: the long password is not being guessed, it is being used to force the error string.

How the long password forces a false matchA flow showing a long password passing through crypt, returning the error string star, which equals the stored star field and is accepted.Password 257-1024 bytessent by attackermusl crypt()key too longreturns "*"error indicatorstored field"*""*" == "*"login accepted
The long password makes crypt() return the same string the passwordless account already stores.

Exactly who is affected

You are affected if all of the following hold at once. You run the Alpine openssh-server package, which is built without PAM, or you run openssh-server-pam with UsePAM no. PasswordAuthentication is yes, the OpenSSH default unless you changed it. The machine has at least one account whose password field is *, and at least one local account with a $5$ or $6$ password hash.

The accounts with * are more common than they sound. Since roughly Alpine 3.16 the base image ships root:*. Any key-only user created with adduser without a password, or set with usermod -p '*', qualifies. So do users coming from a directory service through musl-nscd — nslcd, winbind, sssd — because they have no shadow entry at all.

Root deserves a note of its own. OpenSSH's default PermitRootLogin prohibit-password protects root, so root is only directly reachable if you have set PermitRootLogin yes. That is cold comfort if another account that can log in is able to become root, for example through doas.

Who is not affected

Several common setups are clear. Docker and other container users who do not run sshd inside the container are unaffected — no daemon, no attack surface. Systems with PasswordAuthentication no are safe, and so are cloud images configured through cloud-init, because cloud-init writes PasswordAuthentication no.

On the PAM side, openssh-server-pam with UsePAM yes is not affected; it is only the UsePAM no case that is. Locked accounts are safe too: those with ! as the password field in /etc/shadow, shown as a line starting user:!:, cannot log in by password or key. And a machine where no account carries a $-style hash never meets the second condition, so there is nothing to borrow a salt from.

Dawn over the Alpine release lineA ridge of mountains at first light, with one peak lit in the signal colour and faint package versions suggested as distant terraces.

The fix: update and restart

The primary fix is the package update. Run apk upgrade -U -a. The fixed package lands in Alpine 3.21.10, 3.22.8, 3.23.8 and 3.24.4. Alpine's release announcement lists the exact fixed package versions per branch.

The step people miss is the restart. Upgrading the package on disk does not replace the daemon already running in memory. You have to restart it yourself with rc-service sshd restart. Until you do, the vulnerable process keeps answering connections even though the fixed binary is sitting on disk.

If you cannot update yet

Where you cannot patch immediately, disabling password authentication closes the hole on its own. Before touching anything, confirm your SSH key login works and keep your current session open until you have tested a brand-new login — a mistake here can lock you out.

  1. Create a drop-in

    mkdir -p /etc/ssh/sshd_config.d then echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf. Alpine's default sshd_config reads that directory from 3.19 onward; older releases ignore it, which is why the next step matters.

  2. Rewrite the main config

    A sed -i.bak command changes yes to no on every PasswordAuthentication line in /etc/ssh/sshd_config, whatever the spacing and including lines inside a Match block. It also inserts PasswordAuthentication no at the top for the case where no such line existed, and saves the original as sshd_config.bak.

  3. Validate and restart

    Run sshd -t && rc-service sshd restart. Then confirm with sshd -T | grep -i passwordauthentication, which should print passwordauthentication no.

To undo the change later, delete /etc/ssh/sshd_config.d/00-no-passwords.conf and copy sshd_config.bak back over sshd_config.

The tiny-cloud image trap

The official tiny-cloud images — the qcow2, VHD and AMI artifacts — from 3.18.11 through 3.24.3 ship an alpine user with a * password field and passwordless doas. On first boot they are safe, because no account yet carries a $-style hash, so the second condition is absent.

They turn exploitable the moment any $6$ hash appears on the machine. That can happen quietly: an admin sets a console password, or user-data adds a user with hashed_passwd. From there an attacker gets a shell as alpine and uses the passwordless doas to become root. Images built from 3.21.10, 3.22.8, 3.23.8, 3.24.4 and later include the fixed package; images from earlier point releases do not, so on every running instance you still need to update openssh or disable password authentication.

Tiny-cloud image safe until a hash appearsTwo states of a cloud instance: safe on first boot with no hash, then exploitable once a dollar-six hash is added.First bootalpine user has "*"no $-style hash yetSafeAfter a $6$ hashconsole pw or user-datashell as alpine, then doasExploitablehash added
The condition that flips the instance is a single hashed password being written anywhere on it.

How to tell if you were hit

Check /var/log/messages for sshd lines reading Accepted password for an account that has no password — alpine, root, or any key-only user. An accepted password for an account that was never given one is the clearest signature of this attack.

Widen the review from there. Look at recent doas use, recently created users, new files, and any additions to authorized_keys on machines that were exposed. The advisory is blunt about the judgement call: if you cannot rule out a login, treat the machine as compromised. Rebuilding from a clean image is safer than hoping a single log line tells the whole story.

Scope, gaps and what to watch

The flaw was present across a wide range of releases. Alpine says it affects every release it checked — 3.21 through 3.24 and edge — plus the older releases that no longer receive regular updates. Even those out-of-support branches got fixed packages all the way back to 3.16, and 3.21 reached its own end of support on 1 November 2026, days before the advisory.

257-1024password byte range that triggers it
1connection needed, no retries
3.16earliest branch with a fixed package

Two things are worth tracking. First, no CVE identifier had been assigned when the advisory went out; one may land later, which matters for scanners and inventory tools that key off CVEs rather than package versions. Second, the root cause sits partly in musl's crypt() returning * for over-long keys, so watch the OpenSSH 10.6p2 release notes and musl's own channels for the authoritative description if you need to reason about other musl-based systems.

The practical lesson outlasts this particular bug: an apk upgrade that reports success is not the end of the job for a long-running service. Until sshd -T and a fresh login confirm the state you expect, assume the daemon you can reach is the one that was running before you patched.

Questions readers ask

Does upgrading the openssh package fix the running server?

No. The package on disk is replaced, but the process in memory keeps running the old binary. Run rc-service sshd restart after apk upgrade, then verify with a new login.

I use openssh-server-pam. Am I affected?

Only if you set UsePAM no. With UsePAM yes you are not affected. The plain openssh-server package is built without PAM and is affected by default.

My containers run Alpine but no sshd. Do I need to act?

No. The attack needs a reachable sshd. Containers and other systems that do not run the daemon have no exposure to this specific flaw.

Is root login a risk even with the default config?

By default PermitRootLogin prohibit-password keeps root from being reached directly. The danger is indirect: a passwordless account an attacker can log into may escalate to root through doas.

How do I confirm password authentication is really off?

Run sshd -T | grep -i passwordauthentication. It should print passwordauthentication no. If it prints yes, the config did not take effect or the daemon was not restarted.

This article draws on Transport security has blocked a cleartext HTTP and answers to it (1, 2), on the Stack Exchange network, licensed under CC BY-SA 4.0.

  • #Alpine Linux security
  • #PasswordAuthentication no
  • #musl crypt
  • #sshd vulnerability
  • #tiny-cloud images

Comments

Add a comment
Sign in with Google to join the conversation