невзлом

Важно · OpenSSH / Alpine

OpenSSH + musl без PAM — обход парольной аутентификации (Alpine, 05.11.2026)

← Простая версия для всех

Суть

При сборке/запуске sshd без PAM на musl проверка пароля через crypt() может принять вход для учёток с невалидным полем пароля * (нет пароля / key-only), если атакующий отправляет слишком длинный пароль: musl crypt() в ошибке возвращает *, сравнение с хранимым * проходит. Нужен ещё хотя бы один локальный $5$/$6$ хеш (sshd берёт salt у другой учётки). Учётки с нормальным хешем пароля этим путём не обходятся. OpenSSH: корень вне sshd; workaround в 10.6p2.

Затронуто и исправлено

Условия (Alpine, все сразу): openssh-server без PAM или openssh-server-pam + UsePAM no; PasswordAuthentication yes; учётка с * в shadow (root с ~3.16, adduser без пароля, alpine в tiny-cloud, nss через musl-nscd без shadow); ≥1 локальный $5$/$6$.

Не затронуты: нет sshd (типичный Docker); PasswordAuthentication no; PAM UsePAM yes; shadow ! (locked); нет $-хешей; cloud-init с уже выключенным password auth; glibc-дистрибутивы.

Root: root:* в базе, но дефолт PermitRootLogin prohibit-password не пускает root по паролю. tiny-cloud: alpine + passwordless doas → после входа возможен root.

Ветка Alpineopenssh с фиксом
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

Релизы: 3.21.10 / 3.22.8 / 3.23.8 / 3.24.4. Portable OpenSSH: 10.6p2 (05.11.2026).

Эксплуатация

  • Alpine: «one connection, works every time» при выполнении условий; не пишет about in-the-wild.
  • OpenSSH: critical workaround; отдельно — про ИИ-находки и более частые релизы (не равнять с confirmed exploitation).
  • KEV / CVE ID — нет на 05.11.2026.
  • Публичные разборы есть; ссылки на воспроизведение атаки не публикуем.

Как проверить

# Дистрибутив / libc
cat /etc/os-release
# musl?
ldd /bin/ls 2>/dev/null | head

# Версия пакета openssh (Alpine)
apk info -v openssh 2>/dev/null || apk info openssh

# PAM в рантайме
sshd -T 2>/dev/null | grep -i usepam
# Password auth
sshd -T 2>/dev/null | grep -i passwordauthentication

# Есть ли * и $5$/$6$ в shadow (нужен root)
awk -F: '$2=="*" {print $1":*"}' /etc/shadow
awk -F: '$2 ~ /^\$[56]\$/ {print $1}' /etc/shadow

Критерий закрытия: версия пакета ≥ строки в таблице для вашей ветки и sshd перезапущен после апгрейда.

Как исправить

# 1) Обновить (предпочтительно)
apk upgrade -U -a
# или точечно пакет openssh / openssh-server по политике

# 2) Обязательно перезапустить демон (apk сам его не подменяет)
rc-service sshd restart
# openrc-статус
rc-service sshd status

Инвентаризация: все Alpine-хосты и VM с sshd наружу; CI-образы с sshd; tiny-cloud AWS/Azure/qcow до 3.21.10 / 3.22.8 / 3.23.8 / 3.24.4 — обновить на месте. Закреплённые старые пакеты / зеркала без security — снять pin.

Если обновить нельзя

  1. Убедиться, что вход по ключу работает; сессию не рвать.
  2. Выставить PasswordAuthentication no (drop-in в /etc/ssh/sshd_config.d/ на 3.19+ и/или правка основного конфига) → sshd -t → restart → sshd -T | grep passwordauthentication → ожидается no.
  3. Не полагаться на «пароль сложный»: дыра как раз для учёток без пароля (*).

Признаки взлома и что делать

Alpine: в /var/log/messages ищите Accepted password for по учёткам с * (alpine, root, key-only). Аудит doas, новых пользователей, authorized_keys, недавних файлов. Нельзя исключить вход — считать хост скомпрометированным: ротация ключей/секретов, пересоздание из проверенного образа, не только патч sshd.

Источники