Preskoči na sadržaj
BdThemes API napad: XSS u banneru kompromitirao je WordPress administratore
Ana Horvat
Ana Horvat 9. August 2026. · 9 min čitanja

BdThemes API napad: XSS u banneru kompromitirao je WordPress administratore

Napadači su kompromitirali opskrbni lanac dodataka tvrtke BdThemes bez izmjene ijedne datoteke u službenom WordPress.org repozitoriju. Umjesto toga, izmijenili su udaljeni JSON odgovor koji dodaci dohvaćaju za promotivne obavijesti u administraciji, a XSS propust pretvorili su u potpuno preuzimanje WordPress stranice.

WordPress Plugins tim privremeno je zatvorio sve pogođene dodatke dok traje pregled i istraga. Ako ih imate na stranici, nemojte se zadržati samo na ažuriranju: pregledajte korisnike, direktorije dodataka i tablicu opcija u bazi podataka.

Što je pogođeno i zašto ovo nije običan napad na dodatak

Pogođeni dodaci koriste internu komponentu Biggopti. Ona na svakom učitavanju administracije dohvaća promotivne bannere s API-ja dobavljača i prikazuje ih u WordPress nadzornoj ploči. API ne pokreće aplikacijski poslužitelj, nego poslužuje statične JSON datoteke iz DigitalOcean Spaces bucketa zaštićenog Cloudflareom.

Napadači su očito dobili pravo pisanja u taj bucket ili pristup infrastrukturi BdThemesa. Zamijenili su legitimne JSON odgovore posebno oblikovanim sadržajem. Zato žrtva nije morala instalirati novu verziju dodatka, a datoteke dodatka na hostingu ostale su nepromijenjene: napad se izvršavao isključivo preko API odgovora, što ga čini teško vidljivim alatima koji provjeravaju integritet datoteka i uglavnom neupadljivim za web aplikacijske vatrozide.

Pogođeni dodaci

Ranjivost zahvaća biblioteku Biggopti u različitim verzijama. Ima CVSS ocjenu 5,4 (srednja razina) i u trenutku incidenta nije postojala zakrpa.

  • 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)

XSS u polju display_id izvršavao se svakom administratoru

Svaki BdThemes dodatak koji koristi Biggopti na hooku admin_init dodaje JavaScript u preglednik. Skripta se zato bezuvjetno izvršava pri svakom učitavanju bilo koje stranice unutar wp-admin sučelja, dohvaća podatke bannera i sastavlja HTML obavijest u DOM-u.

Problem je nastao jer kod uzima display_id iz udaljenog JSON-a i bez izlaznog escapinga spaja ga u HTML atribut id. Dovoljno je da napadač zatvori navodnik u vrijednosti atributa kako bi umetnuo vlastiti HTML atribut i JavaScript događaj.

// Neescapirana vrijednost iz udaljenog JSON odgovora
var f = t.display_id || t.id || "default";
var m = "bdt-admin-biggopti-api-biggopti-" + f;
A = 'id="' + m + '"';

U istom se kodu data-display-id ispravno escapira funkcijom koja mijenja &, <, >, i " u HTML entitete. To pokazuje da se autor koda pobrinuo za jedan atribut, ali ne i za id; struktura funkcije upućuje na minificirani ili bundlani kod.

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

Neescapirani unos uveden je 1. ožujka 2026. u Prime Slider 4.1.9, u SVN reviziji r3471891, a zatim je prenesen u druge dodatke. Kasnija izdanja dodala su sanitizer temeljen na DOMParseru za polje sadržaja bannera, koji uklanja opasne HTML oznake i inline handlere, ali id atribut ostao je ranjiv.

Zlonamjerni display_id iz kompromitiranog odgovora prekida atribut id te dodaje onanimationstart. CSS animacija aktivira taj handler za približno 10 milisekundi, bez vidljive interakcije, čim prijavljeni administrator otvori bilo koju stranicu nadzorne ploče. Uočeni odgovor sadržavao je niz SAFE" onanimationstart=eval(String.fromCharCode(...)) style=animation:wrapperSlideInTop .01s ease-out both, koji je dekodirao i dohvaćao vanjsku skriptu.

