Joi, 22 octombrie, ora 4:27 dimineața. Pe ecran, un terminal deschis pe primul server. Tocmai rulasem comanda care trebuia să-mi spună dacă pachetele PHP reparate au ajuns. Răspunsul: nimic. Nicio linie.
În meseria asta, „nimic” e cel mai înșelător răspuns posibil. Poate să însemne „ești deja la zi”. Poate să însemne „pachetele încă n-au ajuns la tine”. Sau poate să însemne că ai pus întrebarea greșit. Cu o zi înainte, echipa PHP publicase unul dintre cele mai grave anunțuri de securitate din ultimii ani: două vulnerabilități critice care permit preluarea controlului asupra unui server web fără parolă, fără cont și fără ca atacatorul să aibă nevoie de vreun plugin vulnerabil.
Articolul ăsta e povestea acelei nopți: ce s-a întâmplat pe 21 octombrie 2026, ce am făcut, pas cu pas, pe serverele pe care găzduim și administrăm site-urile clienților, ce a mers, ce s-a stricat pe parcurs și, mai ales, ce n-a scris nimeni în anunțurile oficiale. Toate detaliile despre clienți sunt anonimizate. Lecțiile, nu.
Ce s-a întâmplat pe 21 octombrie, pe scurt
Pe 21 octombrie 2026, proiectul PHP a lansat de urgență versiunile 8.5.12, 8.4.27, 8.3.36 și 8.2.35. Ele repară două vulnerabilități notate CVE-2026-109618 și CVE-2026-109619, ambele cu scorul 9.2 din 10 (CVSS v4.0). Comunitatea de securitate le-a botezat rapid „php2shell”, un nume care spune tot: de la PHP direct la un shell pe server, adică la control complet.
Pe scurt, cele două probleme sunt:
- CVE-2026-109618, „RCE prin coruperea memoriei la OOM”. Când PHP rămâne fără memorie exact în momentul în care pregătește o cerere, se poate opri la jumătatea drumului, cu date interne doar parțial inițializate. La curățenia de după, motorul tratează acele date stricate ca fiind valide, iar atacatorul poate folosi asta ca să ruleze cod.
- CVE-2026-109619, „RCE prin stare globală rămasă”. O bucată de stare internă care aparține unei cereri poate supraviețui după ce memoria ei a fost eliberată. Următoarea cerere procesată de același proces PHP o poate folosi înainte să fie resetată. Pe scurt: o cerere a atacatorului poate „otrăvi” procesul pentru cererea următoare.
Anunțul oficial e clar: orice instalare PHP care servește pagini web e expusă, indiferent cum rulează PHP pe server: PHP-FPM, Apache cu mod_php, php-cgi, FrankenPHP sau LiteSpeed. Riscul cel mai mare e la Apache cu mod_php, unde există o demonstrație în care o singură cerere anonimă declanșează atacul înainte să ruleze vreo linie din aplicație. Detaliile complete sunt în anunțul de securitate de pe php.net.
De ce e mai grav decât o vulnerabilitate obișnuită de WordPress
Am scris în vară despre wp2shell, breșa critică din nucleul WordPress. Atunci spuneam că e neobișnuit de gravă pentru că nu depindea de niciun plugin. php2shell merge un etaj mai jos.
Gândește-te la site-ul tău ca la o clădire. WordPress e apartamentul tău. Pluginurile sunt mobila. PHP e fundația pe care stă tot blocul. Cele mai multe probleme de securitate sunt în apartament sau în mobilă: un plugin vechi, o parolă slabă, o temă piratată. De data asta, crăpătura era în fundație.
Asta înseamnă trei lucruri concrete:
- Nu contează cât de bine e întreținut WordPress-ul tău. Poți avea nucleul la zi, zero pluginuri vechi, autentificare în doi factori și parole de 30 de caractere. Atacul are loc înainte ca WordPress să apuce să pornească.
- Nu e doar o problemă WordPress. E expus orice site scris în PHP: magazine pe alte platforme, aplicații făcute la comandă, panouri de administrare, formulare vechi uitate pe un subdomeniu.
- Pluginurile de securitate nu ajută. Un plugin de securitate e cod PHP care rulează în interiorul WordPress-ului. Dacă atacul are loc înainte de WordPress, pluginul nici nu apucă să afle că a existat.
Singura reparație completă e actualizarea PHP-ului însuși. Iar asta nu se face din panoul WordPress, ci pe server, de către cine administrează serverul.
Cronologia, oră cu oră
Orele de mai jos sunt în ora României, ca să fie ușor de urmărit.
Marți, 20 octombrie. Echipa de securitate PHP anunță în avans o lansare critică pentru a doua zi, la ora 17:00, cu două vulnerabilități notate 9.2. Își rezervă dreptul să lanseze mai devreme dacă detaliile devin publice sau dacă apar atacuri reale. În aceeași zi, detalii despre vulnerabilități încep să circule public, înainte să existe un patch.
Miercuri, 21 octombrie, dimineața. Primele atacuri reale sunt raportate înainte de lansarea reparației. Exact scenariul de care se temea echipa PHP.
Miercuri, 21 octombrie, în jur de 16:35. PHP publică versiunile reparate, cu aproximativ 25 de minute înainte de ora anunțată. Pentru PHP 8.1, 8.0 și 7.4, versiuni care nu mai primesc oficial actualizări, echipa publică totuși patch-uri minimale de cod sursă, tocmai din cauza gravității.
Miercuri seara. cPanel publică pachetele PHP reparate pentru serverele care folosesc EasyApache, inclusiv reparații aduse înapoi pentru 7.4, 8.0 și 8.1. Imunify360 publică un set de reguli de firewall care blochează forma cunoscută a exploit-ului.
Miercuri, 21 octombrie, ora 22:00. CloudLinux publică primele sale pachete PHP reparate. Distribuirea continuă treptat, versiune cu versiune, toată noaptea.
Joi, 22 octombrie, 4:27 – 6:10. Patch-uim cinci servere de producție, cu câteva sute de domenii găzduite. Despre asta e restul articolului.
Noaptea de 21 spre 22: cum am lucrat
Serverele noastre rulează cPanel pe CloudLinux, cu LiteSpeed ca server web. E o combinație foarte des întâlnită în găzduirea web, așa că e posibil să semene cu ce există și sub site-ul tău. Pe fiecare server rulează simultan mai multe versiuni de PHP, pentru că nu toate site-urile pot folosi cea mai nouă versiune.
Pasul 1: întrebarea corectă, nu doar comanda corectă
Prima comandă din noaptea aceea căuta pachete cu numerele noi de versiune: 8.2.35, 8.3.36, 8.4.27, 8.5.12. N-a găsit nimic. Prima reacție ar fi fost „încă n-au apărut, mai așteptăm”. Ar fi fost o greșeală.
Pe serverele cu CloudLinux, pachetele PHP pentru cPanel nu vin direct de la cPanel, ci printr-un depozit propriu al CloudLinux. Pachetele lor reparate păstrau numărul vechi de versiune. Un PHP afișat ca 8.3.35, deci aparent vulnerabil, era de fapt reparat. Reparația era adusă înapoi în codul vechi și marcată doar în numărul intern al pachetului și în jurnalul de modificări.
Așa că am schimbat întrebarea: nu „ce număr de versiune am?”, ci „ce scrie în jurnalul de modificări al pachetului instalat?”. Dacă apare acolo CVE-2026-109618, pachetul e reparat, indiferent de număr. Asta a devenit testul de bază pentru tot restul nopții.
Pasul 2: măsura de avarie, înainte de reparație
Până la instalarea pachetelor, am aplicat pe toate versiunile de PHP măsura temporară recomandată chiar de echipa PHP: dezactivarea unei funcții numite session.upload_progress.
Ce face funcția asta, pe înțelesul tuturor: când trimiți un fișier printr-un formular, PHP poate nota în sesiunea ta, pe server, cât s-a încărcat până acum, ca o pagină să-ți arate o bară de progres. Problema e că PHP face asta singur, înainte să ruleze orice cod al site-ului, pentru orice vizitator, cu date trimise de vizitator. E exact genul de ușă pe care exploit-ul public o folosea.
Practic nu pierzi nimic dacă o oprești. Barele de progres moderne, din WordPress, Elementor sau WooCommerce, măsoară încărcarea direct în browser și nu au nevoie de ea. Am oprit-o la nivel de server, în fișierele de configurare PHP, nu din setările fiecărui site. Echipa PHP subliniază explicit că setarea trebuie aplicată acolo unde nu poate fi anulată de aplicație.
Echipa PHP e și ea foarte clară că asta nu e o reparație. Blochează calea de atac confirmată, nu și variantele ei. E un plasture pentru câteva ore, nu o soluție.
Pasul 3: patch-urile, server cu server
Am instalat apoi pachetele reparate pe fiecare server și am verificat fiecare versiune de PHP în parte, citind jurnalul de modificări. Pe primul server au venit peste 200 de pachete dintr-o singură actualizare. Pe cel mai mare, care are aproape toate versiunile de PHP din ultimii 20 de ani, actualizarea a durat câteva minute bune.
O surpriză plăcută: CloudLinux a reparat și versiuni pe care cPanel nu le mai repară deloc, precum PHP 7.3 și chiar PHP 5.6. Pentru câteva site-uri vechi, care nu pot rula pe versiuni noi fără să fie refăcute, diferența a fost uriașă. În loc de o mutare forțată pe o altă versiune, peste noapte, cu riscul să nu mai meargă, au primit pur și simplu reparația.
Pasul 4: versiunile pe care nu le folosea nimeni
Odată cu patch-urile am făcut și un inventar: ce versiuni de PHP sunt instalate pe fiecare server și câte site-uri folosesc efectiv fiecare versiune. Rezultatul a fost instructiv. Pe un server existau versiuni instalate de PHP fără niciun site pe ele, care primeau totuși update-uri și ocupau loc degeaba. Pe altul, PHP 4.4 și PHP 5.1, versiuni de acum aproape 20 de ani, erau încă disponibile clienților și nu primiseră nicio reparație. Nu le folosea nimeni, așa că le-am dezactivat. O versiune pe care n-o mai poate alege nimeni e o problemă în minus.
Ce n-a scris nimeni în anunțuri
Anunțurile oficiale spun „actualizați imediat”. Au dreptate. Ce nu spun e cum arată, concret, o actualizare de urgență pe servere reale, cu site-uri reale, la patru dimineața. Iată ce am învățat.
1. Numărul versiunii poate să mintă, în ambele sensuri
Am văzut deja că un PHP 8.3.35 poate fi perfect reparat. Reversul e la fel de adevărat: multe distribuții Linux aplică reparații fără să schimbe numărul afișat. Concluzia practică pentru tine e că numărul de versiune din WordPress, din Sănătatea site-ului, nu-ți spune singur dacă ești protejat. Dacă vezi 8.3.36 sau mai nou, ești sigur în regulă. Dacă vezi un număr mai vechi, nu înseamnă automat că ești vulnerabil, dar înseamnă că trebuie să întrebi.
2. Un răspuns gol nu înseamnă „totul e în regulă”
Prima comandă din noaptea aceea n-a afișat nimic. Dacă m-aș fi oprit acolo, aș fi crezut fie că totul e la zi, fie că nu e nimic de făcut. În securitate, absența unei alarme nu e același lucru cu absența unei probleme. Orice verificare trebuie să-ți arate explicit „da, e reparat”, nu doar să tacă.
3. Firewall-ul nu te acoperă peste tot la fel
Imunify360 a publicat foarte repede reguli care recunosc forma exploit-ului public. Excelent. Doar că, după propria lor documentație, pe serverele cu Apache și ModSecurity regulile blochează atacul, iar pe serverele cu LiteSpeed doar îl înregistrează în jurnal. Pe LiteSpeed, firewall-ul vedea atacul, dar nu-l oprea.
Dacă te bazai doar pe firewall ca să câștigi timp până la patch, pe un server cu LiteSpeed n-aveai, de fapt, nicio protecție din partea lui. Am explicat mai pe larg ce face și ce nu face un firewall aplicativ (WAF). Episodul ăsta e un exemplu perfect.
4. O actualizare de securitate poate să pice site-uri
Asta a fost partea cea mai neplăcută a nopții. După actualizarea pe al treilea server, un magazin online găzduit acolo a început să afișeze „503 Service Unavailable”. Și nu doar el: toate site-urile de pe acel server erau afectate.
Cauza: pe serverele CloudLinux, fiecare client rulează într-o „cușcă” izolată, numită CageFS, care are propria copie a anumitor fișiere de sistem. După actualizarea PHP, cușca trebuie reîmprospătată ca să vadă versiunile noi. Altfel PHP nu mai pornește pentru clienții din cușcă, iar serverul web răspunde cu 503. Reîmprospătarea durează un minut. Site-urile au revenit imediat.
De atunci, pasul de reîmprospătare face parte automat din procedura noastră de actualizare. Lecția mai generală: orice actualizare urgentă e urmată de o verificare a site-urilor, nu doar a pachetelor. Faptul că pachetul e instalat corect nu înseamnă că site-ul merge.
5. Patch-ul schimbă comportamentul PHP
Reparația pentru prima vulnerabilitate vine cu o schimbare de comportament scrisă în jurnalul de modificări al pachetelor: când un script depășește limita de memorie, procesul PHP este acum oprit de tot. Înainte primeai un mesaj de eroare și scriptul se termina „ordonat”. Acum vizitatorul vede o pagină de eroare goală, iar mesajul ajunge doar în jurnalul serverului.
Pentru un site sănătos nu se schimbă nimic. Pentru un magazin WooCommerce mare, cu un import de produse care trecea la limită de memorie, se poate schimba mult. Dacă în zilele următoare vezi erori 500 sau 503 „din senin” pe anumite pagini, întreabă-ți administratorul dacă nu cumva un script lovește limita de memorie.
6. O urgență scoate la suprafață datoria tehnică
Ca să aplici o setare pe toate versiunile de PHP, trebuie să te uiți în configurația fiecăreia. Când te uiți, găsești lucruri. În noaptea aceea am găsit:
- O setare a sesiunilor PHP configurată greșit pe mai multe versiuni, cu o valoare pe care versiunile noi de PHP o resping. Rezultatul era un avertisment scris în jurnale la fiecare pornire a unui proces PHP, adică de mii de ori pe zi. Inofensiv, dar umplea jurnalele și ascundea erorile adevărate.
- O extensie de procesare a imaginilor încărcată de două ori pe aceeași versiune de PHP, o dată instalată de mână și o dată prin managerul de pachete.
- Versiuni de PHP fără niciun site pe ele, dar instalate și actualizate.
- Versiuni de PHP de acum aproape 20 de ani, încă disponibile pentru clienți.
Niciuna nu era urgentă în sine. Toate erau lucruri care, într-o zi obișnuită, nu-și găsesc niciodată rândul. Am scris mai demult despre tiparele pe care le vezi administrând multe servere deodată. Asta e unul dintre ele: cele mai multe probleme nu apar când le cauți, ci când repari altceva.
7. Scripturile se strică exact când ai mai mare nevoie de ele
Am scris un singur script care să facă totul pe toate serverele: actualizare, setarea de avarie, repornire, verificare. A trebuit corectat de două ori în aceeași noapte. PHP 8.5 afișează căile fișierelor de configurare între ghilimele, iar scriptul le citea greșit. Versiunile foarte vechi de PHP nu înțeleg o opțiune modernă și, în loc să dea eroare, așteaptă la nesfârșit cod de la tastatură. Scriptul a rămas blocat pe ultimul server până l-am corectat.
Nu e un argument împotriva automatizării. Fără script, aceeași muncă ar fi durat o zi întreagă. E un argument pentru ca orice automatizare să fie urmărită de un om când rulează pe producție, mai ales prima dată.
Ce înseamnă asta pentru tine, dacă ai un site
Dacă ai un site în PHP, iar WordPress, WooCommerce și majoritatea site-urilor de prezentare din România sunt în PHP, situația ta depinde de cine administrează serverul.
Dacă ai găzduire partajată
Firma de găzduire se ocupă de PHP pentru toți clienții de pe server. Nu poți instala tu patch-ul. Poți însă să întrebi, iar mai jos ai exact întrebările. Un furnizor serios îți răspunde în câteva ore, cu date concrete. Un răspuns de tipul „serverele noastre sunt sigure”, fără nicio dată și nicio versiune, e un semnal de alarmă.
Dacă ai un VPS sau un server propriu
Atunci tu, sau cine îți administrează serverul, sunteți responsabili. Ai nevoie de actualizarea PHP pe toate versiunile instalate, nu doar pe cea folosită de site-ul principal, de repornirea tuturor proceselor PHP și de o verificare a fiecărui site după actualizare. Dacă serverul are cPanel, actualizarea vine prin EasyApache. Dacă are și CloudLinux, nu uita pasul cu CageFS.
Dacă site-ul tău rulează pe PHP 8.1 sau mai vechi
Proiectul PHP nu mai repară oficial aceste versiuni. Unii furnizori au adus reparația și pentru ele: cPanel pentru 7.4, 8.0 și 8.1, iar CloudLinux pentru multe versiuni mai vechi. Dar asta depinde de cine ți-a instalat PHP-ul. Episodul ăsta e cel mai bun moment să pui pe hârtie un plan de trecere la o versiune suportată. Site-urile rămase pe versiuni vechi nu sunt doar mai lente, ci depind de bunăvoința unui furnizor ca să mai primească reparații.
Cum verifici rapid ce versiune de PHP ai
În panoul WordPress mergi la Unelte → Sănătatea site-ului → Informații → Server. Acolo vezi versiunea PHP. Ține minte ce am spus mai sus: 8.2.35, 8.3.36, 8.4.27, 8.5.12 sau mai nou înseamnă sigur în regulă. Un număr mai mic nu înseamnă automat vulnerabil, dar înseamnă că trebuie să întrebi.
3 întrebări pentru firma de găzduire sau pentru omul tău de IT
Dacă n-ai timp de nimic altceva din articolul ăsta, trimite aceste trei întrebări celui care îți administrează serverul:
1. „Ați instalat pachetele PHP care repară CVE-2026-109618 și CVE-2026-109619, pe toate versiunile de PHP de pe server?” Cuvântul important e „toate”. Un server are de obicei mai multe versiuni de PHP, iar site-ul tău poate rula pe una mai veche decât cea implicită.
2. „Cum ați verificat?” Răspunsul bun menționează jurnalul de modificări al pachetelor sau numerele de versiune reparate. Răspunsul slab e „am dat update”.
3. „Ați repornit procesele PHP după actualizare?” Un PHP actualizat pe disc, dar cu procesele vechi încă pornite în memorie, rulează în continuare codul vulnerabil.
Pentru colegii administratori de servere
Dacă administrezi servere cPanel cu CloudLinux, iată pe scurt ce ne-a ajutat în noaptea aceea.
Verifică reparația în jurnalul de modificări, nu în numărul de versiune:
for p in $(rpm -qa 'ea-php*-php-common' 'alt-php*-common' | sort); do
printf '%-58s ' "$p"
rpm -q --changelog "$p" | head -20 | grep -q 'CVE-2026-109618' && echo FIX || echo "FARA FIX"
done
După orice actualizare de pachete PHP pe un server cu CageFS, reîmprospătează cușca și repornește procesele PHP. Altfel riști 503 pe toate site-urile:
cagefsctl --force-update
/usr/local/lsws/bin/lswsctrl restart; pkill lsphp
Pune setarea session.upload_progress.enabled = 0 într-un fișier din directorul de configurări al fiecărei versiuni, nu în .user.ini, pe care clienții îl pot suprascrie. Pe pachetele reparate funcția e oricum scoasă din cod, așa că setarea nu mai are efect acolo. Pe orice versiune încă nereparată, însă, te protejează.
Și încă un lucru: când rulezi binare PHP vechi într-un script, rulează-le fără tastatură atașată (</dev/null) și cu o limită de timp. Altfel unul dintre ele s-ar putea să aștepte la nesfârșit.
Întrebări frecvente despre php2shell
Am un site WordPress actualizat la zi. Sunt protejat?
Nu neapărat. php2shell e în PHP, nu în WordPress. Un WordPress perfect întreținut, pe un PHP nereparat, rămâne vulnerabil.
Pluginul meu de securitate mă protejează?
Nu. Atacul poate avea loc înainte ca WordPress și pluginurile să pornească. Un firewall la nivel de server poate ajuta temporar, dar nu pe toate tipurile de server web, cum am văzut mai sus.
Ce înseamnă „RCE”?
Remote Code Execution, adică execuție de cod de la distanță. Pe scurt, atacatorul poate rula ce vrea pe server: poate citi baza de date, poate modifica site-ul, poate trimite spam sau poate folosi serverul pentru alte atacuri.
De unde știu dacă am fost deja atacat?
Exploit-ul a circulat înainte de reparație, așa că întrebarea e legitimă. Semnele sunt cele obișnuite ale unui site compromis: fișiere PHP noi și necunoscute, utilizatori administratori pe care nu i-ai creat, redirecționări ciudate, conținut spam. Am adunat cele 7 semne că un site WordPress a fost spart. Un administrator poate verifica și jurnalele serverului pentru cereri suspecte din 20–22 octombrie.
Firma mea de găzduire nu răspunde. Ce fac?
Dacă după 48 de ore nu primești un răspuns concret, e un semn bun că e timpul să te uiți după alt furnizor. Până atunci, asigură-te că ai un backup funcțional, păstrat în afara serverului de găzduire.
Trebuie să schimb versiunea de PHP?
Nu pentru php2shell, dacă versiunea ta a primit reparația. Dar dacă ești pe 8.1 sau mai vechi, planifică o trecere. Iar PHP 8.2 nu mai primește reparații de securitate după 31 decembrie 2026.
Ce facem noi pentru clienții WebFixer în astfel de situații
Pentru clienții noștri, php2shell s-a terminat înainte de începutul zilei de lucru de joi. Pachetele reparate au fost instalate pe toate serverele, pe toate versiunile de PHP folosite de site-uri. Fiecare reparație a fost verificată în jurnalul de modificări al pachetului, nu după numărul de versiune, iar site-urile au fost urmărite după actualizare. Cele mai vechi versiuni de PHP, pe care nu le mai folosea nimeni, au fost dezactivate. Clienții n-au trebuit să facă nimic și, cu excepția câtorva minute de 503 pe un singur server, n-au simțit nimic.
Nu e vorba de vreun noroc. Urmărim direct anunțurile de securitate de la PHP, WordPress, cPanel și CloudLinux, avem acces administrativ la servere și o procedură pentru exact astfel de nopți. Iar după fiecare episod de genul ăsta, procedura devine puțin mai bună. Pasul cu CageFS, de exemplu, e acum automat.
Dacă nu știi pe ce PHP rulează site-ul tău, dacă furnizorul tău de găzduire nu ți-a răspuns sau dacă vrei pur și simplu să nu mai fie problema ta, începe cu un audit gratuit. Îți spunem ce putem verifica din exterior și ce ar trebui făcut. Iar dacă vrei ca data viitoare să dormi liniștit în timp ce altcineva patch-uiește serverele la patru dimineața, pachetele WebFixer pornesc de la 49 € pe lună.
Descoperă mai multe la WebFixer
Abonează-te ca să primești ultimele articole prin email.