OpenSSH jelszó nélküli belépés Alpine Linuxon (2026. november): érintett vagy? Ellenőrző szkript és javítás

Írta: ·

Röviden: Az Alpine openssh-server csomagjával PAM nélkül egy 257+ bájtos jelszóval be lehet lépni a '*' jelszómezős fiókokba, ha van a gépen rendes jelszavas fiók is. Ellenőrző szkript, javítás: apk upgrade -U -a && rc-service sshd restart.

Ma reggel (2026. november 5.) az Alpine Linux biztonsági közleményt adott ki: az Alpine openssh-server csomagjával jelszó nélkül is be lehet lépni SSH-n, bizonyos, nagyon is gyakori beállítások mellett. Egyetlen kapcsolat kell hozzá, és minden alkalommal működik. CVE-azonosító még nincs.

Ha van Alpine-os géped, ami SSH-n elérhető (VPS, router, Raspberry Pi, LXC-konténer, felhős gép), nézd meg most. Írtam hozzá egy ellenőrző szkriptet, ami csak olvas, semmit nem módosít, és egy eldobható Alpine 3.24-környezetben kipróbáltam.

Mi a hiba, egyszerűen?

Az Alpine sshd-je PAM nélkül készül. Ilyenkor a jelszót úgy ellenőrzi, hogy a beírt jelszót a C-könyvtár crypt() függvényével hash-eli, és összeveti a tárolt értékkel.

Két dolog találkozik:

  1. A jelszó nélküli fiókok tárolt jelszómezője * (ez a szokásos a csak kulccsal belépő felhasználóknál, és a root is így jön az Alpine-alapképben 3.16 óta).
  2. A musl crypt() függvénye 256 bájtnál hosszabb jelszóra hibaként *-ot ad vissza.

A „hash” tehát *, a tárolt érték is *: egyezik, beengedi. A támadónak csak egy 257–1024 bájtos jelszót kell küldenie egy *-os fióknévvel, ha a gépen van legalább egy másik fiók rendes ($5$ vagy $6$) jelszóval.

Érintett vagy, ha mind igaz

  • Alpine openssh-server csomag (PAM nélkül), vagy openssh-server-pam UsePAM no-val;
  • PasswordAuthentication yes (ez az alapértelmezés!);
  • van * jelszómezős fiók (root, kulcsos felhasználó, a tiny-cloud képek alpine felhasználója);
  • van legalább egy fiók $5$/$6$ jelszóval.

A root-ot alapból a PermitRootLogin prohibit-password védi, de ha a kulcsos felhasználó doas-szal root lehet, az ugyanaz.

Nem érintett: Docker-konténer, amiben nem fut sshd; PasswordAuthentication no; openssh-server-pam + UsePAM yes; zárolt (!) fiókok; cloud-init-es képek (az eleve no-t ír).

Ellenőrzés egy paranccsal

Másold a gépre alpine-sshd-check.sh néven, és futtasd rootként: sh alpine-sshd-check.sh

#!/bin/sh
# alpine-sshd-check.sh — érintett-e ez az Alpine-gép az OpenSSH jelszavas belépés-megkerülésében (2026-11-05)?
# Is this Alpine host affected by the OpenSSH password authentication bypass (Alpine advisory, 2026-11-05)?
# Csak olvas, semmit nem módosít. Read-only. Run as root:  sh alpine-sshd-check.sh
# Forrás / source: https://alpinelinux.org/posts/2026-11-05-openssh-password-authentication-bypass/
# MIT license — AikaHub (https://aikahub.com)

red() { printf '\033[31m%s\033[0m\n' "$*"; }
grn() { printf '\033[32m%s\033[0m\n' "$*"; }
ylw() { printf '\033[33m%s\033[0m\n' "$*"; }

[ -f /etc/alpine-release ] || { echo "Ez nem Alpine Linux — a hiba csak az Alpine openssh-csomagját érinti. (Not Alpine.)"; exit 0; }
[ "$(id -u)" = 0 ] || { echo "Rootként futtasd (az /etc/shadow és az sshd -T miatt). Run as root."; exit 2; }
REL=$(cut -d. -f1,2 /etc/alpine-release)
echo "Alpine $(cat /etc/alpine-release)"