Dva payload puta vode do trajne kompromitacije

Umetnuti event handler bira vanjske skripte prema dostupnosti infrastrukture napadača. Primarni w2.js dolazio je dodatcima koji koriste endpoint api-data-all-records, dok je alternativni x.js bio izravno smješten u infrastrukturi BdThemesa i posluživao se dodacima s endpointom api-data-records.

Primarni payload w2.js

Kad se w2.js pokrene u sesiji prijavljenog administratora, prvo kontaktira C2 endpoint ia-cdn[.]com/fz/c i šalje origin žrtvine stranice. Ako C2 vrati status skip ili done, skripta prekida rad; inače prima upute za ciljanje.

  1. Iskorištava X-WP-Nonce iz aktivne administratorske sesije i preko WordPress REST API-ja stvara novog administratora. Ako taj put ne uspije, pokušava poslati standardni administratorski obrazac.
  2. S C2 poslužitelja preuzima ZIP koji se predstavlja kao dodatak te ga instalira kroz standardni obrazac za prijenos dodataka. Lažni dodatak koristi slug wp-smart-thumbnails ili sličan neutralan naziv, a sadrži webshell emer-run.php koji se poziva izravno URL-om.
  3. Poziv emer-run.php instalira dva modula za trajnost u direktorij Must-Use dodataka. U oba pronađena uzorka vremenske oznake vraćene su na rujan 2025. kako bi se uklopile među legitimne datoteke; nazivi se mogu razlikovati među infekcijama.
  4. Prvi MU dodatak daje magic-login backdoor: neprijavljeni napadač može administratorski pristupiti najdulje registriranom administratoru stranice preko parametra ?_wplogin=<token>.
  5. Drugi MU dodatak skriva novostvorene lažne račune: hooka upite WordPressove baze, uklanja račune s administrativnog popisa korisnika i odgovarajuće smanjuje ukupan broj korisnika.
  6. Skripta šalje rezultate svake faze na C2 preko navigator.sendBeacon.

Alternativni payload x.js

x.js računa administratorske vjerodajnice iz hostnamea žrtvine stranice. Algoritam prolazi kroz znakove hostnamea, gradi 32-bitni hash, uzima apsolutnu vrijednost, pretvara je u base36 i zadržava prvih šest znakova. Time dobiva korisničko ime oblika bd_ + šesteroznakovni hash te lozinku Bd@26! + hash + x.

function makeCreds(host) {
  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"
  };
}

Payload novom računu dodjeljuje adresu @wordpress.org, dohvaća obrazac /wp-admin/user-new.php, iz njega izvlači nonce i URL za odjavu te POST zahtjevom izrađuje administratora. Rezultat, korisničko ime, lozinku, origin, URL stranice i URL za odjavu šalje C2-u preko sendBeacon; ako to ne uspije, koristi fetch s no-cors, keepalive i bez vjerodajnica. U preglednikov localStorage sprema zastavicu dovršetka kad je dostupan.

Vjerodajnice su determinističke pa napadači ne moraju centralno čuvati popis kompromitiranih stranica. S druge strane, incident response tim može za sumnjivu domenu izračunati točan račun i lozinku koje treba tražiti.

Indikatori kompromitacije

Pregledajte poslužitelj i bazu prema sljedećim indikatorima. Pogođeni API endpointi u međuvremenu vraćaju čisti JSON, ali to ne uklanja već stvorene račune, webshellove i MU backdoorove.

Mrežni indikatori

  • Primarni payload: ia-cdn[.]com/fz/w2.js
  • C2 beacon endpoint: ia-cdn[.]com/fz/c
  • Kompromitirani API endpoint, sada očišćen: api[.]sigmative[.]io/prod/store/api/biggopti/api-data-all-records
  • Kompromitirani API endpoint, sada očišćen: api[.]sigmative[.]io/prod/store/api/biggopti/api-data-records
  • Alternativni payload na infrastrukturi dobavljača: api[.]sigmative[.]io/prod/store/api/biggopti/x.js

