Tinklaraštis

19 metų šešėlyje: CIFSwitch suteikia root per SMB dalijimosi prijungimo mechanizmą.

CIFSwitch
CVE / Linux / Saugumas

19 metų šešėlyje: CIFSwitch suteikia root per SMB dalijimosi prijungimo mechanizmą.

Įsivaizduokite: jūsų serveryje veikia paprastas neprivilegijuotas vartotojas — kūrėjas, VPS nuomininkas, studentas bendrame hostinge. Jis paleidžia vieną komandą. Po sekundės jis turi root. SELinux tuo metu gali veikti enforcing režimu. AppArmor — aktyvus. Niekas nesuveikė.

Būtent taip veikia CIFSwitch — Linux branduolio pažeidžiamumas, kurį tyrinėtojas Asim Viladi Oglu Manizada atrado ir atskleidė 2026 m. gegužės 28 d. CVE identifikatorius publikavimo metu dar nepriskirtas, branduolio pataisymas daugiau nei savaitę yra parengtas ir laukia eilės stabilioms šakoms. Viešas proof-of-concept pasirodė kartu su atskleidimo ataskaita — tai reiškia, kad bet kas gali atkurti ataką dabar pat.

Klaida kode slypi nuo 2007 metų. 19 metų. Ji išgyveno daugybę auditų ir tūkstančius atnaujinimų, likdama visiškai nepastebėta — nes tai ne buferio perpildymas ir ne use-after-free. Tai loginė klaida branduolio ir userspace sąsajoje, kurią aptikti buvo įmanoma tik žiūrint į sistemą kaip visumą, o ne į atskirus komponentus.

KAS YRA CIFS IR cifs.upcall

CIFS (Common Internet File System) — tai SMB protokolo realizacija Linux branduolyje. Paprasčiau tariant, tai kas leidžia Linux prijungti Windows serverių tinklo aplankus komanda mount -t cifs. Branduolio modulis cifs atsakingas už visą failų sistemos lygmenį: prijungimą, skaitymą, rašymą, derybas su serveriu. Tačiau yra niuansas — Kerberos autentifikacijos branduolys pats neatlieką. Tam egzistuoja atskira schema.

Kai CIFS klientui reikia Kerberos/SPNEGO žetono autentifikuotam prijungimui, jis naudoja Linux raktų žiedų mechanizmą: prašo rakto tipo cifs.spnego. Sistema pastebi šį prašymą ir pagal taisyklę faile /etc/request-key.d/cifs.spnego.conf paleidžia userspace pagalbininką — cifs.upcall — su root teisėmis. Šis gauna Kerberos medžiagą ir grąžina ją branduoliui. Visa ši schema yra paketo cifs-utils dalis.

Esminis dalykas čia — cifs.upcall paleidžiamas su root teisėmis. Tai savaime nėra klaida, tai architektūrinis sprendimas: pagalbininkui reikia privilegijų dirbti su skirtingų vartotojų kredencialų talpyklomis. Problema ta, kad branduolys netikrinjo: kas gi, iš tikrųjų, paprašė paleisti šį pagalbininką?

KAIP VEIKIA KLAIDA

Kai branduolys prašo rakto cifs.spnego, jis formuoja aprašymo eilutę iš realios sistemos būsenos: serveris, uid, creduid, proceso pid, upcall-target tipas. Maždaug taip: ver=0x2;host=fs.acme.com;ip4=192.168.1.10;sec=krb5;uid=0x3e8;creduid=0x3e8;pid=0x4f2a;upcall_target=app. Šie laukai tikri — branduolys juos ima iš savo būsenos.

Problema slypi rakto tipo cifs_spnego_key_type apibrėžime faile fs/smb/client/cifs_spnego.c. Prieš pataisymą struktūra atrodė taip:

struct key_type cifs_spnego_key_type = {
    .name        = "cifs.spnego",
    .instantiate = cifs_spnego_key_instantiate,
    .destroy     = cifs_spnego_key_destroy,
    .describe    = user_describe,
};

Matote ko trūksta? Lauko .vet_description — kablio, kuris turėtų tikrinti rakto aprašymo teisėtumą. Be jo branduolys neskyrė CIFS kliento prašymo nuo bet kurio kito proceso prašymo. Paprastas neprivilegijuotas vartotojas galėjo iškviesti request_key("cifs.spnego", visiškai_suklastotas_aprašymas, "") — ir sistema reaguodavo lygiai taip pat kaip į branduolio prašymą: paleisdavo cifs.upcall su root teisėmis.

