Sari la conținut
Braincap
← Toate articolele

Un popup fals de Cloudflare, două vulnerabilități în lanț și 6.369 de fișiere: anatomia unei compromiteri Magento

de Claudiu Hulea · IT Management Consultant

Ilustrație a unui popup fals de verificare Cloudflare (ClickFix) care duce la un backdoor și fișiere malițioase

Cum arată, pas cu pas, investigarea unui atac real — și de ce upgrade-ul de securitate pe care toată lumea îl crede suficient nu închide, de fapt, ușa.

Totul a început cu un angajat atent.

Într-o dimineață, cineva din echipa unui client — un magazin construit pe Magento 2.4.5 — a observat ceva ciudat pe pagina principală: un popup care imita perfect o verificare Cloudflare. „Let us know you’re human“, scria. Și trei pași simpli: apasă Win + R, apoi Ctrl + V, apoi Enter.

Pentru un ochi neantrenat, pare o verificare anti-bot obișnuită. În realitate, e una dintre cele mai eficiente tehnici de inginerie socială din ultimul an, numită ClickFix: un script copiază pe furiș o comandă în clipboard-ul victimei, apoi o convinge s-o lipească în dialogul Run al Windows-ului și s-o execute. Rezultatul — un infostealer care rulează direct pe stația angajatului, în afara oricărui antivirus care s-ar fi uitat la browser.

Popup-ul nu era decât vârful aisbergului. Ce am găsit dedesubt a fost o compromitere completă, activă de nouă luni, cu două vulnerabilități critice înlănțuite și 6.369 de fișiere malițioase presărate prin instalare.

Iată cum arată o investigație reală.

Prima privire: skimmerul din baza de date

Popup-ul ClickFix era livrat de un script terț, încărcat de pe un domeniu extern printr-un fragment de cod injectat în baza de date — mai exact într-un bloc CMS afișat pe toate paginile magazinului.

Detaliul care încurcă multe scanări automate: domeniul nu apărea niciodată în clar. Era codificat base64, ascuns într-un apel atob(). O căutare simplă SELECT ... WHERE content LIKE '%domeniu%' întoarce zero rezultate chiar și pe un site infectat. Trebuie să cauți după atob, nu după domeniu.

Am eliminat scriptul, am golit cache-ul (inclusiv Varnish — altfel skimmerul rămâne servit din cache ore întregi) și am blocat vizitatorii de a mai fi expuși. Dar asta era doar simptomul. Întrebarea reală: cum a ajuns acolo?

Vulnerabilitatea #1: PolyShell — uploadul care nu ar trebui să existe

Pe disc, în pub/media/custom_options/quote/, am găsit peste o mie de fișiere .php. Acolo nu au ce căuta niciodată fișiere PHP — e un director de upload pentru opțiunile custom ale produselor.

Fișierele erau polyglot-uri: începeau cu antetul GIF89a (deci trec de orice validare care verifică „e o imagine?“), urmat imediat de <?php. Un backdoor complet: verificare prin cookie-parolă, execuție de comenzi prin eval(base64_decode()), upload arbitrar de fișiere.

Vectorul, confirmat ulterior de cercetarea Sansec despre „PolyShell“: REST API-ul Magento pentru coșuri de oaspete, neautenticat:

POST /rest/V1/guest-carts/{cartId}/items

Adăugând un produs cu o opțiune de tip fișier, atacatorul încarcă polyglot-ul. Magento îl scrie pe disc în timpul validării, înainte să apuce să respingă ceva. Fără verificare de tip, fără restricție de extensie.

Partea neliniștitoare: pe site-ul investigat niciun produs nu avea opțiuni de tip fișier configurate, și totuși fișierele ajungeau pe disc. Vectorul e accesibil prin REST indiferent de configul magazinului.

Vulnerabilitatea #2: CosmicSting — cum s-a ajuns în baza de date

PolyShell explică webshell-urile de pe disc. Dar cum a fost injectat skimmerul în baza de date? Aici multe rapoarte se opresc la „atacatorul a injectat în CMS“ fără să spună cum.

Analiza logurilor a dat răspunsul. Skimmerul a fost scris printr-o singură cerere:

PUT /rest/V1/cmsBlock/1