Datoteke, opcije i računi

  • Webshell emer-run.php, MD5: 1024732009983dd5e54b4cf5593f04d4.
  • MU magic-login backdoor class-wp-token-validate.php, MD5: 7719cd98a35ffad2771f26d1ceab7d27.
  • MU stealth modul class-wp-query-9d127ff3.php ili sličan naziv prema obrascu class-wp-query-*.php, MD5 poznatog uzorka: 9aadc3e5c5242b273bd17c5bdc358845.
  • MU modul koji se predstavlja kao health check, wp-cache-optimizer.php, MD5: e450ae5bc4bfc0d960dded06a76bb8e9.
  • Opcija baze fz_emer_login_tokens, koja čuva magic-login tokene.
  • Opcija baze fz_emer_done_v1, koja označava dovršenu kompromitaciju.
  • Računi s e-adresom na domeni @wordpress.org ili @developer.wordpress.org.
  • Korisnička imena koja odgovaraju obrascu bd_ iza kojeg slijedi šest alfanumeričkih znakova.

Kronologija incidenta

  • 1. ožujka 2026. – Biggopti API JavaScript dodan je u Prime Slider 4.1.9 (SVN r3471891). display_id ulazi neescapiran u id atribut, a koristi se endpoint api-data-records.
  • 10. svibnja 2026. – endpoint se mijenja u api-data-all-records. Dodan je DOMParser sanitizer za polje sadržaja, ali id atribut ostaje neescapiran.
  • 23. lipnja 2026.start_date kampanje u kompromitiranom API-ju nosi promotivnu obavijest „Summer Sale”. To je najraniji mogući datum aktivnog XSS-a.
  • 6. kolovoza 2026. u 22:40 UTC – posljednja izmjena kompromitiranog api-data-records odgovora.
  • 7. kolovoza 2026. u 09:11 UTC – posljednja izmjena kompromitiranog api-data-all-records odgovora.
  • 7. kolovoza 2026. – napad je uočen u stvarnim napadima i prijavljen sigurnosnom timu; WordPress direktorij zatvara dodatke do pregleda.
  • 7. kolovoza 2026. u 16:56 UTC – prikupljeni su artefakti istrage.
  • 8. kolovoza 2026. – oba API endpointa vraćaju čisti JSON.

Što trebate učiniti odmah

Ako vaša stranica koristi bilo koji navedeni BdThemes dodatak, pretpostavite da je administrator možda učitao kompromitiranu administracijsku stranicu između najranijeg mogućeg datuma napada i čišćenja API-ja. Pregledajte popis korisnika, osobito račune bd_****** i e-adrese s navedenih domena, zatim provjerite direktorije standardnih i Must-Use dodataka za navedene datoteke te pretražite tablicu opcija za fz_emer_login_tokens i fz_emer_done_v1.

Samo uklanjanje dodatka ili provjera izmjena u datotekama nije dovoljna jer je napad stvarao administratore i trajne backdoorove bez izmjene postojećih datoteka dodatka. Uklonite pronađene indikatore, opozovite sumnjive administratorske račune i provjerite cijelu instalaciju prije nego što joj ponovno povjerite produkcijski promet.

Wordfence Premium, Care, Response i plaćeni korisnici Wordfence CLI-ja dobili su potpise zlonamjernog softvera i WAF pravila za ovaj incident 7. kolovoza 2026. Besplatni korisnici Wordfencea i besplatnog Wordfence CLI-ja dobit će iste potpise i pravila nakon uobičajenog odgode od 30 dana.

Zaključak

Ovaj incident pokazuje da pouzdana udaljena promotivna poruka može postati vektor napada jednako opasan kao kompromitirano izdanje dodatka. Obranu zato ne smijete graditi samo na provjeri promjena u WordPress datotekama: kod koji renderira udaljeni sadržaj mora escapirati svaki kontekst, a incident response mora obuhvatiti račune, bazu, MU dodatke, mrežne zahtjeve i mehanizme trajnosti.

Pridružite se HelloWP zajednici!

Razgovarajte s nama o WordPressu, web razvoju i podijelite iskustva s drugim developerima.

- članovi
- online
Pridruži se

Koristimo kolačiće kako bismo poboljšali vaše iskustvo. Nastavkom se slažete s našom Politikom kolačića.