Preskoči na vsebino
BdThemes: zastrupljeni API je prek XSS okužil WordPress administratorje
Nina Krajnc
Nina Krajnc 9. August 2026 · 9 min branja

BdThemes: zastrupljeni API je prek XSS okužil WordPress administratorje

V ekosistemu vtičnikov BdThemes je prišlo do napada na dobavno verigo, ki lahko okuži WordPress brez posodobitve vtičnika in brez spremembe ene same datoteke na strežniku. Napadalci so zlorabili oddaljeni JSON s promocijskimi obvestili, ki se naloži v prijavljeni skrbniški seji, zato moraš prizadeta spletna mesta takoj pregledati tudi na ravni uporabnikov, MU-vtičnikov in podatkovne zbirke.

Vsi spodaj navedeni vtičniki so v uradnem imeniku WordPressa začasno zaprti, dokler pregled in preiskava ne zaključita. Napad cilja komponento Biggopti, ki jo uporabljajo vtičniki BdThemes.

Zakaj je ta incident nevaren

Napad ne potrebuje posodobitve vtičnika, da doseže spletno mesto. Ne spremeni datotek vtičnika na disku, zato ga preverjanje integritete datotek praviloma ne zazna, požarni zid za spletne aplikacije pa ga težko opazi.

Kako deluje kompromitirana dobavna veriga

Oddaljeni promocijski JSON postane vektor napada

Vtičniki BdThemes vključujejo interno komponento Biggopti. Ta iz API-ja ponudnika pridobi promocijske pasice in jih prikaže na nadzorni plošči WordPressa. API ne poganja dinamične aplikacije, temveč streže statične datoteke JSON iz prostora DigitalOcean Spaces, ki ga varuje Cloudflare.

Napadalci niso spremenili izvorne kode v uradnem repozitoriju WordPress.org. Pridobili so zapisovalni dostop do vedra s statičnimi podatki oziroma do povezane infrastrukture in zamenjali legitimne odgovore JSON z zlonamernimi zapisi. To kaže na resen vdor v poverilnice shrambe v oblaku ali interno infrastrukturo BdThemes.

Vtičnik ob admin_init brezpogojno doda JavaScript v brskalnik. Skripta se zato zažene pri vsakem nalaganju katerekoli strani wp-admin, pridobi podatke o pasici z API-ja in sestavi element HTML v DOM-u.

XSS v atributu id

Ranljivost cross-site scripting (XSS) nastane, ker koda polje display_id iz oddaljenega odgovora JSON brez ustreznega ubežanja vstavi v atribut HTML id. Če display_id manjka, uporabi id, nato pa vrednost default.

// Vrednost prihaja iz oddaljenega JSON-a.
var f = t.display_id || t.id || "default";

// Nevarno: vrednost se brez ubežanja sestavi v atribut HTML.
var m = "bdt-admin-biggopti-api-biggopti-" + f;
A = 'id="' + m + '"';

Ista skripta vrednost za atribut data-display-id pravilno ubeži z zamenjavo znakov &, <, >, in ". Za atribut id tega ne naredi, čeprav bi morala enako obravnavati vsak podatek, ki prihaja iz zunanjega odgovora.