Svarbi detalė: branduoliui net nereikėjo sėkmingai grąžinti rakto. cifs.upcall buvo paleidžiamas prieš tai, kai branduolys išduodavo klaidą -ENOKEY. Ataka pavykdavo anksčiau nei ateidavo atsisakymas.

KAIP TIKSLIAI IŠNAUDOJAMA

Užpuolikas suformuoja suklastotą aprašymo eilutę, kurioje nustato upcall_target=app ir įrašo savo proceso pid. Toliau — pasitikėjimo grandinė pradeda veikti prieš sistemą.

cifs.upcall, paleistas kaip root, nuskaito aprašymą ir mato upcall_target=app. Kode tai signalas: „reikia pereiti į programos namespace, kad tinkamai veiktume konteineriuose.” Pagalbininkas iškviečia switch_to_process_ns(arg->pid) — ir pereina į užpuoliko nurodyto proceso namespace. Šį namespace užpuolikas visiškai kontroliuoja.

Dabar root procesas yra užpuoliko vardų erdvėje. Kitas žingsnis — getpwuid(uid): pagalbininkas ieško paskyros per NSS (Name Service Switch), kad gautų vartotojo gid. NSS skaito konfigūraciją iš /etc/nsswitch.conf — kurią užpuolikas savo namespace jau pakeitė. Pakeistas nsswitch.conf nurodo į libnss_pwn.so.2 — užpuoliko biblioteką. Root pagalbininkas ją įkelia. Biblioteka vykdoma su root teisėmis.

Manizados demonstraciniame PoC ši biblioteka įrašo taisyklę į /etc/sudoers.d — ir užpuolikas gauna galimybę vykdyti bet kokias komandas kaip root per sudo.

KAS NUTINKA TOLIAU — PRIKLAUSO NUO SISTEMOS NUSTATYMŲ

CIFSwitch nėra universalus pažeidžiamumas. Sėkmingam išnaudojimui būtina vienu metu įvykdyti keturias sąlygas: pažeidžiamas branduolys (kodas buvo nuo 2007 m.), įdiegtas cifs-utils versija 6.14 ar naujesnė su cifs.spnego taisykle, leidžiamos neprivilegijuotos user namespaces ir LSM politika, kuri neblokuoja grandinės.

Čia prasideda įdomiausia dalis. SELinux enforcing režimu — skamba kaip patikima apsauga. Tačiau testavimas parodė: CentOS Stream 9 GNOME, Rocky Linux 9 Workstation ir AlmaLinux 9.7 yra išnaudojamos su įjungtu SELinux enforcing. AppArmor taip pat nepadeda Linux Mint 21.3/22.3 ir SLES 15 SP7 atveju. Numatytosios politikos tiesiog neapima šio atakos vektoriaus.

Apsaugo tik griežtesnės konfigūracijos: Fedora 40–44, CentOS Stream 10 ir Rocky Linux 10 nėra išnaudojamos — tačiau tik todėl, kad SELinux jose sukonfigūruotas griežčiau. Pakanka paleisti setenforce 0 — ir apsauga išnyksta. Ubuntu 26.04 blokuoja ataką per AppArmor userns politiką. 24.04 versijoje politika taip pat aktyvi, tačiau yra apėjimas: aa-exec -p trinity paleidžia procesą pagal AppArmor profilį, kuris leidžia kurti user namespaces — ir ataka vėl veikia. Amazon Linux 2 nepažeidžiamas — tačiau tik todėl, kad ten per senas cifs-utils 6.2 be namespace perjungimo palaikymo.

ATAKOS GRANDINĖ REALIAME PASAULYJE

Scenarijus: VPS nuomininkas Ubuntu 22.04 su įdiegtu cifs-utils. Serveris naudojamas kaip bendros infrastruktūros dalis — keli klientai, kiekvienas su savo neprivilegijuotu vartotoju. Vienas nuomininkas atsiunčia PoC iš GitHub ir paleidžia vieną komandą. Po sekundės jis turi root prieigą prie viso serverio — įskaitant visų kitų nuomininkų duomenis, duomenų bazes, SSL sertifikatus, SSH raktus.

