Cea mai utilă frază din analiza post-incident a Brevo e o recunoaștere despre detecție, nu despre breșă.
Fiindcă Worker-ul malițios de Cloudflare rescria răspunsurile la marginea rețelei și elimina antete de securitate precum Content-Security-Policy, serverele și fișierele de origine au rămas nemodificate — iar verificările standard de integritate nu au sesizat schimbarea.
Totul de pe server era corect. Problema era în tranzit.
Ce s-a întâmplat
Atacatorii au obținut o cheie API Cloudflare de lungă durată, cu permisiuni complete pe cont, care fusese scrisă direct în codul sursă al aplicației Brevo. Cheia ar fi putut fi expusă încă de la finalul lui august, deși Brevo nu raportează dovezi de utilizare malițioasă anterioară.
Pe 14 septembrie au folosit-o ca să creeze un Cloudflare Worker, împreună cu rute și înregistrări DNS în zonele Brevo, fără să declanșeze vreo alertă. Timp de aproximativ cinci ore și jumătate, Worker-ul a modificat conținutul pe măsură ce ieșea din CDN.
Printre resursele afectate: pagini de pe brevo.com, sendinblue.com, subdomeniile de autentificare, cont și onboarding, și sibforms.com — plus scriptul de formulare Brevo, widgetul Conversations și loaderul de SDK pe care clienții îl încorporează pe propriile site-uri.
Sansec a observat activitatea malițioasă între 16:05 și 20:13 UTC și estimează că peste 100.000 de site-uri de clienți ar fi putut încărca o componentă afectată.
Cifra asta cere atenție. E numărul site-urilor care ar fi putut servi fișierul, nu numărul celor compromise. Ce s-a întâmplat efectiv cu un vizitator a depins de cine era.
Două payload-uri, alese după vizitator
Dacă erai administrator WordPress autentificat, scriptul încerca să instaleze un plugin, adus de pe un subdomeniu CDN al Brevo controlat de atacatori.
Se prezintă drept „Web Media Optimizer". Odată instalat, se ascunde din lista de pluginuri WordPress, se copiază în directorul de must-use plugins ca să se încarce automat și să nu poată fi dezactivat din interfață, și contactează periodic un server al atacatorilor pentru un URL codificat Base64 cu JavaScript de injectat în paginile vizitatorilor. Păstrează o copie de rezervă a ultimului URL funcțional, ca să continue să meargă dacă acel server cade.
Plantează și o cheie de autentificare scrisă în cod, care permite atacatorului să genereze o sesiune validă de administrator fără să știe vreo parolă.
Dacă erai oricine altcineva, primeai o pagină falsă de verificare Cloudflare pe tot ecranul, urmată de instrucțiuni ClickFix care îți cereau să lipești o comandă în Windows.
Suprapunerea a fost arătată celor care navigau pe site-urile clienților — și, notabil, celor care apăsau un link de dezabonare dintr-un e-mail de campanie trimis prin Brevo.
Malware-ul conținea și verificări pentru a evita crawlerele, dezvoltatorii și scanerele automate, motiv pentru care unii oameni au raportat că n-au văzut nimic în neregulă.
De ce e ăsta modul de eșec interesant
Majoritatea monitorizărilor de integritate a site-urilor urmăresc fișierele de pe serverul de origine. Sume de control, control al versiunilor, detecție de modificări. Nimic nu se declanșează aici, pentru că nimic de pe origine n-a fost atins.
Același lucru e valabil pentru antetele de securitate. Content-Security-Policy e o apărare livrată prin același răspuns ca și conținutul pe care ar trebui să-l protejeze. Dacă ceva poate rescrie răspunsul, poate elimina mai întâi antetul.
Apărările unui site călătoresc pe același canal ca și conținutul lui. Compromiți canalul și le obții pe amândouă.
Controlul care ar fi ajutat pentru scripturile terțe încorporate e Subresource Integrity — un hash pe eticheta <script>, care face browserul să refuze un fișier ce nu se potrivește.
Merită spus onest de ce aproape nimeni nu-l folosește aici. SRI cere ca hash-ul să se schimbe de fiecare dată când furnizorul actualizează fișierul, iar widgeturile de marketing se actualizează des și fără preaviz. Costul folosirii lui e că lucrurile se rup; costul nefolosirii e exact asta. E un compromis real, nu o scăpare, și merită decis deliberat, nu din inerție.
Ce se verifică, concret
Sansec a publicat instrucțiuni concrete de căutare. Dacă site-ul tău încorporează trackerul Brevo, widgetul de chat sau un formular găzduit Brevo, a servit un fișier afectat în acel interval.
Jurnal de acces, 14 septembrie POST /wp-admin/update.php?action=upload-plugin GET /wp-admin/plugins.php?action=activate (la scurt timp dupa)
Pluginuri Orice plugin instalat sau activat pe 14 septembrie Compara directorul de pluginuri de pe disc cu ecranul de administrare — pluginul se ascunde din lista Verifica directorul de must-use plugins
Daca gasesti ceva Roteste parolele de administrator si invalideaza sesiunile. Cheia de autentificare din cod inseamna ca doar schimbarea parolei nu e suficienta cat timp pluginul e acolo.
Iar pentru oameni, nu pentru servere: oricine a văzut o pagină întreagă cu „confirmă că ești om" și i-a urmat instrucțiunile a rulat o comandă pe propriul calculator. Acel dispozitiv are nevoie de o scanare, iar credențialele folosite pe el trebuie tratate ca expuse.
Al doilea incident în aceeași săptămână
Pe 10 septembrie, Brevo a comunicat o compromitere separată, în care un atacator a exploatat un acces SAML SSO configurat prea larg, ajungând la 138 de conturi de clienți, exportând contacte din 43 și trimițând phishing din șase.
Una dintre victimele din aval a fost Trezor, care a raportat că phishingul rezultat a ajuns la 347.000 de adrese de e-mail și a compromis efectiv cel puțin 2.500 de utilizatori.
Brevo nu a stabilit public dacă cele două incidente au legătură și nu a răspuns la întrebare când i s-a pus.
Decurg două lucruri.
Un furnizor care are două incidente de securitate distincte în patru zile e în sine un semnal, indiferent dacă împart o cauză comună. E rezonabil ca un client să întrebe ce s-a schimbat între timp.
Iar Trezor e acum a doua apariție în newsroom-ul nostru a unei companii atinse printr-un terț într-o singură lună — întâi prin platforma de raportare expusă a unui furnizor de logistică, acum prin furnizorul de e-mail marketing. Sistemele proprii nu au fost compromise în niciunul dintre cazuri. Asta e forma riscului: poziția ta de securitate e parțial o funcție de decizii luate în companii cu care ai contract și în care n-ai nicio vizibilitate.
Ce reții
- Chei API de lungă durată, cu permisiuni complete, scrise în codul sursă. E al treilea articol din luna asta în care asta a fost cauza. Limitează drepturile cheilor, pune-le termen de expirare și scanează repository-urile și pipeline-urile după ele.
- Știi ce JavaScript terț încarcă site-ul tău. Widgeturi de marketing, unelte de chat, analytics, bannere de consimțământ. Fiecare rulează cu privilegiile site-ului tău, în browserele vizitatorilor tăi, sub reputația domeniului tău.
- Decide deliberat în privința Subresource Integrity. Pentru scripturile care se schimbă rar, folosește-l. Pentru celelalte, consemnează că ai acceptat riscul și de ce.
- Monitorizarea integrității originii nu e monitorizarea integrității site-ului. Dacă ai un CDN sau o platformă de edge, configurația acelei platforme face parte din suprafața ta de atac, iar modificările ei ar trebui să genereze alerte.
- Întreabă-ți furnizorii cum sunt limitate credențialele lor de CDN și DNS. E o întrebare incomodă și e exact cea care contează aici.
4Tify analizează expunerea prin scripturi terțe și configurația de edge — părțile unui site care nu stau pe server. Dacă vrei o evaluare, scrie-ne.
