CVE-2026-31431 (Copy Fail): Cum a atenuat-o Appbox
O vulnerabilitate gravă din kernelul Linux, CVE-2026-31431, a fost dezvăluită săptămâna trecută. Iată cum a atenuat-o Appbox și cum a lansat remedierea kernelului Debian.
CVE-2026-31431 (Copy Fail) - Cum am atenuat-o
Săptămâna trecută a fost dezvăluită o vulnerabilitate gravă de escaladare locală a privilegiilor în kernelul Linux: CVE-2026-31431, poreclită "Copy Fail". Aceasta afectează o gamă largă de versiuni de kernel din distribuțiile Linux moderne, iar un exploit public a apărut rapid după dezvăluire.
Vreau să fiu direct în privința a ceea ce s-a întâmplat, ce înseamnă pentru Appbox și ce am făcut în această privință. Pe scurt: datorită modului în care sunt construite containerele noastre, aplicațiile care rulează cu remaparea namespace-urilor de utilizator erau deja protejate împotriva transformării acestei probleme în root pe gazdă, chiar înainte ca kernelurile remediate să fie lansate. Ieri (4 mai 2026), am efectuat și o mentenanță de urgență pentru a actualiza fiecare server la un kernel remediat, astfel încât bugul este acum complet eliminat din flota noastră.
Ce este "Copy Fail"?
CVE-2026-31431 este o vulnerabilitate în API-ul criptografic AF_ALG al kernelului. Prin asocierea la un anumit cifru (authencesn(hmac(sha256),cbc(aes))) și abuzarea modului în care kernelul îmbină paginile într-un buffer temporar, un utilizator local neprivilegiat poate scrie fragmente arbitrare de 4 octeți direct în page cache-ul fișierelor pe care nu ar trebui să aibă permisiunea să le modifice - inclusiv binare SUID precum /usr/bin/su.
După ce copia din page cache a lui su este suprascrisă cu un mic ELF malițios, următoarea invocare rulează codul atacatorului ca UID 0. Sfârșitul jocului pentru gazdă.
Pentru detaliile tehnice complete (dezasamblare shellcode, urme syscall și tot restul), analiza lui Andrea Veri este excelentă: CVE-2026-31431: Copy Fail vs. rootless containers. El a făcut și munca de a demonstra - cu eBPF și dovezi uid_map - exact ceea ce vom discuta în continuare: faptul că namespace-urile de utilizator neutralizează acest exploit.
De ce aplicațiile Appbox erau deja protejate
Exploitul se bazează pe faptul că setuid(0) acordă efectiv root pe gazdă. Într-un container care rulează cu namespace-uri de utilizator activate, nu asta se întâmplă.
Namespace-urile de utilizator mapează spațiul UID al containerului la un interval UID diferit (neprivilegiat) pe gazdă. Așadar, când exploitul reușește în interiorul containerului și setuid(0) returnează succes, shellul "root" rezultat este mapat la un utilizator obișnuit neprivilegiat al gazdei - nu la root real. Shellcode-ul rulează, promptul se schimbă în #, dar pe gazdă:
podman 27943 0.0 0.0 2984 2028 pts/1 S+ 22:15 0:00 sleep 100
Atât. Fără acces la fișierele gazdei, fără /etc/shadow, fără root pe gazdă. Limita namespace-ului containerului oprește această problemă să devină o evadare către root pe gazdă.
La nivel de platformă, fiecare Appbox primește propriul daemon Docker pornit cu remaparea namespace-urilor de utilizator activată. În pseudocod, arată mai degrabă așa:
start_docker_daemon(
userns_remap = appbox_id,
container_namespace = appbox_id
)Acea mapare este susținută de un interval subordonat UID/GID dedicat pe gazdă:
write "/etc/subuid" -> "<appbox-id>:<host-subuid-start>:65536"
write "/etc/subgid" -> "<appbox-id>:<host-subgid-start>:65536"În plus, definițiile aplicațiilor pot în continuare suprascrie explicit UsernsMode atunci când o aplicație necesită tratament special:
container_config = {
userns_mode: app.userns_mode,
network_mode: app.network_mode,
...
}Așadar, descrierea corectă este: remaparea namespace-urilor de utilizator face parte din setarea implicită a platformei, iar excepțiile per aplicație sunt explicite. Există un număr mic de aplicații care au nevoie de setări diferite deoarece expun funcționalități ce necesită capabilități suplimentare, iar acele cazuri sunt gestionate separat.
Cu alte cuvinte: pentru aplicațiile care rulează cu configurația normală remapată, Copy Fail nu putea transforma compromiterea unui container în root pe gazdă.
Ce am vrut totuși să remediem
Namespace-urile de utilizator opresc evadarea către gazdă, dar nu fac bugul să dispară în interiorul containerului. Un atacator ar fi putut totuși să escaladeze la "root în container" în limita aplicației, ceea ce, deși izolat, tot reprezintă o igienă slabă de securitate. Kernelul însuși era vulnerabil, iar noi am vrut ca această problemă să dispară.
Imediat ce am aflat despre bug, am început să ne evaluăm expunerea. Chiar dacă remaparea namespace-urilor de utilizator bloca deja partea de evadare către gazdă pentru configurația noastră normală de aplicații, am vrut ca bugul de kernel de bază să fie eliminat cât mai repede posibil.
Ce am făcut ieri
Duminică noaptea am programat mentenanță de urgență pentru luni, 4 mai 2026, prima fereastră în care puteam lansa o actualizare de kernel la nivelul întregii flote.
În timpul ferestrei:
- Fiecare gazdă a fost actualizată folosind pachetele oficiale de kernel Debian care conțin remedierea pentru "Copy Fail".
- Obiectivul a fost simplu: să eliminăm complet calea vulnerabilă din kernel, nu doar să ne bazăm pe izolarea existentă prin namespace-uri.
Mentenanța este finalizată. Fiecare gazdă Appbox rulează acum un kernel remediat.
Ce înseamnă asta pentru tine
- Nu a trebuit să faci nimic. Aplicațiile tale au continuat să ruleze, iar singurul efect vizibil pentru clienți au fost eventualele întreruperi foarte scurte din timpul ferestrei de mentenanță.
- Chiar înainte de remedierea de ieri, remaparea namespace-urilor de utilizator însemna că acest bug nu putea transforma compromiterea unei aplicații normale în root pe gazdă. Acesta este exact tipul de scenariu pentru care există acest model de izolare.
- În continuare, politica noastră rămâne neschimbată: namespace-urile de utilizator rămân activate implicit, iar foarte puținele excepții trec printr-o revizuire suplimentară de securitate.
Imaginea de ansamblu
Acesta este unul dintre acele CVE-uri în care titlul ("escaladare locală a privilegiilor, exploit public, fiecare kernel modern afectat") sună catastrofal, iar pentru multe medii multi-tenant chiar a fost. Motivul pentru care nu a fost catastrofal pentru noi este același motiv pentru care am luat, cu ani în urmă, decizii arhitecturale care uneori ne costă puțină compatibilitate: rulăm aplicațiile cu principiul privilegiilor minime integrat în stratul de containere, nu adăugat ulterior.
Apărarea în profunzime chiar funcționează. Bug la nivelul kernelului? Stratul de namespace l-a prins. Bug la nivelul namespace-ului? Reducerea capabilităților și seccomp prind mare parte din rest. Nu pretindem că vreun singur strat este perfect; ne asigurăm doar că există întotdeauna încă unul.
Dacă ai întrebări despre acest lucru sau despre modul în care sunt configurate aplicațiile tale specifice, te rugăm să ne contactezi.
Ai întrebări? Contactează-ne la support@appbox.co sau deschide un tichet la billing.appbox.co.
