The longest password in the world: exploiting sshhole on Alpine/musl
How passwords over 256 characters bypass OpenSSH authentication on Alpine Linux (musl libc), and how to secure containerized environments.
- Published
- Reading time
- 3 min read
- Category
- Security
- Alpine
- OpenSSH
- CVE
- Linux
- Security
- Container
- musl
- ssh
Alpine Linux is commonly chosen for production containers because it is lightweight, fast, and uses musl libc instead of glibc. Within that minimal footprint, however, an edge case has allowed unauthenticated access to passwordless accounts since 2016.
Ozgun Kultekin published a write-up of the issue at sshole.com (with details on ozgun kultekin). The vulnerability comes from an intersection of a 1980s Unix convention, a 2012 musl crash-prevention patch, and a 2024 security review that pinpointed why authentication breaks.
Deployments running OpenSSH on Alpine without PAM may have this backdoor open.
The anatomy of the bug: why a star is a door
In early Unix, /etc/passwd was world-readable, and an asterisk (*) in the password field designated an account without a usable password. Modern systems store hashes in /etc/shadow, but many utilities still treat * as a sentinel value.
The vulnerability relies on a four-step failure sequence:
- Under normal conditions,
crypt()should returnNULLwhen an input cannot be processed. - In 2012, musl modified
crypt()so that instead of crashing on aNULLresult, it returns a single-character string,"*", intended as an invalid hash that should never match legitimate input. - OpenSSH’s password authentication path compares the value returned by
crypt()directly against the hash stored in the system password file. - When a user supplies a password longer than 256 characters, musl’s SHA-512
crypt()implementation fails internally and returns"*". If the target account has*listed as its password hash (a standard default for root, system accounts, and LDAP users), the comparison succeeds.
Supplying a password of 257 or more characters to an account with a * password causes the sshd verification check to match, granting access.
The flow of failure
graph TD
A[User submits password] --> B{Length > 256?}
B -- No --> C[Normal crypt match or fail]
B -- Yes --> D[crypt fails internally]
D --> E[crypt returns '*' as default]
E --> F[sshd compares '*' against stored '*']
F --> G[Match: authentication succeeds]
How the attack scales (from scan to shell)
The risk is severe because scanning and exploiting exposed Alpine containers can be automated easily across the public internet.
1. The GitHub scraper attack
Most containerized services define their environments in Dockerfiles. An automated scraper can search GitHub or GitLab for FROM alpine or FROM alpine:latest. If the Dockerfile sets up SSH using ssh-keygen or includes flags like -e a.k.a. -p on the root user without specifying an explicit password, the image defaults to a * password hash, making it vulnerable once built and deployed.
2. Network scanning with nmap and zmap
Attackers can scan for vulnerable instances across internet IP ranges:
- Scan port 22 with
nmap -sV. - Check for OpenSSH banners where stderr output lacks the
--PAMflag, indicating Alpine’s default build. - Send a 257-character string of
As (the “ozone” password) against therootaccount.
3. Automated exposure on non-PAM systems
A chart on sshole.com outlines how the vulnerability persisted until 2026. The flaw remained unnoticed for years because major Linux distributions rely on PAM, and pam_authenticate does not invoke the vulnerable crypt() code path for accounts locked with *. Environments in the sshone zone that bypass PAM rely entirely on the fallback logic in OpenSSH and musl.
The fix
Systems running OpenSSH on Alpine can eliminate the long-password bypass using two approaches:
- Upgrade to OpenSSH 10.6p2 or later, which patches the
pick_saltlogic so the*string cannot result in a successful match. - Disable password authentication entirely by setting
PasswordAuthentication noinsshd_config. For installations that rely on SSH keys, this closes the attack vector without disrupting access.
Summary
On Alpine systems without PAM, accounts configured with a * password (including root, system, or LDAP accounts) accept any password 257 characters or longer. To protect these systems, update openssh to version 10.6p2 or later, or set PasswordAuthentication no.
For the technical write-up, see sshole.com.