Jorge Turbica / blog · Blog ← Todos los artículos EN · Read in English
Tecnologías

Una contraseña de 257 bytes abre sshd en Alpine sin PAM: actualiza OpenSSH ya

Un fallo entre musl y sshd permite entrar por SSH sin contraseña en Alpine de la 3.16 a la 3.24. Qué hosts están expuestos y cómo cerrarlo.

Una sola conexión, sin reintentos y con una contraseña de entre 257 y 1024 bytes: así se entra por SSH en un Alpine Linux con sshd sin PAM, sin conocer ninguna contraseña. Alpine publicó el aviso el 5 de noviembre de 2026, el mismo día que OpenSSH sacó la 10.6p2 con la corrección, y afecta a todas las ramas que el equipo de Alpine ha revisado, de la 3.16 a la 3.24 y edge. En el momento del aviso no había CVE asignado, así que no esperes a que tu escáner de vulnerabilidades lo marque.

Por qué funciona el ataque

Sin PAM, sshd valida la contraseña él mismo: calcula crypt() del intento y lo compara con el campo de /etc/shadow. Si ese campo es demasiado corto para contener una sal, como el * de las cuentas sin contraseña, sshd toma prestada la sal de otra cuenta que sí tenga un hash.

El problema está en cómo responde la crypt() de musl a una clave de más de 256 bytes: devuelve la cadena * como indicador de error. Y * es justo lo que contiene el campo de cualquier cuenta sin contraseña. El "hash" coincide y el login se acepta. OpenSSH considera que la causa raíz está fuera de sshd, pero como se explota a través de él, la 10.6p2 lo evita en su propio código.

¿Estás afectado?

Tienen que darse todas estas condiciones:

  • Usas el paquete openssh-server de Alpine, que se compila sin PAM, o openssh-server-pam con UsePAM no.
  • PasswordAuthentication está en yes, que es el valor por defecto de OpenSSH.
  • Hay alguna cuenta con * en el campo de contraseña: root en la imagen base desde la 3.16, usuarios solo con clave creados con adduser sin contraseña, usuarios de un directorio vía musl-nscd o el usuario alpine de las imágenes tiny-cloud.
  • Al menos una cuenta local tiene un hash $5$ o $6$. Basta con una para que todas las cuentas sin contraseña queden expuestas.

root en sí está protegido por el PermitRootLogin prohibit-password por defecto, pero eso sirve de poco si otra cuenta alcanzable puede escalar con doas.

El caso más delicado son las imágenes oficiales tiny-cloud (qcow2, VHD y AMI) de la 3.18.11 a la 3.24.3: traen un usuario alpine con * y doas sin contraseña. Son seguras en el primer arranque, pero en cuanto aparece un hash $6$ en la máquina, por ejemplo porque alguien fija una contraseña de consola o el user-data crea un usuario con hashed_passwd, el atacante obtiene una shell como alpine y root con doas.

No están afectados los contenedores que no ejecutan sshd, los sistemas con PasswordAuthentication no, openssh-server-pam con UsePAM yes, las cuentas bloqueadas con ! y las imágenes configuradas con cloud-init, que ya escribe PasswordAuthentication no. Según OpenSSH, el fallo se limita a sistemas Linux con musl y PAM desactivado: Debian, Ubuntu o RHEL usan glibc y suelen compilar sshd con PAM.

Cómo actualizar

La vía corta es actualizar y, sobre todo, reiniciar el demonio: el paquete nuevo no sustituye al sshd que ya está en marcha.

bash
apk upgrade -U -a
rc-service sshd restart

Las versiones corregidas por rama son estas, e incluyen las ramas sin soporte regular:

RamaVersión corregida de openssh
edge10.6_p2-r0
3.2410.3_p1-r2
3.2310.2_p1-r1
3.2210.0_p1-r11
3.219.9_p2-r1
3.209.7_p1-r6
3.199.6_p1-r3
3.189.3_p2-r4
3.179.1_p1-r7
3.169.0_p1-r6

Las versiones puntuales 3.21.10, 3.22.8, 3.23.8 y 3.24.4 ya incluyen el paquete corregido, y las imágenes construidas a partir de ellas también. Una instancia arrancada con una imagen anterior sigue vulnerable hasta que actualices el paquete en ella: reconstruir la imagen no arregla las máquinas que ya están en marcha.

Si hoy no puedes actualizar, desactivar el login por contraseña cierra el agujero igual. Antes, comprueba que entras con tu clave y deja abierta la sesión actual hasta probar un login nuevo. Estos son los comandos del aviso de Alpine (el directorio sshd_config.d lo lee la configuración por defecto desde la 3.19; el sed cubre las versiones anteriores y los bloques Match):

bash
mkdir -p /etc/ssh/sshd_config.d
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
sed -i.bak -e '1i PasswordAuthentication no' \
  -e 's/^\(\s*PasswordAuthentication[^y#]*\)yes/\1no/i' \
  /etc/ssh/sshd_config
sshd -t && rc-service sshd restart
sshd -T | grep -i passwordauthentication

La última línea tiene que imprimir passwordauthentication no.

Checklist después del parche

  • apk info -v openssh-server (o openssh-server-pam) muestra la versión corregida de tu rama.
  • El proceso sshd se ha reiniciado después de la actualización, no solo el paquete.
  • sshd -T | grep -i passwordauthentication devuelve lo que esperas en cada host, incluidos los que salen de imágenes tiny-cloud anteriores a la 3.24.4.
  • Busca en /var/log/messages líneas Accepted password for de cuentas que no tienen contraseña (alpine, root o usuarios solo con clave). Revisa también el uso de doas, los usuarios creados hace poco y los authorized_keys de las máquinas expuestas. Si no puedes descartar un acceso, Alpine recomienda tratar la máquina como comprometida.

Lo que más me llama la atención es la cadena: ni musl ni sshd hacen nada absurdo por separado, pero un valor de error que coincide con un valor legítimo convierte un detalle de implementación en un bypass total. Y encaja con el aviso que abre las notas de la 10.6p2: el equipo de OpenSSH recibe muchos informes hechos con IA, ha visto fallos encontrados así que luego descubre otra persona por su cuenta, y por eso publicará versiones más a menudo en lugar de acumular correcciones. Si mantienes hosts con Alpine expuestos a internet, PasswordAuthentication no debería ser la configuración base, haya parche o no.

Fuentes

Jorge Turbica

Software Engineer y SRE. Escribo sobre los retos reales que me encuentro en producción.

Ver portfolio ↗