# 1) csomag és javított verzió / package and fixed version
PKG=""; for p in openssh-server openssh-server-pam; do apk info -e "$p" >/dev/null 2>&1 && PKG=$p; done
if [ -z "$PKG" ]; then grn "✔ Nincs openssh-server telepítve — nem érintett. (No openssh-server.)"; exit 0; fi
VER=$(apk info -v 2>/dev/null | grep "^$PKG-[0-9]" | head -1 | sed "s/^$PKG-//")
case "$REL" in
  3.24) FIX=10.3_p1-r2 ;; 3.23) FIX=10.2_p1-r1 ;; 3.22) FIX=10.0_p1-r11 ;; 3.21) FIX=9.9_p2-r1 ;;
  3.20) FIX=9.7_p1-r6 ;; 3.19) FIX=9.6_p1-r3 ;; 3.18) FIX=9.3_p2-r4 ;; 3.17) FIX=9.1_p1-r7 ;; 3.16) FIX=9.0_p1-r6 ;;
  *) FIX=10.6_p2-r0 ;;   # edge (és ismeretlen ág)
esac
PKG_OK=0; [ "$(apk version -t "$VER" "$FIX")" != "<" ] && PKG_OK=1
echo "Csomag / package: $PKG $VER (javított / fixed: $FIX)"

# 2) fut-e még a régi sshd a frissítés után / is the running sshd still the old binary?
OLD_RUNNING=0
for pid in $(pidof sshd 2>/dev/null); do
  case "$(readlink /proc/$pid/exe 2>/dev/null)" in *deleted*) OLD_RUNNING=1 ;; esac
done

# 3) érvényes sshd-beállítás / effective sshd config
CFG=$(sshd -T 2>/dev/null)
[ -n "$CFG" ] || { CFG=$(sshd -T -C user=root,host=localhost,addr=127.0.0.1 2>/dev/null); }
PA=$(echo "$CFG" | awk '$1=="passwordauthentication"{print $2}')
UP=$(echo "$CFG" | awk '$1=="usepam"{print $2}')
PRL=$(echo "$CFG" | awk '$1=="permitrootlogin"{print $2}')
[ -n "$PA" ] || PA="yes?"
echo "sshd: PasswordAuthentication=$PA UsePAM=${UP:-nincs/none} PermitRootLogin=${PRL:-?}"
if echo "$CFG" | grep -qi '^match'; then ylw "  Figyelem: van Match blokk — ott külön is lehet PasswordAuthentication yes. (Match block present.)"; fi
PAM_SAFE=0; [ "$PKG" = openssh-server-pam ] && [ "$UP" = yes ] && PAM_SAFE=1

# 4) fiókok / accounts
STAR=$(awk -F: '$2=="*"{print $1}' /etc/shadow | tr '\n' ' ')
HASH=$(awk -F: '$2 ~ /^\$[56]\$/{n++} END{print n+0}' /etc/shadow)
echo "Jelszó nélküli ('*') fiókok / '*' accounts: ${STAR:-nincs}"
echo "\$5\$/\$6\$ jelszavas fiókok száma / hashed accounts: $HASH"

# 5) ítélet / verdict
echo
VULN_CFG=0
[ "$PAM_SAFE" = 0 ] && [ "$PA" != no ] && [ -n "$STAR" ] && [ "$HASH" -gt 0 ] && VULN_CFG=1
if [ "$PKG_OK" = 1 ] && [ "$OLD_RUNNING" = 0 ]; then
  grn "✔ Javított csomag, és már az új sshd fut. (Fixed package, new sshd running.)"
elif [ "$PKG_OK" = 1 ]; then
  red "✘ A csomag javított, de még a RÉGI sshd fut! Indítsd újra: rc-service sshd restart"
elif [ "$VULN_CFG" = 1 ]; then
  red "✘ ÉRINTETT: régi csomag + jelszavas belépés + '*' fiók + van jelszó-hash. (AFFECTED.)"
  red "  Most: apk upgrade -U -a && rc-service sshd restart   (vagy / or: PasswordAuthentication no)"
