[ under non-PAM configurations.
In musl libc, the SHA-256 (`$5$`) and SHA-512 (`$6$`) implementations of `crypt()` enforce a 256-byte input cap. Passwords exceeding 256 bytes cause `crypt()` to return a literal asterisk (`"*"`), rather than `NULL`.
2. **OpenSSH Salt Borrowing (`pick_salt`):**
When OpenSSH runs without PAM (`UsePAM no`), it relies directly on `crypt()`. For accounts without a set password (`/etc/shadow` entry is `*`, typical of locked, service, or SSH-key-only accounts), OpenSSH borrows a valid `$5$` or `$6$` salt from another system account to prevent timing-based user enumeration (CVE-2016-6210).
encrypted_password = xcrypt(password, salt);
return encrypted_password != NULL && strcmp(encrypted_password, pw_password) == 0;
When an attacker submits a password longer than 256 characters (e.g. 300 bytes of `'A'`), musl `crypt()` returns `*`. Because the target's shadow record `pw_password` is also `*`, the comparison succeeds (`strcmp("*", "*") == 0`), granting immediate authenticated access.
The OpenSSH preauth monitor initializes the salt cache during its first authentication cycle. An initial probe attempt within the same connection primes `pick_salt()`, allowing the subsequent overflow payload to match.
All conditions must be present simultaneously:
- **musl C library** (Alpine Linux, OpenWrt, Void musl, etc.).
- **OpenSSH compiled/configured without PAM** (`UsePAM no`).
- **Password authentication enabled** (`PasswordAuthentication yes`).
- **Target user has `*` in `/etc/shadow`** (e.g. `alpine`, `ctf`, `deploy`, or `root` if `PermitRootLogin yes`).
- **At least one other account exists** with a valid `$5$` or `$6$` hash in `/etc/shadow`.
## Operational Note: OpenSSH 9.8+ `PerSourcePenalties`
OpenSSH 9.8+ includes `PerSourcePenalties` active by default. Rapid consecutive failed authentications from the same source IP trigger an automatic penalty window (15–30 seconds), causing sshd to drop new connections immediately:
srclimit_penalise: activating ipv4 penalty of 16.502 seconds for penalty: failed authentication
drop connection from [IP] on [PORT] penalty: failed authentication
> In CTF and red-team engagements, prioritize targeting known usernames directly (`-u ctf` or `-u alpine`) rather than rapid unthrottled spraying, to avoid triggering source IP penalties.
Run the vulnerable target container locally:
docker run -d --name sshhole-lab -p 2222:22 ghcr.io/leonjza/sshhole-lab:latest
python3 poc.py --host 127.0.0.1 -p 2222 -u alpine -c "id; uname -a"
This project is licensed under the [MIT License](LICENSE).
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
