Pull to refresh
Logo
SSH password bypass exposes musl-based Linux systems

SSH password bypass exposes musl-based Linux systems

Force in Play

A quirk in musl's crypt() lets any password over 256 characters unlock key-only accounts on Alpine and other musl systems.

Overview

Updated 1 hour ago

Any password longer than 256 characters will log an attacker into an account set up for SSH-key login only, on Alpine Linux and other systems that pair the musl C library with OpenSSH. The flaw, nicknamed *sshole, has worked that way since 2016.

Two ordinary design choices collide. musl's crypt() returns an asterisk when it cannot hash a password, and OpenSSH borrows another account's salt to avoid revealing which usernames exist. A locked account's `*` then matches the failed hash. OpenSSH released version 10.6p2 and Alpine shipped a patch on November 5. No CVE has been assigned.

Why it matters

Alpine runs in more than a billion Docker pulls and countless routers and embedded devices, many of which will never be patched.

Questions about this story

Free account needed to ask — your question is kept and asked for you right after sign-up. Answers are public.

No questions yet — be the first to ask.

Key Indicators

256
Characters needed to trigger the bypass
musl's SHA-512 crypt refuses inputs longer than 256 bytes and returns an asterisk.
22M
Systems with SSH open on port 22
Shodan count cited by Detectify; only a fraction meet the exploit conditions.
1B+
Alpine Docker Hub base image downloads
The container image is the most widely distributed musl system.
10 years
Time the exploitable configuration existed
OpenSSH's salt-borrowing fix landed in July 2016.

Voices

Curated perspectives — historical figures and your fellow readers.

Sign up to generate historical perspectives on this story.

People Involved

Organizations Involved

Timeline

August 2012 November 2026

7 events Latest: Yesterday
Tap a bar to jump to that date
  1. Researcher discloses *sshole; patches ship

    Latest Disclosure

    Özgün Kültekin publishes the bypass. OpenSSH releases 10.6p2 and Alpine issues an update the same day.

  2. OpenSSH review fixes pick_salt()

    Code change

    A security review patches the salt-selection function. The exploitable comparison sits four lines below.

  3. Alpine 3.16 moves root to '*'

    Code change

    Locking root with '!' broke SSH keys without PAM, so Alpine switched the field to '*'. Key-only cloud images become the vulnerable configuration.

  4. Alpine Docker images ship with no root password

    Vulnerability

    CVE-2019-5021 exposes containers with an empty root password. Alpine locks root, first with '!' and later with '*'.

  5. OpenSSH borrows salts to hide usernames

    Security fix

    The fix for CVE-2016-6210 hashes passwords against another account's salt for invalid users. That path later reaches the '*' comparison.

  6. musl caps SHA-512 passwords at 256 bytes

    Code change

    To prevent long-password denial-of-service, musl refuses inputs over 256 bytes and returns '*'. The cap becomes the exploit's trigger.

  7. musl swaps NULL for an asterisk

    Code change

    A musl commit makes crypt() return '*' when hashing fails, so programs compare against a wrong password instead of crashing.

Scenarios

1

Automated scanners find and exploit unpatched Alpine hosts

Possible Resolves by Feb 5, 2027

Discussed by: Check Point and Detectify researchers

With roughly 22 million SSH-exposed systems and a one-connection exploit, scanners can test at scale. Any host with a `*` account and another account holding a real SHA-256 or SHA-512 hash is vulnerable. A confirmed compromise would turn a theoretical bypass into an active incident.

2

CVE assigned as vendors coordinate patches

Likely Resolves by End of 2026

Discussed by: security researchers and distribution maintainers

No CVE existed at disclosure. An assignment from MITRE or a CNA would trigger formal tracking, downstream patch requirements and vulnerability scanners adding a check. OpenSSH and Alpine have already shipped fixes, so a CVE would mainly widen the patch mandate.

3

OpenWrt, buildroot and Yocto confirm exposure

Possible Resolves by Jan 31, 2027

Discussed by: the discoverer and security analysts

The discoverer named these projects as affected, but OpenWrt's default SSH server is Dropbear, not OpenSSH. Confirmation from at least two would widen the patch surface to embedded firmware that is rarely updated.

Historical Context

3 moments from history that rhyme with this story — and how they unfolded.

July 2016

CVE-2016-6210 and the salt-borrowing fix (2016)

OpenSSH leaked which usernames existed because hashing a real user's password took milliseconds longer than rejecting a fake one. The fix made sshd borrow a salt from another account and hash the supplied password anyway, so every rejection took similar time.

Then

The username-timing leak closed.

Now

The borrowed-salt path became the route by which a 257-character password reaches musl's '*' return.

Why this matters now

Without this workaround, sshd would reject a '*' account before hashing and the bypass would not work.

2019

CVE-2019-5021: Alpine's empty root password (2019)

Alpine's official Docker images shipped with root's password field empty, letting anyone log in as root inside the container. The project locked root, first with '!' and then, in 2022, with '*'.

Then

Containers no longer had a blank root password.

Now

The '*' lock preserved SSH-key logins but created the exact account state the 2026 bypass exploits.

Why this matters now

It explains why Alpine's default accounts carry '*' rather than a real hash.

April 2014

Heartbleed (2014)

A missing bounds check in OpenSSL's heartbeat extension let attackers read up to 64 kilobytes of server memory per request, including private keys. The library sat inside a large share of the internet's HTTPS servers.

Then

Sites raced to patch and reissue certificates.

Now

It became the reference case for how a flaw in a shared library propagates across millions of systems that cannot all be updated.

Why this matters now

The *sshole bug follows the same pattern: a small library decision reaches far beyond the project that made it.

Sources

(9)