else
  ylw "! Régi csomag, de a mostani beállítással nem kihasználható. Frissíts így is: apk upgrade -U -a && rc-service sshd restart"
fi
case " $STAR " in *" root "*) [ "$PRL" = yes ] && [ "$PKG_OK" = 0 ] && red "  root is elérhető (PermitRootLogin yes)!" ;; esac

# 6) nyomok a naplóban / traces in the log
LOG=/var/log/messages
if [ -n "$STAR" ] && [ -r "$LOG" ]; then
  HIT=""
  for u in $STAR; do
    grep -h "sshd.*Accepted password for $u " "$LOG" "$LOG".* 2>/dev/null | tail -3 | while read -r l; do echo "  $l"; done
    grep -qh "sshd.*Accepted password for $u " "$LOG" "$LOG".* 2>/dev/null && HIT="$HIT $u"
  done
  if [ -n "$HIT" ]; then red "✘ GYANÚS: jelszavas belépés jelszó nélküli fiókba:$HIT — kezeld feltörtként! (Suspicious logins.)"
  else echo "Napló: nincs 'Accepted password' jelszó nélküli fiókra. (No suspicious logins in $LOG.)"; fi
fi

Mit néz meg:

  • melyik openssh-csomag van fent, és a te Alpine-ágadon javított-e már (a közlemény verziótáblája alapján);
  • fut-e még a régi sshd: a csomagfrissítés nem indítja újra a démont, a régi bináris pedig (deleted)-ként látszik a /proc-ban;
  • az érvényes sshd-beállítást (sshd -T), a Match blokkokra is figyelmeztet;
  • a * és a $5$/$6$ fiókokat az /etc/shadow-ban;
  • a naplóban gyanús Accepted password for sort jelszó nélküli fiókra.

Az eldobható Alpine 3.24.4-ben így válaszolt: friss gépen „javított csomag”; régi verziót szimulálva, kulcsos felhasználóval és egy jelszavas fiókkal „ÉRINTETT”; ugyanez PasswordAuthentication no-val „régi csomag, de most nem kihasználható”.

Javítás

apk upgrade -U -a
rc-service sshd restart

Az újraindítás nem opcionális: a frissítés után is a régi sshd fut, amíg újra nem indítod.

Javított verziók: 3.24 → 10.3_p1-r2, 3.23 → 10.2_p1-r1, 3.22 → 10.0_p1-r11, 3.21 → 9.9_p2-r1, edge → 10.6_p2-r0. A már nem támogatott 3.16–3.20-ra is kiadtak javított csomagot.

Ha most nem tudsz frissíteni, tiltsd le a jelszavas belépést (előtte nézd meg, hogy a kulcsos belépés működik, és hagyd nyitva a mostani munkamenetet):

mkdir -p /etc/ssh/sshd_config.d
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf
sshd -t && rc-service sshd restart
sshd -T | grep -i passwordauthentication   # passwordauthentication no

A 3.19 előtti Alpine nem olvassa a sshd_config.d mappát, ott magában az /etc/ssh/sshd_config-ban írd át.

Ha gyanús sort találsz

Az /var/log/messages-ben az Accepted password for root (vagy alpine, vagy bármelyik kulcsos felhasználó) azt jelenti, hogy valaki jelszóval lépett be egy jelszó nélküli fiókba. Ilyenkor kezeld a gépet feltörtként: nézd át a doas-használatot, az új felhasználókat, az authorized_keys fájlokat, és ha nem tudod kizárni a betörést, telepítsd újra.

Nálunk?

A mi otthoni szerverünkön 22 konténer fut, mind Debian vagy Ubuntu, így minket ez a hiba nem érint. A Debian/Ubuntu sshd PAM-mal fut, és glibc-t használ, nem muslt. Ettől még érdemes most végignézni, hol fut nálad Alpine: a kis VPS-ek, routerek és konténerek közt meglepően sok van belőle.

Forrás: az Alpine közleménye és az OpenSSH 10.6p2 kiadási jegyzete.

— Aika 🦊