ssh-keysign-pwn: kaip paprastas vartotojas pavogia serverio raktus — ir kaip tai sustabdyti
Serveris sukonfigūruotas. Nginx už Cloudflare, fail2ban blokuoja botus, root prisijungimas per SSH išjungtas. Viešos prieigos prie /etc/shadow nėra — tai 640, root:shadow. Privatūs SSH serverio raktai saugomi /etc/ssh/ su teisėmis 600. Viskas užrakinta.
Tada kažkas gauna neprivilegijuotą shell — per pažeidžiamą įskiepį, silpną slaptažodį, bet ką — ir per kelias sekundes perskaito /etc/shadow bei visus privačius serverio SSH raktus. Be sudo ir be root. Tiesiog paleidžia skriptą.
Sveiki atvykę į CVE-2026-46333, dar žinomą kaip ssh-keysign-pwn.
KAS ATSITIKO
2026 m. gegužės 14 d. Qualys pranešė apie pažeidžiamumą Linux branduolio saugumo komandai, o patch’as buvo įkeltas tą pačią dieną per commit’ą 31e62c2ebbfd. Tą pačią dieną iš viešo commit’o atsirado nepriklausomas PoC exploit’as. Pilnas Qualys advisory paskelbtas gegužės 20 d.
Pažeidžiamumas neliečia OpenSSH ir ne konkrečios konfigūracijos — jis yra pačioje Linux branduolio logikoje.
KAIP TAI VEIKIA
Įsivaizduok apsaugininką, kuris jau baigė pamainą ir atidavė praleidimą — bet seifo raktai dar jo kišenėje. Būtent tuo momentu kažkas prieina ir prašo raktų. Formaliai apsaugininkas jau nebe apsaugininkas, patikrinimas nepavyksta.
Maždaug taip veikia CVE-2026-46333.
Linux branduolys naudoja ptrace — sąsają, per kurią vienas procesas gali stebėti kitą arba pasiekti jo išteklius. Kai privilegijuotas procesas baigiasi, branduolys atlaisvina jo atmintį (mm) — apsaugininkas atidavė praleidimą. Tačiau failų deskriptoriai atvirų failų — /etc/shadow, /etc/ssh/ssh_host_*_key — vis dar gyvi. Raktai kišenėje.
Tuo trumpu momentu funkcija __ptrace_may_access() praleidžia dalį patikrinimo: užduotis jau neturi atminties konteksto, o deskriptoriai jautriems failams vis dar egzistuoja. Užpuolikas pagauna šį momentą per sisteminį iškvietimą pidfd_getfd() — jis leidžia nukopijuoti failo deskriptorių iš kito proceso į savą — ir gauna tiesioginę prieigą prie failo.
Du atakos vektoriai viešame PoC:
ssh-keysign — tai OpenSSH setuid pagalbinė programa, paleidžiama kaip root kai SSH klientui reikia pasirašyti duomenis serverio privačiu raktu. Ji įdiegiama kartu su openssh-client ir yra daugumoje Linux sistemų. Ji atidaro serverio privačius raktus (/etc/ssh/ssh_host_*_key) ir laiko juos atidarytus savo darbo metu. Užpuolikas pagauna ssh-keysign užbaigimo momentą ir pavogia deskriptorių — privatūs raktai perskaityti.
chage — slaptažodžių galiojimo valdymo įrankis. Paleidus chage -l , sistema atidaro /etc/shadow vartotojo slaptažodžio duomenims perskaityti. Ta pati race condition — ir slaptažodžių maišos pas užpuoliką.
Tai ne buferio perpildymas ir ne sudėtinga exploit’ų grandinė. Tiesiog kelių eilučių kodo lenktynės.
KODĖL TAI PAVOJINGA
Qualys sukūrė keturis veikiančius exploit’us tai pačiai pažeidžiamumui:
chage — skaito /etc/shadow su slaptažodžių maišomis.
ssh-keysign — skaito privačius SSH serverio raktus.
pkexec — vykdo bet kokias komandas kaip root. Reikia aktyvios konsolinės sesijos, tačiau užpuolikas gali būti prisijungęs nuotoliniu būdu per SSH.
accounts-daemon — taip pat vykdo komandas kaip root, be konsolinės sesijos. Patikrinta ant numatytųjų Debian 13 ir Fedora instaliacijų.
Taigi „tiesiog skaito failus” — tai tik viešas PoC. Pilnas root per pkexec ir accounts-daemon techniškai įmanomas daugelyje distribucijų su numatytąja instaliacija.
Privatus SSH serverio raktas — tai kaip jūsų serveris pristatosi klientams SSH prisijungimo metu. Kas valdo šį raktą — gali apsimesti jūsų serveriu. Tylus MITM klientams, kurie jau pridėjo raktą į known_hosts. Kol raktai nerotuoti, užpuolikas gali perimti SSH sesijas nepastebėtas.
Maišos iš /etc/shadow galima išnešti į atskirą mašiną ir laužti offline be triukšmo infrastruktūroje. Jokių pėdsakų jūsų serverio žurnaluose. Jei vienas slaptažodis naudojamas keliose vietose — kompromitavimas plinta horizontaliai.
Vienas serveris su neprivilegijuota prieiga tampa įėjimo tašku į visą infrastruktūrą.
KĄ DARYTI DABAR
1 žingsnis. Užblokuoti exploit’ą nedelsiant — be perkrovimo
Kol branduolys dar neatnaujintas, du būdai uždaryti vektorių dabar pat.
A variantas — sysctl. Apriboti ptrace branduolio lygmeniu. Reikšmė 2 — pakankama mitigacija pagal Ubuntu rekomendaciją: draudžia ptrace vartotojams be CAP_SYS_PTRACE:
echo kernel.yama.ptrace_scope=2 | sudo tee /etc/sysctl.d/99-CVE-2026-46333.conf
sudo sysctl -p /etc/sysctl.d/99-CVE-2026-46333.conf
Dėmesio: reikšmė 3 išjungia ptrace visiškai visiems įskaitant root ir negali būti atšaukta be perkrovimo — nenaudokite jos.
Šalutinis poveikis: neprivilegijuoti vartotojai nebegalės naudoti gdb, strace kitiems procesams. Gamybiniuose serveriuose tai priimtina.
B variantas — pašalinti SUID bitą iš abiejų atakos vektorių:
# Debian/Ubuntu
chmod u-s /usr/lib/openssh/ssh-keysign
chmod u-s /usr/bin/chage
# RHEL/AlmaLinux/Rocky
chmod u-s /usr/libexec/openssh/ssh-keysign
chmod u-s /usr/bin/chage
Tai neutralizuoja lygiai tuos du binariniai failus, kuriuos naudoja viešas PoC. Įdiegus branduolio patch’ą, SUID bitą reikia grąžinti.
2 žingsnis. Atnaujinti branduolį
# Debian/Ubuntu
apt update && apt upgrade -y
# RHEL/AlmaLinux/Rocky
dnf clean metadata && dnf upgrade -y
Po atnaujinimo perkrovimas būtinas — branduolio patch’as pradeda veikti tik po jo.
Branduolio versijos su patch’u:
Ubuntu 24.04 LTS — patch’as versijoje 6.8.0-117 (USN-8278-1, paskelbta 2026 m. gegužės 19 d.):
uname -r
# 6.8.0-111-generic → pažeidžiama, atnaujinti
# 6.8.0-117-generic → patch'as įdiegtas
Ubuntu 22.04 LTS — lowlatency/HWE branduolys serija 6.8.x: 6.8.0-117.117.1~22.04.1 (USN-8278-1). Standartinis 5.15.x branduolys — sekti: https://ubuntu.com/security/CVE-2026-46333
AlmaLinux 10 — pradedant kernel-6.12.0-227.el10 (gamybos saugykloje nuo gegužės 16 d.).
Po perkrovimo su pataisytu branduoliu pašalinti mitigacijas:
sudo rm /etc/sysctl.d/99-CVE-2026-46333.conf
sudo sysctl kernel.yama.ptrace_scope=1
# Debian/Ubuntu
chmod u+s /usr/lib/openssh/ssh-keysign
chmod u+s /usr/bin/chage
# RHEL/AlmaLinux/Rocky
chmod u+s /usr/libexec/openssh/ssh-keysign
chmod u+s /usr/bin/chage
ptrace_scope reikia grąžinti į 1 (Ubuntu numatytoji reikšmė), ne į 0.
3 žingsnis. Rotuoti SSH host keys
Net po patch’o įdiegimo — jei užpuolikas jau gavo raktus prieš atnaujinimą, seni raktai kompromituoti. Pergeneruoti kritiniuose serveriuose:
rm /etc/ssh/ssh_host_*
ssh-keygen -A
systemctl restart ssh # Debian/Ubuntu
systemctl restart sshd # RHEL/AlmaLinux/Rocky
Įspėti vartotojus: kito SSH prisijungimo metu jie pamatys įspėjimą apie pakeistą serverio raktą — tai normalu, reikia priimti naują fingerprint’ą.
4 žingsnis. Audituoti vietinius vartotojus ir pakeisti slaptažodžius
Patikrinti, kas iš viso turi shell prieigą prie mašinos:
awk -F: '$7 !~ /nologin|false/ {print $1, $7}' /etc/passwd
Viską nereikalingą — užblokuoti:
usermod -s /usr/sbin/nologin vartotojo_vardas
Jei mašinoje buvo neprivilegijuotų vartotojų su shell prieiga — laikyti jų slaptažodžių maišas kompromituotomis ir pakeisti:
passwd vartotojo_vardas
5 žingsnis. Patikrinti NoNewPrivileges kritiniuose servisuose
NoNewPrivileges — systemd direktyva, draudžianti procesui įgyti aukštesnes privilegijas nei tos, su kuriomis jis buvo paleistas. Net jei užpuolikas gavo shell kaip www-data ir bando išnaudoti panašų vektorių — privilegijų eskalavimas bus blokuotas branduolio lygmeniu.
Tai ne tiesioginis CVE-2026-46333 taisymas, tačiau sumažina atakos paviršių panašioms race condition situacijoms:
systemctl show nginx | grep NoNewPrivileges
systemctl show postgresql | grep NoNewPrivileges
Jei tuščia arba false — pridėti:
systemctl edit nginx
[Service]
NoNewPrivileges=yes
systemctl daemon-reload && systemctl restart nginx
Tas pats PostgreSQL, MySQL ir kitiems servisams, paleistiems kaip neprivilegijuoti vartotojai.
IŠVADA
CVE-2026-46333 — priminimas, kad „serveris uždarytas iš išorės” ir „serveris saugus” yra du skirtingi teiginiai. Vietinė neprivilegijuota prieiga, kuri atrodo nekenksminga, virsta slaptų duomenų, gyvenančių ilgiau nei pati pažeidžiama mašina, vagyste.
Patch’as — šiandien. Raktų rotacija — po patch’o. Vartotojų auditas — gera proga padaryti tai bet kokiu atveju.
PoC viešas. Laikrodis tiksena.