…cu un token de admin valid. Dar în aceeași perioadă, 2.490 de încercări de a obține un token prin parolă au eșuat toate cu 401. Atacatorul nu avea nevoie de parolă — forja tokenul.

Cum? Prin CVE-2024-34102, cunoscut ca CosmicSting (CVSS 9.8): o vulnerabilitate XXE care permite citirea fișierului app/etc/env.php. Din el, atacatorul a extras crypt/key — cheia de criptare Magento. Iar cu acea cheie, poate semna tokenuri JWT de admin oricâte vrea.

Două vulnerabilități, în lanț: CosmicSting deschide ușa (citire fișier → furt cheie → forjare token), PolyShell oferă persistența pe disc.

Diagrama lanțului de atac: CosmicSting → forjare token de admin → skimmer în baza de date → PolyShell (persistență) → ClickFix la vizitatori

Momentele care fac diferența

O investigație bună nu e o listă de comenzi. E o serie de întrebări la care refuzi să răspunzi din reflex. Câteva care au contat aici:

Execuția a eșuat — și de ce e important. Cele peste o mie de webshell-uri erau pe disc, dar niciunul nu se executa: configul nginx bloca rularea PHP în directorul de media. Am confirmat empiric — toate cele 669 de accesări directe primeau același răspuns de 1692 bytes (pagina de fallback), nu output de webshell. Concluzia schimbă totul: atacatorul avea control asupra conținutului aplicației, dar nu asupra sistemului de operare. Serverul nu trebuia reinstalat.

Căutarea case-sensitive care aproape a ratat 140 de fișiere. Prima curățare a folosit find -name '*.php'. În Linux, asta e case-sensitive — și a ratat 140 de fișiere cu extensii .PHP, .Php, .php7..gif, .inc. Le-am prins abia refăcând scanarea după conținut (grep '<?php'), nu după extensie. Lecție: la curățare, nu te încrede în extensii.

Restricția de admin care nu restricționa nimic. Am pus o regulă nginx care limita accesul la panoul de admin la rețeaua internă. Testată din exterior — panoul răspundea în continuare 200. Cauza: lanțul de proxy-uri (Cloudflare → WAF → Varnish → nginx) făcea ca nginx să vadă ca sursă 127.0.0.1 (Varnish, pe loopback), care e „intern“, deci regula lăsa tot traficul să treacă. Fără real_ip_recursive configurat corect pe toate hop-urile, orice restricție de IP e iluzorie. E genul de greșeală care arată bine în config și nu protejează nimic.

De ce rotirea cheii nu e suficientă. Am rotit crypt/key — pas evident după ce știi că a fost furată. Dar Magento validează tokenurile JWT de admin cu toate cheile din crypt/key, nu doar cu cea curentă. Am verificat în cod: prepareAllAccepted(). Cât timp cheia compromisă rămâne în fișier, tokenurile forjate cu ea rămân valide. Cheia veche trebuie eliminată, nu doar înlocuită cu una nouă. (Cu grija de a nu strica datele deja criptate cu ea — se reencriptează întâi.)

Lecția cea mare: patch-ul pe care toată lumea îl crede suficient

După curățare, am făcut ce ar face oricine: upgrade Magento la ultimul patch de securitate de pe linia respectivă (2.4.5-p14). Asta a închis CosmicSting — nativ, verificat.

Dar nu a închis PolyShell.

Pentru că, așa cum documentează Sansec, vulnerabilitatea de upload afectează toate versiunile Magento până la 2.4.8, cu fix doar în 2.4.9 (încă în pre-release la momentul scrierii), fără backport pe liniile de producție.

Asta e capcana. Un operator conștiincios face upgrade la ultimul patch, vede că e „la zi“ și presupune că e protejat. Dar vectorul prin care au intrat 80% din magazinele Magento neprotejate în această campanie rămâne deschis în core, indiferent cât de patch-uit ești.

Soluția, până la 2.4.9, e la nivel de infrastructură și cod defensiv:

  • nginx — blochează execuția fișierelor executabile în pub/media (nu doar .php — și .php8, .phtm, .phar) și accesul complet la custom_options.
  • plugin la nivel de aplicație — respinge extensiile periculoase chiar la stratul de upload (Magento\Framework\File\Uploader), care implicit acceptă orice extensie când nu e setat un whitelist.
  • WAF — blochează endpoint-urile vulnerabile.