Tam nereikia žinoti root slaptažodžio. Nereikia tinklo prieigos. Nereikia išnaudoti atminties — jokio heap spray, jokių ROP grandinių. Tiesiog vienas sistemos iškvietimas request_key() su suklastotu aprašymu, ir toliau sistemos logika viską padaro pati.

Pradinis prieigos vektorius gali būti bet koks: SSH prieiga su ribotomis teisėmis, web shell per pažeidžiamą web programą, aptarnavimo paskyros kompromitavimas, ištrūkimas iš konteinerio, kuris neizoluoja user namespaces. Svarbiausia — neprivilegijuotas vartotojas pažeidžiamoje sistemoje.

CHRONOLOGIJA

2007 m. — klaida atsiranda kode. Faile fs/smb/client/cifs_spnego.c apibrėžiama struktūra cifs_spnego_key_type be kablio .vet_description. Tai ne realizacijos klaida — tai praleistas patikrinimas projektuojant mechanizmą.

2026 m. gegužės 16 d. — Asim Viladi Oglu Manizada praneša apie problemą branduolio ir cifs-utils prižiūrėtojams.

2026 m. gegužės 16–27 d. — branduolio pataisymas (commit 3da1fdf4efbc) paruoštas ir įtrauktas į eilę stabilioms šakoms. Vyksta koordinuota embargo su linux-distros@ — kad distribucijos spėtų paruošti paketus iki viešo atskleidimo.

2026 m. gegužės 28 d. — embargo baigiasi. Manizada skelbia išsamų writeup heyitsas.im ir PoC GitHub kartu su atskleidimo raštu oss-security adresų sąraše. Tuo metu branduolio pataisymas jau daugiau nei savaitę laukia stable eilėje, tačiau distribucijų atnaujinti paketai dar platinami.

2026 m. birželio 1 d. — pataisymai toliau pasiekia Red Hat, Ubuntu, Debian, SUSE, Oracle ir Amazon Linux. CVE identifikatorius dar nepriskirtas.

KAIP TAI GALĖJO EGZISTUOTI 19 METŲ

Programuotojo atmintis negali vienu metu išlaikyti viso sistemos pasitikėjimo grafo. Kai 2007 m. buvo realizuojamas CIFS upcall mechanizmas, kūrėjas matė savo dalį: branduolys prašo rakto, userspace pagalbininkas jį gauna ir atlieka darbą. Logika teisinga. Kas nebuvo akivaizdu — tai kad bet kuris procesas gali inicijuoti tą patį prašymą su suklastotais duomenimis, nes rakto tipas netikrina aprašymo kilmės.

Tai klasikinis confusion atakos šablonas: komponentas A pasitiki duomenimis, kurie, jo prielaida, gali ateiti tik iš komponento B. Tačiau nėra mechanizmo, kuris tai garantuotų. Rasti tokį pažeidžiamumą rankinio audito metu labai sunku — reikia vienu metu turėti galvoje ir branduolio kodą, ir userspace pagalbininką, ir raktų žiedų mechanizmą, ir tai, kaip NSS veikia nestandartinėmis namespace sąlygomis. Joks auditorius nestebi viso šio grafo vienu metu.

Be to, išnaudojimo sąlygos netrivialios: reikia konkrečios cifs-utils versijos su namespace perjungimo palaikymu ir LSM politikos, kuri neblokuoja grandinės. Serveriuose be cifs-utils klaida išvis neišnaudojama. Tai smarkiai sumažino tikimybę atsitiktinai aptikti problemą įprastos veiklos metu.

KODĖL RANDA DABAR

CIFSwitch nerado žmogus — tiksliau, rado žmogus su įrankiu, leidusiu pamatyti būtent tokio tipo ryšius tarp komponentų.

Manizada aprašo metodą savo writeup: jis aprūpino LLM agentus grafo perėjimo įrankiu, įkvėptu GraphWalk tyrimo. Agentai kūrė semantinį su sauga susijusių objektų grafą — kas kuria objektą, kas jį naudoja kaip autoritetingą šaltinį, kur atsiveria spraga tarp to, ką objektas teigia apie save, ir to, ką daro jo vartotojas. Pakankamai dideliame grafe modeliai su šiuo įrankiu pranoko samprotaujančius modelius be jo.

