{"id":258,"date":"2026-08-09T10:45:27","date_gmt":"2026-08-09T08:45:27","guid":{"rendered":"https:\/\/helloblog.io\/ro\/atac-supply-chain-bdthemes-api-json-xss\/"},"modified":"2026-08-09T10:45:27","modified_gmt":"2026-08-09T08:45:27","slug":"atac-supply-chain-bdthemes-api-json-xss","status":"publish","type":"post","link":"https:\/\/helloblog.io\/ro\/atac-supply-chain-bdthemes-api-json-xss\/","title":{"rendered":"Atac supply chain \u00een pluginurile BdThemes: XSS prin API JSON compromis"},"content":{"rendered":"\n<p>O compromitere a lan\u021bului de aprovizionare a afectat ecosistemul BdThemes f\u0103r\u0103 ca atacatorii s\u0103 modifice fi\u0219ierele din repository-ul WordPress.org. Ei au alterat r\u0103spunsuri JSON servite de API-ul furnizorului, iar codul vulnerabil din pluginuri a executat JavaScript \u00een browserul fiec\u0103rui administrator autentificat care deschidea orice pagin\u0103 din <code>wp-admin<\/code>.<\/p>\n\n\n\n<p>Pluginurile afectate au fost \u00eenchise temporar \u00een directorul WordPress \u00een timpul inspec\u021biei. Dac\u0103 administrezi un site care le-a folosit, trateaz\u0103 incidentul ca pe o posibil\u0103 compromitere complet\u0103: simpla actualizare sau verificare a integrit\u0103\u021bii fi\u0219ierelor nu este suficient\u0103, deoarece atacul nu trebuia s\u0103 schimbe fi\u0219ierele pluginului pe disc.<\/p>\n\n\n\n<div class=\"wp-block-group callout callout-danger is-style-danger is-layout-flow wp-block-group-is-layout-flow\" style=\"border-width:1px;border-radius:8px;padding-top:1rem;padding-right:1.5rem;padding-bottom:1rem;padding-left:1.5rem\">\n\n<h4 class=\"wp-block-heading callout-title\">Ac\u021biune imediat\u0103<\/h4>\n\n\n<p>Atacul putea crea conturi de administrator neautorizate, instala un plugin cu webshell \u0219i ad\u0103uga backdoor-uri persistente \u00een directorul de Must-Use plugins. Verific\u0103 imediat utilizatorii, pluginurile, directorul <code>mu-plugins<\/code> \u0219i op\u021biunile din baza de date.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Pluginurile afectate \u0219i severitatea problemei<\/h2>\n\n\n\n<p>Problema afecteaz\u0103 biblioteca intern\u0103 Biggopti \u00een mai multe versiuni \u0219i are scorul CVSS 5.4, de severitate medie, f\u0103r\u0103 patch disponibil la momentul raport\u0103rii. \u00cen practic\u0103, impactul este mult mai grav atunci c\u00e2nd cineva controleaz\u0103 fluxul JSON de la distan\u021b\u0103: XSS-ul ruleaz\u0103 \u00een contextul unui administrator WordPress autentificat \u0219i poate prelua site-ul.<\/p>\n\n\n\n<p>Biggopti exist\u0103 \u00een urm\u0103toarele pluginuri BdThemes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Element Pack Addons for Elementor (<code>bdthemes-element-pack-lite<\/code>)<\/li>\n\n\n<li>Prime Slider Addons for Elementor (<code>bdthemes-prime-slider-lite<\/code>)<\/li>\n\n\n<li>Pixel Gallery Addons for Elementor (<code>pixel-gallery<\/code>)<\/li>\n\n\n<li>Ultimate Post Kit Addons for Elementor (<code>ultimate-post-kit<\/code>)<\/li>\n\n\n<li>Ultimate Store Kit \u2013 Addon For WooCommerce, EDD and Elementor (<code>ultimate-store-kit<\/code>)<\/li>\n\n\n<li>Live Copy Paste for Elementor (<code>live-copy-paste<\/code>)<\/li>\n\n\n<li>Smart Admin Assistant (<code>smart-admin-assistant<\/code>)<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cum a func\u021bionat compromiterea prin API<\/h2>\n\n\n\n<p>Biggopti \u00eencarc\u0103 bannere promo\u021bionale \u00een panoul WordPress. Componenta cite\u0219te datele dintr-un API care este sus\u021binut de un bucket static DigitalOcean Spaces, protejat de Cloudflare, nu de un server de aplica\u021bie dinamic. Atacatorii au ob\u021binut acces de scriere la acel bucket \u0219i au \u00eenlocuit r\u0103spunsurile JSON legitime cu r\u0103spunsuri mali\u021bioase.<\/p>\n\n\n\n<p>Fiecare plugin care folose\u0219te Biggopti adaug\u0103 un asset JavaScript client-side pe hook-ul <code>admin_init<\/code>. Scriptul ruleaz\u0103 astfel necondi\u021bionat la fiecare \u00eenc\u0103rcare a unei pagini din <code>wp-admin<\/code>, cere datele bannerului \u0219i construie\u0219te elemente HTML \u00een DOM (Document Object Model, structura de obiecte a paginii).<\/p>\n\n\n\n<p>Vulnerabilitatea XSS (Cross-Site Scripting) apare deoarece codul preia <code>display_id<\/code> din JSON \u0219i \u00eel concateneaz\u0103 direct \u00een atributul HTML <code>id<\/code>, f\u0103r\u0103 escaping pe partea de client:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#e1e4e8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ `display_id` vine din r\u0103spunsul JSON de la API\nvar displayId = banner.display_id || banner.id || &quot;default&quot;;\nvar elementId = &quot;bdt-admin-biggopti-api-biggopti-&quot; + displayId;\nvar attributes = 'id=&quot;' + elementId + '&quot;'; \/\/ valoare neescapat\u0103\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6A737D\">\/\/ `display_id` vine din r\u0103spunsul JSON de la API<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">var<\/span><span style=\"color:#E1E4E8\"> displayId <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> banner.display_id <\/span><span style=\"color:#F97583\">||<\/span><span style=\"color:#E1E4E8\"> banner.id <\/span><span style=\"color:#F97583\">||<\/span><span style=\"color:#9ECBFF\"> \"default\"<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">var<\/span><span style=\"color:#E1E4E8\"> elementId <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#9ECBFF\"> \"bdt-admin-biggopti-api-biggopti-\"<\/span><span style=\"color:#F97583\"> +<\/span><span style=\"color:#E1E4E8\"> displayId;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">var<\/span><span style=\"color:#E1E4E8\"> attributes <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#9ECBFF\"> 'id=\"'<\/span><span style=\"color:#F97583\"> +<\/span><span style=\"color:#E1E4E8\"> elementId <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#9ECBFF\"> '\"'<\/span><span style=\"color:#E1E4E8\">; <\/span><span style=\"color:#6A737D\">\/\/ valoare neescapat\u0103<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>\u00cen aceea\u0219i zon\u0103 de cod, atributul <code>data-display-id<\/code> prime\u0219te escaping corect pentru <code>&amp;<\/code>, <code>&lt;<\/code>, <code>&gt;<\/code> \u0219i ghilimele duble. Diferen\u021ba arat\u0103 c\u0103 atributul <code>id<\/code> a r\u0103mas neprotejat, chiar dac\u0103 versiunile ulterioare au introdus un sanitizer bazat pe <code>DOMParser<\/code> pentru c\u00e2mpul de con\u021binut al bannerului. Acest sanitizer elimina tagurile HTML periculoase \u0219i handler-ele inline, dar nu rezolva injectarea \u00een atributul <code>id<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#e1e4e8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>function escapeAttribute(value) {\n  return (value || &quot;&quot;)\n    .replace(\/&amp;\/g, &quot;&amp;amp;&quot;)\n    .replace(\/&lt;\/g, &quot;&amp;lt;&quot;)\n    .replace(\/&gt;\/g, &quot;&amp;gt;&quot;)\n    .replace(\/&quot;\/g, &quot;&amp;quot;&quot;);\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">function<\/span><span style=\"color:#B392F0\"> escapeAttribute<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#FFAB70\">value<\/span><span style=\"color:#E1E4E8\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">  return<\/span><span style=\"color:#E1E4E8\"> (value <\/span><span style=\"color:#F97583\">||<\/span><span style=\"color:#9ECBFF\"> \"\"<\/span><span style=\"color:#E1E4E8\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    .<\/span><span style=\"color:#B392F0\">replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#DBEDFF\">&#x26;<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#F97583\">g<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">\"&#x26;amp;\"<\/span><span style=\"color:#E1E4E8\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    .<\/span><span style=\"color:#B392F0\">replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#DBEDFF\">&#x3C;<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#F97583\">g<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">\"&#x26;lt;\"<\/span><span style=\"color:#E1E4E8\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    .<\/span><span style=\"color:#B392F0\">replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#DBEDFF\">><\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#F97583\">g<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">\"&#x26;gt;\"<\/span><span style=\"color:#E1E4E8\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    .<\/span><span style=\"color:#B392F0\">replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#DBEDFF\">\"<\/span><span style=\"color:#9ECBFF\">\/<\/span><span style=\"color:#F97583\">g<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">\"&#x26;quot;\"<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Un <code>display_id<\/code> construit special \u00eenchidea atributul <code>id<\/code>, introducea un handler <code>onanimationstart<\/code> \u0219i pornea o anima\u021bie CSS dup\u0103 aproximativ 10 milisecunde. Rezultatul: browserul administratorului executa silen\u021bios codul injectat la \u00eenc\u0103rcarea oric\u0103rei pagini din dashboard. Nu era necesar\u0103 o actualizare a pluginului, iar fi\u0219ierele locale ale pluginului nu se modificau; de aceea scanerele care verific\u0103 numai integritatea fi\u0219ierelor \u0219i WAF-urile observau greu compromiterea.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Evolu\u021bia atacului dup\u0103 executarea XSS<\/h2>\n\n\n\n<p>Handler-ul injectat \u00eenc\u0103rca scripturi externe \u00een etape, \u00een func\u021bie de disponibilitatea infrastructurii atacatorilor. Campania a folosit dou\u0103 payload-uri principale, asociate cu endpoint-uri API diferite.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Payload-ul principal: <code>w2.js<\/code><\/h3>\n\n\n\n<p>Scriptul principal era livrat pluginurilor care apelau endpoint-ul <code>api-data-all-records<\/code>. Rulat \u00een sesiunea unui administrator, parcurgea urm\u0103torii pa\u0219i:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Contacta serverul C2 la <code>ia-cdn[.]com\/fz\/c<\/code> \u0219i trimitea originea site-ului pentru a primi instruc\u021biuni de \u021bintire. Oprea execu\u021bia dac\u0103 serverul r\u0103spundea cu starea <code>skip<\/code> sau <code>done<\/code>.<\/li>\n\n\n<li>Folosea valoarea <code>X-WP-Nonce<\/code> disponibil\u0103 \u00een sesiunea activ\u0103 pentru a crea un administrator prin WordPress REST API. Dac\u0103 metoda e\u0219ua, \u00eencerca formularele standard WordPress.<\/li>\n\n\n<li>Desc\u0103rca de la C2 o arhiv\u0103 ZIP care pretindea c\u0103 este plugin. O instala prin formularul standard de \u00eenc\u0103rcare a pluginurilor. Pluginul fals folosea slug-uri aparent neutre, precum <code>wp-smart-thumbnails<\/code>, \u0219i includea webshell-ul <code>emer-run.php<\/code>, apelat direct prin URL.<\/li>\n\n\n<li>Apela <code>emer-run.php<\/code>, care instala dou\u0103 module persistente \u00een directorul Must-Use plugins. Mostrele analizate aveau timestamp-uri schimbate \u00een septembrie 2025 pentru a se amesteca printre fi\u0219ierele legitime; numele fi\u0219ierelor puteau varia \u00eentre infec\u021bii.<\/li>\n\n\n<li>Primul modul MU era un backdoor de autentificare magic\u0103: permitea intrarea administrativ\u0103 neautentificat\u0103 cu parametrul URL <code>?_wplogin=&lt;token&gt;<\/code> \u0219i viza administratorul \u00eenregistrat cel mai devreme pe site.<\/li>\n\n\n<li>Al doilea modul MU ascundea urmele analizei: se lega de interog\u0103rile WordPress c\u0103tre baza de date, ascundea conturile neautorizate din lista de utilizatori din administrare \u0219i mic\u0219ora corespunz\u0103tor totalul de utilizatori.<\/li>\n\n\n<li>Trimitea rezultatele fiec\u0103rei etape c\u0103tre C2 prin <code>navigator.sendBeacon<\/code>.<\/li>\n\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Payload-ul alternativ: <code>x.js<\/code><\/h3>\n\n\n\n<p>Scriptul alternativ era g\u0103zduit direct \u00een infrastructura BdThemes \u0219i era servit victimelor ale c\u0103ror pluginuri apelau <code>api-data-records<\/code>. El calcula creden\u021biale deterministe pornind de la hostname-ul site-ului: genera un hash base36 de \u0219ase caractere, un nume de utilizator cu prefixul <code>bd_<\/code> \u0219i o parol\u0103 \u00een forma <code>Bd@26!&lt;hash&gt;x<\/code>. Contul primea o adres\u0103 de e-mail <code>@wordpress.org<\/code>.<\/p>\n\n\n\n<p>Caracterul determinist elimina nevoia atacatorilor de a p\u0103stra central o list\u0103 cu site-urile compromise. Un responder la incidente putea calcula, pentru un domeniu suspect, numele de utilizator \u0219i parola pe care scriptul \u00eencerca s\u0103 le creeze.<\/p>\n\n\n\n<p>Apoi <code>x.js<\/code> \u00eenc\u0103rca pagina <code>\/wp-admin\/user-new.php<\/code>, extr\u0103gea nonce-ul formularului \u0219i trimitea formularul de creare a unui utilizator cu rolul <code>administrator<\/code>. Raporta c\u0103tre C2 starea opera\u021biei, creden\u021bialele, originea site-ului, URL-ul paginii \u0219i linkul de logout, prin <code>sendBeacon<\/code>; c\u00e2nd API-ul nu era disponibil, folosea <code>fetch<\/code> cu <code>keepalive<\/code>. Dac\u0103 putea accesa <code>localStorage<\/code>, marca browserul ca procesat pentru a evita repetarea opera\u021biei.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Indicatori de compromitere<\/h2>\n\n\n\n<p>Caut\u0103 indicatorii de mai jos \u00een loguri, \u00een fi\u0219iere \u0219i \u00een baza de date. Endpoint-urile API BdThemes listate au revenit ulterior la JSON curat, dar acces\u0103rile istorice \u0219i artefactele l\u0103sate pe site r\u0103m\u00e2n relevante pentru investiga\u021bie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Domenii \u0219i endpoint-uri externe<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Payload principal: <code>ia-cdn[.]com\/fz\/w2.js<\/code><\/li>\n\n\n<li>Endpoint C2 pentru beacon: <code>ia-cdn[.]com\/fz\/c<\/code><\/li>\n\n\n<li>Endpoint API compromis: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/api-data-all-records<\/code><\/li>\n\n\n<li>Endpoint API compromis: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/api-data-records<\/code><\/li>\n\n\n<li>Payload alternativ g\u0103zduit \u00een infrastructura furnizorului: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/x.js<\/code><\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Fi\u0219iere, module MU \u0219i op\u021biuni WordPress<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Webshell: <code>emer-run.php<\/code>, MD5 <code>1024732009983dd5e54b4cf5593f04d4<\/code>.<\/li>\n\n\n<li>Backdoor MU pentru magic login: <code>class-wp-token-validate.php<\/code>, MD5 <code>7719cd98a35ffad2771f26d1ceab7d27<\/code>.<\/li>\n\n\n<li>Modul MU de ascundere: <code>class-wp-query-9d127ff3.php<\/code> sau un nume asem\u0103n\u0103tor cu modelul <code>class-wp-query-*.php<\/code>, MD5 <code>9aadc3e5c5242b273bd17c5bdc358845<\/code>.<\/li>\n\n\n<li>Modul MU denumit aparent \u201eHealth Check\u201d: <code>wp-cache-optimizer.php<\/code>, MD5 <code>e450ae5bc4bfc0d960dded06a76bb8e9<\/code>.<\/li>\n\n\n<li>Op\u021biunea <code>fz_emer_login_tokens<\/code>, care stocheaz\u0103 tokenuri pentru magic login.<\/li>\n\n\n<li>Op\u021biunea <code>fz_emer_done_v1<\/code>, care marcheaz\u0103 compromiterea ca finalizat\u0103.<\/li>\n\n\n<li>Conturi cu domeniile de e-mail <code>@wordpress.org<\/code> sau <code>@developer.wordpress.org<\/code>.<\/li>\n\n\n<li>Nume de utilizator care respect\u0103 modelul <code>bd_<\/code> urmat de \u0219ase caractere alfanumerice.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cronologia incidentului<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>1 martie 2026:<\/strong> Biggopti API JS intr\u0103 \u00een Prime Slider 4.1.9, \u00een SVN <code>r3471891<\/code>. C\u00e2mpul <code>display_id<\/code> ajunge neescapat \u00een atributul <code>id<\/code>; pluginul folose\u0219te endpoint-ul <code>api-data-records<\/code>.<\/li>\n\n\n<li><strong>10 mai 2026:<\/strong> endpoint-ul se schimb\u0103 \u00een <code>api-data-all-records<\/code>. Apare sanitizerul <code>DOMParser<\/code> pentru c\u00e2mpul de con\u021binut, dar atributul <code>id<\/code> r\u0103m\u00e2ne neescapat.<\/li>\n\n\n<li><strong>23 iunie 2026:<\/strong> c\u00e2mpul <code>start_date<\/code> din campania API compromis\u0103, asociat notific\u0103rii \u201eSummer Sale\u201d, indic\u0103 cea mai timpurie dat\u0103 posibil\u0103 la care XSS-ul putea fi activ.<\/li>\n\n\n<li><strong>6 august 2026, 22:40 UTC:<\/strong> ultima modificare observat\u0103 pentru <code>api-data-records<\/code> compromis.<\/li>\n\n\n<li><strong>7 august 2026, 09:11 UTC:<\/strong> ultima modificare observat\u0103 pentru <code>api-data-all-records<\/code> compromis.<\/li>\n\n\n<li><strong>7 august 2026:<\/strong> atacul este observat \u00een practic\u0103, iar pluginurile sunt \u00eenchise \u00een directorul WordPress \u00een a\u0219teptarea verific\u0103rii.<\/li>\n\n\n<li><strong>7 august 2026, 16:56 UTC:<\/strong> sunt capturate artefacte pentru investiga\u021bie.<\/li>\n\n\n<li><strong>8 august 2026:<\/strong> ambele endpoint-uri API livreaz\u0103 din nou JSON curat.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Ce verifici acum pe site<\/h2>\n\n\n\n<p>\u00cencepe cu toate site-urile care au avut instalat unul dintre cele \u0219apte pluginuri, inclusiv site-urile pe care pluginul nu mai este activ ast\u0103zi. Inspecteaz\u0103 lista de utilizatori direct \u00een WordPress \u0219i \u00een baza de date, deoarece modulul de stealth putea ascunde conturile din interfa\u021ba de administrare.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Caut\u0103 utilizatori administratori necunoscu\u021bi, mai ales conturi <code>bd_<\/code> urmate de \u0219ase caractere \u0219i adrese cu <code>@wordpress.org<\/code> sau <code>@developer.wordpress.org<\/code>.<\/li>\n\n\n<li>Verific\u0103 directorul pluginurilor pentru <code>emer-run.php<\/code>, pluginuri \u00eenc\u0103rcate recent \u0219i arhive ori directoare cu nume care imit\u0103 pluginuri legitime, inclusiv <code>wp-smart-thumbnails<\/code>.<\/li>\n\n\n<li>Inspecteaz\u0103 <code>wp-content\/mu-plugins<\/code> pentru fi\u0219ierele \u0219i modelele de nume din lista de indicatori, inclusiv module cu timestamp-uri suspect de vechi.<\/li>\n\n\n<li>Caut\u0103 op\u021biunile <code>fz_emer_login_tokens<\/code> \u0219i <code>fz_emer_done_v1<\/code> \u00een tabela de op\u021biuni WordPress.<\/li>\n\n\n<li>Verific\u0103 logurile pentru cereri c\u0103tre domeniile \u0219i endpoint-urile IoC \u0219i compar\u0103 fi\u0219ierele g\u0103site cu hash-urile MD5 furnizate.<\/li>\n\n\n<li>Presupune c\u0103 un site pe care g\u0103se\u0219ti indicatori a permis execu\u021bie de cod la distan\u021b\u0103. Elimin\u0103 persisten\u021ba, conturile neautorizate \u0219i webshell-urile, apoi investigheaz\u0103 \u00een profunzime ce alte modific\u0103ri au ap\u0103rut.<\/li>\n\n<\/ol>\n\n\n\n<p>Regulile WAF \u0219i semn\u0103turile pentru aceast\u0103 compromitere au fost puse la dispozi\u021bia utilizatorilor Wordfence Premium, Care \u0219i Response, precum \u0219i clien\u021bilor pl\u0103ti\u021bi Wordfence CLI, la 7 august 2026. Utilizatorii versiunilor gratuite Wordfence \u0219i Wordfence CLI le primesc dup\u0103 \u00eent\u00e2rzierea standard de 30 de zile.<\/p>\n\n\n\n<p>Incidentul arat\u0103 un risc pe care verificarea strict\u0103 a fi\u0219ierelor nu \u00eel acoper\u0103: date considerate de \u00eencredere, \u00eenc\u0103rcate de la distan\u021b\u0103 \u00een interfa\u021ba de administrare, sunt parte din suprafa\u021ba de atac. Pentru componentele proprii, trateaz\u0103 orice c\u00e2mp primit prin API ca date ne\u00eencredere, escapeaz\u0103-l pentru contextul exact \u00een care \u00eel inserezi \u0219i limiteaz\u0103 \u00eenc\u0103rcarea scripturilor administrative la ecranele unde ai nevoie de ele.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Referin\u021be \/ Surse<\/h2>\n                <ul class=\"references-list\"><li><a href=\"https:\/\/www.wordfence.com\/blog\/2026\/08\/psa-supply-chain-compromise-in-bdthemes-ecosystem-via-poisoned-api-response\/\" target=\"_blank\" rel=\"noopener noreferrer\">PSA: Supply Chain Compromise in BdThemes Ecosystem via Poisoned API Response<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/blog\/2026\/07\/wordfence-prism-detected-backdoored-wordpress-plugin-within-two-hours-of-it-being-introduced\/\" target=\"_blank\" rel=\"noopener noreferrer\">Advanced Responsive Video Embedder supply chain attack<\/a><\/li><li><a href=\"https:\/\/optinmonster.com\/security-incident-tampered-script-served-via-optinmonster-and-trustpulse\/#what-to-check-and-do\" target=\"_blank\" rel=\"noopener noreferrer\">Security Incident: Tampered Script Served via OptinMonster and TrustPulse<\/a><\/li><\/ul>\n            <\/div>","protected":false},"excerpt":{"rendered":"<p>Un flux JSON compromis a transformat bannerele administrative ale unor pluginuri BdThemes \u00eentr-un vector de preluare complet\u0103 a site-ului. Afl\u0103 ce pluginuri sunt afectate \u0219i ce urme trebuie s\u0103 cau\u021bi.<\/p>\n","protected":false},"author":30,"featured_media":257,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[138,11,125,10,129],"class_list":["post-258","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-securitate","tag-pluginuri-wordpress","tag-securitate","tag-supply-chain","tag-wordpress","tag-xss"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/posts\/258","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/users\/30"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/comments?post=258"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/posts\/258\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/media\/257"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/media?parent=258"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/categories?post=258"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/ro\/wp-json\/wp\/v2\/tags?post=258"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}