function escapeHtml(value) {
  return (value || "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

Zgodovina SVN kaže, da je neubežen vnos v atribut id najprej prišel v Prime Slider 1. marca 2026, v različici 4.1.9 in reviziji r3471891, nato pa še v druge vtičnike. Poznejše izdaje so za polje vsebine pasice dodale čistilnik na osnovi DOMParser, ki odstrani nevarne oznake HTML in inline handlerje, vendar display_id v atributu id ni dobil ubežanja.

Zlonamerni display_id zapre atribut id in doda handler dogodka onanimationstart. CSS-animacija ga sproži v 10 milisekundah, zato se JavaScript izvede tiho vsakič, ko prijavljeni skrbnik odpre stran nadzorne plošče. Tako napadalec izkoristi že overjeno skrbniško sejo v brskalniku.

Ranljivi vtičniki in ocena tveganja

Biggopti Library je ranljiv za XSS prek parametra display_id iz API-ja Sigmative zaradi nezadostnega ubežanja izhoda. Ocena CVSS znaša 5,4 oziroma srednje tveganje, popravek pa ob razkritju še ni obstajal. Podrobnosti ranljivosti so na strani Wordfence Threat Intelligence.

Prizadeti so naslednji vtičniki in njihovi slugi:

  • 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

Večstopenjska zlonamerna koda

Vbrizgani handler pridobi zunanjo skripto glede na dosegljivost infrastrukture napadalca. Napad uporablja dva toka: primarni w2.js za vtičnike z endpointom api-data-all-records in alternativni x.js za vtičnike z endpointom api-data-records.

Primarni tok w2.js

Glavna koda w2.js najprej pošlje izvor spletnega mesta na C2 endpoint ia-cdn[.]com/fz/c in prejme navodila za ciljanje. Če C2 vrne stanje skip ali done, izvajanje prekine.

Nato koda uporabi X-WP-Nonce iz aktivne skrbniške seje ter prek WordPress REST API-ja ustvari novega uporabnika z vlogo administrator. Če REST API ne uspe, uporabi običajne oddaje obrazcev WordPressa.

S C2 nato prenese ZIP lažnega vtičnika in ga namesti prek standardnega obrazca za nalaganje vtičnikov. Vtičnik se skriva za nevtralno zvenečim slugom, na primer wp-smart-thumbnails, vsebuje pa spletno lupino emer-run.php, ki jo napadalec neposredno prikliče prek URL-ja.

emer-run.php namesti dva modula za obstojnost v imenik Must-Use vtičnikov. Oba zajeta primerka sta imela časovne žige prestavljene v september 2025, da bi se zlila z legitimnimi datotekami; imena datotek se med okužbami lahko spremenijo.

  • Prvi MU-vtičnik doda stranska vrata za prijavo brez avtentikacije prek parametra URL ?_wplogin=<token>. Cilja administratorja, ki je na spletnem mestu registriran najdlje.
  • Drugi MU-vtičnik skriva sledi analitikom: priklopi se na poizvedbe podatkovne zbirke WordPressa, skrije ustvarjene lažne račune s seznama uporabnikov in ustrezno zmanjša prikazano skupno število uporabnikov.

Koda ob vsakem koraku pošlje rezultat na C2 prek navigator.sendBeacon.

Alternativni tok x.js

Alternativna skripta x.js je gostovala neposredno v infrastrukturi BdThemes. Iz imena gostitelja spletnega mesta izračuna deterministične poverilnice: uporabniško ime sestavi kot bd_ in šestznakovni hash base36, geslo pa kot Bd@26!, isti hash in končni znak x.

function makeCreds() {
  var host = siteKey();
  var hash = 0;

  for (var i = 0; i < host.length; i++) {
    hash = ((hash << 5) - hash + host.charCodeAt(i)) | 0;
  }

  var n = Math.abs(hash).toString(36).slice(0, 6);
  return {
    user: 'bd_' + n,
    pass: 'Bd@26!' + n + 'x'
  };
}

Skripta novemu računu pripne e-poštni naslov z domeno @wordpress.org, nato pa izid pošlje C2. V brskalnikov localStorage zapiše zastavico, če je na voljo, da istega postopka ne izvaja znova.

Ker algoritem vedno ustvari enake poverilnice za isto ime gostitelja, napadalcem ni treba centralno hraniti seznama kompromitiranih mest. Pri pregledu sumljive domene lahko zato natančno izračunaš pričakovano uporabniško ime in geslo ter ju poiščeš.

Kazalniki kompromitacije

Pri pregledu strežnika, podatkovne zbirke in omrežnih dnevnikov poišči vse spodnje kazalnike. Najdba enega od njih zahteva celovit odziv na incident, ne le odstranitev posamezne datoteke.

Zunanji endpointi

  • Primarna zlonamerna koda: ia-cdn[.]com/fz/w2.js
  • C2 beacon endpoint: ia-cdn[.]com/fz/c
  • Kompromitirani endpoint ponudnika: api[.]sigmative[.]io/prod/store/api/biggopti/api-data-all-records
  • Kompromitirani endpoint ponudnika: api[.]sigmative[.]io/prod/store/api/biggopti/api-data-records
  • Alternativna koda na infrastrukturi ponudnika: api[.]sigmative[.]io/prod/store/api/biggopti/x.js

Oba endpointa JSON zdaj vračata čiste podatke, vendar to ne odstrani že izvedene kode, ustvarjenih računov ali nameščenih stranskih vrat. Endpointa sta bila v času kompromitacije vir zastrupljenih podatkov.

Datoteke in zapisi v podatkovni zbirki

  • Spletna lupina: emer-run.php z MD5 1024732009983dd5e54b4cf5593f04d4.
  • MU-vtičnik za magic login: class-wp-token-validate.php z MD5 7719cd98a35ffad2771f26d1ceab7d27.
  • MU-vtičnik za prikrivanje: class-wp-query-9d127ff3.php oziroma podobno ime po vzorcu class-wp-query-*.php, z MD5 9aadc3e5c5242b273bd17c5bdc358845.
  • MU-vtičnik, poimenovan kot health check: wp-cache-optimizer.php z MD5 e450ae5bc4bfc0d960dded06a76bb8e9.
  • Možnost podatkovne zbirke fz_emer_login_tokens, ki shranjuje žetone za magic login.
  • Možnost podatkovne zbirke fz_emer_done_v1, ki označuje dokončano kompromitacijo.
  • Uporabniški računi z e-poštnim naslovom na domeni @wordpress.org ali @developer.wordpress.org.
  • Uporabniška imena po vzorcu bd_ in šest alfanumeričnih znakov.

Časovnica incidenta

  1. 1. marec 2026: Biggopti API JavaScript pride v Prime Slider 4.1.9 (SVN r3471891). display_id se brez ubežanja vstavi v atribut id, uporabi pa se endpoint api-data-records.
  2. 10. maj 2026: endpoint se spremeni v api-data-all-records. Za polje vsebine dodajo čistilnik DOMParser, atribut id pa ostane ranljiv.
  3. 23. junij 2026: zastrupljena kampanja v API-ju dobi start_date za obvestilo »Summer Sale«. To je najzgodnejši možni datum aktivnega XSS-a.
  4. 6. avgust 2026 ob 22:40 UTC: zadnja sprememba zastrupljenega api-data-records.
  5. 7. avgust 2026 ob 09:11 UTC: zadnja sprememba zastrupljenega api-data-all-records.
  6. 7. avgust 2026: napad zaznajo v dejanskih okužbah, vtičnike pa v imeniku WordPress zaprejo do pregleda.
  7. 7. avgust 2026 ob 16:56 UTC: zajamejo artefakte preiskave.
  8. 8. avgust 2026: oba API endpointa znova vračata čist JSON.

Kaj naredi zdaj

Če uporabljaš kateregakoli od prizadetih vtičnikov, ne čakaj na zgolj posodobitev. Preglej seznam uporabnikov, vključno s skritimi oziroma sumljivimi administratorji, imenik wp-content/mu-plugins, imenike vtičnikov ter tabelo možnosti v podatkovni zbirki za vse navedene kazalnike.

Preveri tudi dostopne dnevnike in DNS oziroma HTTP promet za povezave z ia-cdn[.]com ter pregledaj, ali je kdo neposredno klical sumljive PHP datoteke. Ker napad uporablja legitimno sejo administratorja in lahko za seboj pusti več plasti obstojnosti, odstrani lažne račune, spletno lupino in MU-vtičnike šele po forenzičnem zajemu dokazov ter rotaciji vseh skrbniških poverilnic, gesel podatkovne zbirke, API-ključev in sej.

C2 domena je povezana tudi z napadi na dobavno verigo vtičnikov Advanced Responsive Video Embedder in OptinMonster v prejšnjih dveh mesecih. Cilj te kampanje je tiha, množična skrbniška obstojnost in oddaljeno izvajanje kode v WordPress okoljih.

Preveri več kot le integriteto datotek

Čiste datoteke vtičnika ne dokazujejo, da spletno mesto ni kompromitirano. Ta napad je zlorabil zaupanja vreden tok oddaljenih podatkov, nato pa je v prijavljeni seji ustvaril račune, naložil zlonamerno kodo in namestil obstojnost.

Pridružite se skupnosti HelloWP!

Klepetajte z nami o WordPressu, spletnem razvoju in delite izkušnje z drugimi razvijalci.

- člani
- na spletu
Pridruži se

Piškotke uporabljamo za izboljšanje vaše izkušnje. Z nadaljevanjem se strinjate z našo Politiko piškotkov.