Tai svarbus signalas visai industijai: „confusion across trust boundaries” tipo pažeidžiamumų klasė — tai būtent tai, ką LLM pagalba grįsta analizė randa geriau nei žmonės. Žmogus auditorius skaito kodą tiesiškai; grafo perėjėjas mato ryšius per dešimtis failų ir komponentų. CIFSwitch nebus paskutinė tokio tipo klaida, rasta tokiu būdu.

KODĖL PAVOJINGA

Paveikimo mastas stulbina. Manizada išbandė apie 30 distribucijų ir leidimų kombinacijų. Pažeidžiamos numatytojoje konfigūracijoje, be jokių pakeitimų: Linux Mint 21.3 ir 22.3, CentOS Stream 9 GNOME, Rocky Linux 9 Workstation, visos Kali Linux versijos nuo 2021.4 iki 2026.1 headless variante, AlmaLinux 9.7, SLES 15 SP7. Tai ne egzotika — tai pagrindinės distribucijos, veikiančios gamybos serveriuose visame pasaulyje.

Atskira istorija — debesijos atvaizdai. AlmaLinux 9.7 Azure debesijos atvaizdas pažeidžiamas iš karto — cifs-utils ten įdiegtas iš anksto. Amazon Linux 2023 pažeidžiamas esant SELinux permissive, tačiau tik jei cifs-utils įdiegtas rankiniu būdu — pagal numatytuosius nustatymus jo ten nėra. Tai reiškia, kad dalis debesijos instancijų, paleistų su pažeidžiamais atvaizdais, gali būti pažeidžiamos dabar pat — jei administratorius nespėjo atnaujinti branduolio.

Administratoriui, valdančiam bendrą hostingą ar VPS platformą, situacija ypač opi: vienas kompromituotas nuomininkas su shell prieiga reiškia visišką hosto sistemos ir visų kitų duomenų kontrolę. Įmonės aplinkoje su daugeliu kūrėjų ar aptarnavimo paskyrų — bet kuri iš jų yra potencialus privilegijų eskalavimo iki root vektorius.

KAIP IŠVENGTI PASIKARTOJIMO

CIFSwitch nėra vienišas atvejis. CopyFail (CVE-2026-31431) prieš kelis mėnesius naudojo tą patį principą: privilegijuotas komponentas pasitikėjo duomenimis, kurių kilmė nebuvo tikrinama. „Confusion across trust boundaries” atakų klasė — loginės klaidos komponentų su skirtingais privilegijų lygiais sąsajoje — pasitaiko reguliariai ir rankinio audito metu yra itin sunku ją aptikti.

Architektūrinis atsakymas — mažiausio pasitikėjimo principas: privilegijuotas komponentas neturi priimti duomenų iš mažiau privilegijuoto be aiškios kilmės patikros. Branduolio atveju tai reiškia .vet_description rakto tipo struktūroje. Userspace pagalbininkų atveju — neturėti rakto aprašymo laukų kaip branduolio kilmės be patikrinimo.

Serverių konfigūracijos lygmeniu: neprivilegijuotos user namespaces — tai funkcija, kurios dauguma gamybos serverių nenaudoja, tačiau kuri įjungta pagal numatytuosius nustatymus. Jos išjungimas viena sysctl eilute pašalina visą LPE atakų klasę, ne tik CIFSwitch. Jei cifs-utils nereikalingas — jo pašalinimas visiškai eliminuoja šio pažeidžiamumo atakos paviršių.

TAISYMO KOMANDOS

Pirmiausia — patikrinti, ar sistemoje įdiegtas cifs-utils:

dpkg -l cifs-utils 2>/dev/null || rpm -q cifs-utils 2>/dev/null

Jei paketas neįdiegtas — sistema nepažeidžiama per šį vektorių nepriklausomai nuo branduolio versijos, tolesnių žingsnių nereikia. Jei įdiegtas — skaitykite toliau.

Jei cifs-utils nereikalingas — paprasčiausias ir patikimiausias sprendimas dabar pat:

# Debian / Ubuntu
sudo apt remove cifs-utils

# RHEL / CentOS / Rocky / AlmaLinux
sudo dnf remove cifs-utils

Jei cifs-utils reikalingas, tačiau Kerberos autentifikacija SMB nenaudojama — užblokuoti request-key taisyklę. Ši komanda iš Manizados writeup pakeičia taisyklę taip, kad rakto prašymas nedelsiant atmetamas, o ne paleidžiamas pagalbininkas:

