BdThemes įskiepių tiekimo grandinės ataka per užnuodytą API: ką patikrinti WordPress svetainėje
BdThemes įskiepių ekosistemą paveikė tiekimo grandinės kompromitavimas, kuriam užpuolikams nereikėjo pakeisti nė vieno failo oficialioje WordPress.org saugykloje. Jie pakeitė nuotolinio API grąžinamus JSON įrašus ir per administratoriaus naršyklę įvykdė XSS kodą, todėl svetainė galėjo būti perimta vien atidarius bet kurį wp-admin puslapį.
Paveikti įskiepiai laikinai uždaryti WordPress įskiepių kataloge, kol WordPress Plugins komanda atlieka patikrą ir tęsiamas tyrimas. Jei naudojate bent vieną iš jų, nelaukite įskiepio atnaujinimo: patikrinkite savo naudotojus, įskiepių katalogus ir duomenų bazę pagal šiame straipsnyje pateiktus kompromitavimo požymius.
Kodėl šis incidentas išskirtinis
Užkrėsti galima ir be įskiepio atnaujinimo. Ataka vyko per nuotolinį reklaminį JSON srautą, todėl įprastas failų integralumo tikrinimas pakeistų įskiepio failų neras, o WAF ją gali pastebėti sunkiai.
Kaip veikė kompromitavimas
BdThemes įskiepiuose yra vidinis komponentas Biggopti. Jis į WordPress administravimo skydelį įkelia reklaminius pranešimus: JavaScript pasiima duomenis iš tiekėjo API, o paskui naršyklėje suformuoja HTML. API duomenis aptarnavo ne dinaminis programų serveris, bet statiniai JSON failai DigitalOcean Spaces objektų saugykloje, kurią saugojo Cloudflare.
Problema kilo dėl nepakankamo display_id reikšmės išvalymo prieš įterpiant ją į HTML id atributą. Užpuolikai įgijo rašymo prieigą prie saugyklos, pakeitė teisėtus JSON atsakymus specialiai suformuotais įrašais ir taip išnaudojo jau įskiepiuose buvusį XSS pažeidžiamumą.
Kiekvienas Biggopti naudojantis įskiepis per admin_init prijungia kliento JavaScript. Vadinasi, kodas vykdomas besąlygiškai kiekvieną kartą, kai prisijungęs administratorius atidaro bet kurį wp-admin puslapį. Pažeidžiama logika iš nuotolinio įrašo ima display_id arba id ir tiesiogiai sudeda reikšmę į atributo eilutę.
// Nuotolinė reikšmė nebuvo išvaloma prieš patekdama į HTML atributą.
var displayId = item.display_id || item.id || "default";
var elementId = "bdt-admin-biggopti-api-biggopti-" + displayId;
html = 'id="' + elementId + '"';Tame pačiame kode data-display-id atributui buvo naudojamas simbolių išvalymas: &, <, >, ir kabutės pakeičiami HTML esybėmis. Nors ši dalis dėl minifikavimo arba bundling atrodo painiai, ji parodo, kad būtent id atributo vieta liko neapsaugota.
function escapeAttribute(value) {
return (value || "")
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """);
}Neišvalytą atributo įterpimą Prime Slider įskiepyje įdiegė 2026 m. kovo 1 d. versija 4.1.9, SVN pakeitime r3471891, o vėliau tokia logika pateko ir į kitus įskiepius. Vėlesnėse laidose turinio laukui pridėtas DOMParser valiklis, kuris šalina pavojingas HTML žymas bei inline handlerius, tačiau id atributas ir toliau nebuvo išvalomas.
Kenkėjiškas display_id ištrūkdavo iš id atributo ir pridėdavo onanimationstart įvykio handlerį. CSS animacija jį suaktyvindavo maždaug per 10 milisekundžių, todėl kodas tyliai pasileisdavo administratoriui įkėlus administravimo puslapį. Tuo metu užkrėstame API atsakyme dar buvo „Summer Sale“ pranešimo įrašas su tokiu payload.
Pažeidžiamumas įvertintas 5.4 CVSS (vidutinis) balais ir neturėjo pataisos. Išsamus pažeidžiamumo įrašas: Biggopti Library – Cross-Site Scripting via display_id from Sigmative API.
Du kenkėjiškų payload etapų keliai
XSS įvykio handleris įkeldavo išorinį scenarijų pagal užpuolikų infrastruktūros pasiekiamumą. Pagrindinis kelias naudojo api-data-all-records endpoint, o alternatyvus – api-data-records endpoint.
Pagrindinis payload: w2.js
w2.js, vykdomas aktyvioje administratoriaus sesijoje, veikė tokia seka:
- Patikrindavo C2 serverį. Į
ia-cdn[.]com/fz/cišsiųsdavo svetainės origin ir gaudavo taikymo instrukcijas. Jei C2 atsakydavoskiparbadone, scenarijus nutraukdavo darbą. - Sukurdavo neteisėtą administratoriaus paskyrą. Scenarijus panaudodavo aktyvioje sesijoje esantį
X-WP-Nonceir WordPress REST API. Jei tai nepavykdavo, naudodavo įprastą formos pateikimą. - Įdiegdavo webshell. Iš C2 serverio parsisiųsdavo netikrą įskiepio ZIP ir įkeldavo jį per standartinę įskiepių įkėlimo formą. Įskiepis maskuodavosi
wp-smart-thumbnailsarba panašiu neutraliu slug, o jame esantisemer-run.phpwebshell būdavo kviečiamas tiesiogiai URL adresu. - Įrašydavo Must-Use (MU) įskiepių užpakalines duris. Paleidus
emer-run.php, į MU įskiepių katalogą patekdavo du išlikimą užtikrinantys moduliai. Abu ištirti pavyzdžiai buvo dirbtinai datuoti 2025 m. rugsėju, kad susilietų su teisėtais failų laiko žymenimis; failų vardai skirtinguose užkrėtimuose gali skirtis. Pirmasis modulis leido neprisijungus patekti administratoriaus teisėmis per URL parametrą?_wplogin=<token>ir taikėsi į seniausiai svetainėje registruotą administratorių. Antrasis modulis slėpdavo neteisėtas paskyras: jis hook perimdavo WordPress duomenų bazės užklausas, pašalindavo sukurtas paskyras iš administravimo naudotojų sąrašo ir atitinkamai mažindavo bendrą naudotojų skaičių. - Išsiųsdavo rezultatus. Kiekvieno vykdymo etapo duomenis persiųsdavo C2 serveriui per
navigator.sendBeacon.
Alternatyvus payload: x.js
Antrinis scenarijus x.js buvo laikomas tiesiogiai BdThemes infrastruktūroje ir pasiekdavo aukas per api-data-records. Jis iš svetainės hostname matematiškai apskaičiuodavo deterministinius administratoriaus prisijungimo duomenis: naudotojo vardą bd_ su šešių simbolių base36 hash, slaptažodį Bd@26! su tuo pačiu hash ir galine x, taip pat el. pašto adresą su @wordpress.org domenu.
Kadangi duomenys priklauso tik nuo hostname, užpuolikams nereikia centralizuotai saugoti užkrėstų svetainių sąrašo. Incidentą tiriantys specialistai gali iš įtariamos svetainės domeno apskaičiuoti tikslų naudotojo vardą ir slaptažodį, kurio turi ieškoti.
Scenarijus atidarydavo /wp-admin/user-new.php, iš puslapio ištraukdavo nonce ir atsijungimo URL, o paskui per formos POST sukurdavo administratorių. Į C2 jis persiųsdavo kūrimo būseną, prisijungimo duomenis, svetainės origin, atsijungimo URL ir puslapio URL; tam pirmiausia bandydavo navigator.sendBeacon, o nepavykus – fetch užklausą be CORS atsakymo skaitymo. Naršyklės localStorage, jei jis buvo prieinamas, įrašydavo vykdymo vėliavą, kad scenarijus nebekartotų operacijos.
Ką apima incidentas
C2 domenas siejamas su tais pačiais veikėjais, kurie per pastaruosius du mėnesius įvykdė Advanced Responsive Video Embedder ir OptinMonster tiekimo grandinės atakas.
Kampanija siekė plačiai ir nepastebimai įsitvirtinti administratoriaus teisėmis bei įgyti nuotolinio kodo vykdymo galimybę WordPress aplinkose. Užpuolikams nereikėjo nei prieigos prie konkrečių svetainių, nei pakeisti įskiepių šaltinio: pakako užnuodyti patikimu laikytą reklaminį srautą. Kenkėjiški JSON įrašai ir x.js atsirado pačio tiekėjo saugykloje, todėl tai rodo rimtą BdThemes debesijos prieigos duomenų arba vidinės infrastruktūros kompromitavimą.
Paveikti įskiepiai
- Element Pack Addons for Elementor –
bdthemes-element-pack-lite - Prime Slider Addons for Elementor –
bdthemes-prime-slider-lite - Pixel Gallery Addons for Elementor –
pixel-gallery - Ultimate Post Kit Addons for Elementor –
ultimate-post-kit - Ultimate Store Kit – Addon For WooCommerce, EDD and Elementor –
ultimate-store-kit - Live Copy Paste for Elementor –
live-copy-paste - Smart Admin Assistant –
smart-admin-assistant
Kompromitavimo požymiai ir patikra
Pradėkite nuo naudotojų sąrašo, nes užpakalinės durys gali slėpti sukurtas paskyras administravimo sąsajoje. Ieškokite administratorių, kurių el. pašto domenas yra @wordpress.org arba @developer.wordpress.org, ir naudotojų vardų, atitinkančių bd_ bei šešių raidinių skaitmeninių simbolių šabloną.
Tada patikrinkite įskiepių ir ypač MU įskiepių katalogą. Svarbūs failai bei jų MD5 reikšmės:
- Webshell:
emer-run.php– MD51024732009983dd5e54b4cf5593f04d4. - Magic-login MU užpakalinės durys:
class-wp-token-validate.php– MD57719cd98a35ffad2771f26d1ceab7d27. - Slaptumo MU modulis:
class-wp-query-9d127ff3.phparba panašusclass-wp-query-*.phppavadinimas – MD59aadc3e5c5242b273bd17c5bdc358845. - MU „Health Check“ modulis:
wp-cache-optimizer.php– MD5e450ae5bc4bfc0d960dded06a76bb8e9.
Duomenų bazėje ieškokite parinkčių fz_emer_login_tokens, kur saugomi magic-login tokenai, ir fz_emer_done_v1, kuri žymi baigtą kompromitavimą. Taip pat peržiūrėkite žurnalus ir tinklo srautą dėl toliau nurodytų išorinių resursų.
- Pagrindinis payload:
ia-cdn[.]com/fz/w2.js. - C2 beacon endpoint:
ia-cdn[.]com/fz/c. - Anksčiau užnuodyti, dabar išvalyti tiekėjo endpoint:
api[.]sigmative[.]io/prod/store/api/biggopti/api-data-all-records,api[.]sigmative[.]io/prod/store/api/biggopti/api-data-recordsirapi[.]sigmative[.]io/prod/store/api/biggopti/x.js.
Tikrinkite kelis sluoksnius
Neribokite patikros vien įskiepių failų palyginimu su oficialia versija. Ši ataka galėjo palikti nepakitusius BdThemes įskiepio failus, bet įrašyti administratoriaus paskyras, atskirą netikrą įskiepį, MU modulius ir duomenų bazės parinktis.
Įvykių eiga
- 2026-03-01: Prime Slider 4.1.9 įdiegė Biggopti API JavaScript (
r3471891).display_idpateko įidatributą neišvalytas; naudotasapi-data-recordsendpoint. - 2026-05-10: Endpoint pakeistas į
api-data-all-records. Turinio laukui pridėtasDOMParservaliklis, betidatributas liko pažeidžiamas. - 2026-06-23: Užnuodytame API sraute nurodyta kampanijos
start_datesu „Summer Sale“ pranešimu. Tai ankstyviausia galima XSS aktyvumo data. - 2026-08-06 22:40 UTC: Užnuodyto
api-data-recordspaskutinis pakeitimo laikas. - 2026-08-07 09:11 UTC: Užnuodyto
api-data-all-recordspaskutinis pakeitimo laikas. - 2026-08-07: Užfiksuota ataka realiose svetainėse, o paveikti įskiepiai uždaryti WordPress kataloge, kol vyksta peržiūra.
- 2026-08-07 16:56 UTC: Užfiksuoti tyrimo artefaktai.
- 2026-08-08: Abu API endpoint jau grąžino švarų JSON.
Ką daryti dabar
Jei naudojate paveiktą BdThemes įskiepį, nedelsdami atlikite kompromitavimo požymių auditą: peržiūrėkite naudotojų lentelę ir administratorių paskyras, paieškokite netikro įskiepio bei MU modulių, patikrinkite wp_options parinktis ir išanalizuokite ryšius su nurodytais domenais. Aptikę požymių, laikykite svetainę visiškai kompromituota: pašalinkite kenkėjiškus komponentus, panaikinkite neteisėtas paskyras ir atkurkite patikimą administravimo prieigą.
Wordfence Premium, Care, Response ir mokamos Wordfence CLI versijos gavo šio kompromitavimo aptikimo parašus bei WAF taisykles 2026 m. rugpjūčio 7 d. Nemokami Wordfence ir Wordfence CLI naudotojai šiuos parašus bei taisykles gaus po įprasto 30 dienų atidėjimo.
Nuorodos / Šaltiniai
Hannah Turing
WordPress kūrėja ir techninė rašytoja HelloWP. Padedu kūrėjams kurti geresnes svetaines naudojant šiuolaikinius įrankius, tokius kaip Laravel, Tailwind CSS ir WordPress ekosistema. Aistringai vertinu švarų kodą ir kūrėjo patirtį.
Visi įrašai