Niciuna nu e un patch. Toate, împreună, țin locul patch-ului.

Ce ar trebui să verifice orice operator Magento

Dacă administrezi un magazin Magento, iată checklist-ul minim scos din acest incident:

  1. Fișiere executabile în pub/media — caută după conținut, nu extensie: grep -rl '<?php' pub/media/. Orice rezultat = compromitere.
  2. Nivelul de patchbin/magento --version. Dacă nu are sufix -pN, ești vulnerabil la CosmicSting și altele.
  3. 2FA pe admin — obligatoriu în Magento 2.4, dar deseori dezactivat „ca să fie mai comod“.
  4. CSP — implicit e pe report-only (nu blochează nimic). Trebuie trecut pe enforced.
  5. Restricția de admin pe IP — și verificat că funcționează efectiv prin lanțul de proxy-uri, nu doar că e în config.
  6. Backdoor-uri de persistență — caută accesson.php și fișiere similare împrăștiate în var/, vendor/.
  7. Dacă a fost compromis — rotește crypt/key (și elimină cheia veche), parolele, tokenurile.

Concluzie

Atacatorul din spatele acestei campanii nu era sofisticat. Uneltele erau crimeware „de raft“, infrastructura era hosting offshore, iar tiparul de activitate — 24/7, fără pauză, luni întregi — arăta clar automatizare, nu țintire. Magazinul acesta a fost pur și simplu unul dintre miile scanate în masă.

Și exact asta e ideea. Nu trebuie să fii o țintă importantă ca să fii compromis. Trebuie doar să rulezi o versiune neprotejată dintr-o platformă populară, într-un moment în care un exploit public lovește 80% din magazinele vulnerabile în câteva săptămâni.

Apărarea nu a fost o singură măsură eroică. A fost un strat peste altul — execuție blocată, upload blocat, cheie rotită, WAF, headere, 2FA — fiecare acoperind ce lasă descoperit celălalt. Iar prima linie de apărare a fost, de fapt, un om atent care a observat un popup care nu era în regulă.


Braincap oferă servicii de răspuns la incidente, audit de securitate și securitate cibernetică pentru infrastructuri de comerț electronic. Dacă bănuiești o compromitere sau vrei o evaluare de securitate a magazinului tău, ne poți contacta la office@braincap.ro sau prin pagina de contact.

Surse

Întrebări frecvente

Ce a fost, pe scurt, această compromitere Magento?

O compromitere completă a unui magazin Magento 2.4.5, activă de nouă luni: un popup fals de tip ClickFix la vizitatori, un skimmer injectat în baza de date și 6.369 de fișiere malițioase pe disc. La bază, două vulnerabilități înlănțuite: CosmicSting (CVE-2024-34102) și PolyShell.

Ce sunt CosmicSting și PolyShell?

CosmicSting (CVE-2024-34102, CVSS 9.8) e o vulnerabilitate XXE care permite citirea env.php și furtul cheii de criptare, cu care atacatorul forjează tokenuri de admin. PolyShell e o vulnerabilitate de upload prin REST API-ul de coșuri de oaspete, care lasă webshell-uri polyglot pe disc. CosmicSting deschide ușa, PolyShell dă persistența.

De ce nu e suficient upgrade-ul de securitate?

Pentru că patch-ul (ex. 2.4.5-p14) închide CosmicSting, dar NU PolyShell: vulnerabilitatea de upload afectează toate versiunile până la 2.4.8, cu fix doar în 2.4.9. Un operator „la zi" rămâne expus prin acest vector. Până la 2.4.9, apărarea e la nivel de infrastructură: blocarea execuției în pub/media, respingerea extensiilor periculoase la upload, WAF.

Ce ar trebui să verifice un operator Magento?

Fișiere executabile în pub/media (caută după conținut, `grep -rl "<?php" pub/media/`), nivelul de patch (`bin/magento --version`), 2FA pe admin, CSP pe enforced (nu report-only), restricția de admin pe IP care chiar funcționează prin lanțul de proxy, backdoor-uri de persistență, și — dacă a fost compromis — rotirea și eliminarea cheii vechi crypt/key.

Articole similare