cat >/etc/request-key.d/cifs.spnego.conf <<'EOF'
create cifs.spnego * * /usr/sbin/keyctl negate %k 30 %S
EOF

Jei SMB prijungimas visai nenaudojamas — užblokuoti cifs modulio įkėlimą:

echo "install cifs /bin/true" | sudo tee /etc/modprobe.d/disable-cifs.conf

Verta taip pat išjungti neprivilegijuotas user namespaces — tai blokuoja ne tik CIFSwitch, bet ir visą panašių LPE klasę. Jei serveris nenaudoja konteinerių ar funkcijų, kurioms reikalingos user namespaces:

# Debian / Ubuntu — reikia abiejų parametrų
sudo sysctl -w kernel.unprivileged_userns_clone=0
sudo sysctl -w user.max_user_namespaces=0
printf "kernel.unprivileged_userns_clone=0\nuser.max_user_namespaces=0\n" | sudo tee -a /etc/sysctl.d/99-hardening.conf

# RHEL / CentOS / Rocky / AlmaLinux
sudo sysctl -w user.max_user_namespaces=0
echo "user.max_user_namespaces=0" | sudo tee -a /etc/sysctl.d/99-hardening.conf

Patikrinti, ar kuri nors iš priemonių suveikė, galima su oficialiu PoC. Pritaikius švelninimo priemonę, paleiskite:

git clone https://github.com/manizada/CIFSwitch
cd CIFSwitch && make && ./cifswitch

Jei PoC baigiasi negavęs root — priemonė veikia. Tai oficialus validavimo būdas iš autoriaus writeup.

ATNAUJINIMAS

Pagrindinis ilgalaikis sprendimas — atnaujinti branduolį. Pataisymas aukštesniame lygmenyje — commit 3da1fdf4efbc490041eb4f836bf596201203f8f2: prideda funkciją cifs_spnego_key_vet_description(), kuri leidžia kurti raktą tik tada, kai prašymas atėjo iš CIFS per spnego_cred. Distribucijos perkelia šį pataisymą — stebėkite savo distribucijos saugumo kanalą ir atnaujinkite kai tik paketas pasirodys:

# Debian / Ubuntu
sudo apt update && sudo apt upgrade

# RHEL / CentOS / Rocky / AlmaLinux
sudo dnf update kernel

Po atnaujinimo — paleidimas iš naujo privalomas, naujas branduolys įsigalioja tik po reboot. Įsitikinti, kad sistema paleista su atnaujintu branduoliu:

uname -r

Išvestis parodys branduolio versiją — palyginkite su pataisymo versija savo distribucijos saugumo biuletenyje. Galutinis patikrinimas — paleisti oficialų PoC: jei jis baigiasi negavęs root, branduolys turi pataisymą:

git clone https://github.com/manizada/CIFSwitch
cd CIFSwitch && make && ./cifswitch

Kol jūsų distribucijos pataisymas dar neišleistas — naudokite priemones iš aukščiau esančio skyriaus.

IŠVADOS

CIFSwitch primena, kad „saugus” nereiškia „patikrintas”. Linux branduolys praeina per daugybę auditų ir peržiūrų, SELinux ir AppArmor veikia milijonuose serverių — ir vis tiek 19 metų sena klaida dviejų komponentų sąsajoje išgyveno iki 2026-ųjų. Ne todėl, kad niekas nežiūrėjo, o todėl, kad niekas nežiūrėjo į abu vienu metu.

Jei valdote Linux serverius — pirmasis veiksmas šiandien: patikrinti, ar cifs-utils yra mašinose, kur jo neturėtų būti, ir pašalinti. Antras: išjungti neprivilegijuotas user namespaces serveriuose, kuriems jų nereikia. Trečias: stebėti distribucijos saugumo kanalą ir atnaujinti branduolį, kai tik pataisymas pasirodys.

Tiems, kas valdo VPS platformas ir bendrą hostingą — tai ne tik rekomendacija. PoC viešas, veikia, ir bet kuris nuomininkas su shell prieiga gali išbandyti jį dabar pat. Reakcijos laikas matuojamas valandomis, ne dienomis.

Leave your thought here

El. pašto adresas nebus skelbiamas. Būtini laukeliai pažymėti *