Ga naar inhoud
BdThemes-supplychainaanval via vergiftigde API: controleer je WordPress-sites
Naomi Wijngaard
Naomi Wijngaard 9 August 2026 · 9 min leestijd

BdThemes-supplychainaanval via vergiftigde API: controleer je WordPress-sites

Een gecompromitteerde promotiefeed heeft meerdere BdThemes-plugins veranderd in een aanvalskanaal. Aanvallers hoefden geen bestanden in de WordPress.org-repository te wijzigen: een vergiftigd JSON-antwoord liet JavaScript draaien in iedere ingelogde beheerderssessie en kon zo volledige siteovername veroorzaken.

De WordPress-pluginteam heeft alle getroffen plugins tijdelijk gesloten terwijl het onderzoek en een volledige inspectie lopen. Controleer sites met deze plugins direct op de indicatoren in dit artikel, ook als je geen verdachte wijzigingen in pluginbestanden ziet.

Volledige sitecompromittering mogelijk

Deze aanval werkt zonder pluginupdate en laat de pluginbestanden op schijf ongemoeid. Alleen bestandsintegriteitscontroles missen de primaire infectieketen daarom mogelijk.

Wat is er gecompromitteerd?

BdThemes levert in meerdere plugins een intern systeem met de naam Biggopti. Dit systeem haalt promotiebanners op vanaf een API en toont ze in het WordPress-dashboard. De API gebruikt geen dynamische applicatieserver, maar statische JSON-bestanden in een DigitalOcean Spaces-bucket die Cloudflare beschermt.

Aanvallers kregen schrijfrechten op die opslagbucket of op de infrastructuur eromheen. Zij vervingen legitieme JSON-antwoorden door kwaadaardige records en maakten misbruik van een XSS-kwetsbaarheid die de pluginmakers in de parser voor die antwoorden hadden geïntroduceerd.

XSS, of cross-site scripting, betekent dat onbetrouwbare invoer als uitvoerbare browsercode op een pagina terechtkomt. Hier draait die code in de browser van een ingelogde WordPress-beheerder, stilzwijgend bij elke laadactie van een wp-admin-pagina.

Getroffen plugins en kwetsbaarheid

De kwetsbaarheid zit in Biggopti en heeft een CVSS-score van 5,4 (gemiddeld). De patchstatus is niet gepatcht. Het betreft XSS via de parameter display_id uit de Sigmative API, doordat de code uitvoer onvoldoende escapt.

De volgende plugins gebruiken de getroffen Biggopti-functionaliteit:

De kwetsbaarheid maakt het mogelijk dat iemand die de Sigmative API-server of de bijbehorende opslag compromitteert, willekeurige scripts in geïnjecteerde pagina’s uitvoert. Bekijk de volledige kwetsbaarheidsregistratie voor de technische classificatie: Biggopti Library – Cross-Site Scripting via display_id from Sigmative API.

De fout in de dashboardbanner

Elke BdThemes-plugin die Biggopti gebruikt, laadt een client-side JavaScript-bestand tijdens admin_init. Daardoor draait het script onvoorwaardelijk bij iedere wp-admin-paginalaadactie. Het script vraagt de bannergegevens op bij de API en bouwt vervolgens een HTML-notice in de DOM, de documentstructuur van de browser.

Daarbij neemt de code display_id uit het externe JSON-antwoord rechtstreeks op in een HTML-id-attribuut. Die waarde krijgt geen client-side escaping. Het patroon komt neer op het volgende onveilige gedrag:

// displayId komt uit een extern JSON-antwoord en is niet ontsmet.
const displayId = banner.display_id || banner.id || 'default';
const elementId = 'bdt-admin-biggopti-api-biggopti-' + displayId;
const attributes = 'id="' + elementId + '"';

In hetzelfde script ontsmet de code het attribuut data-display-id wél. Die routine vervangt onder meer &, <, >, en dubbele aanhalingstekens door HTML-entiteiten. De bescherming geldt echter niet voor de injectie in het id-attribuut.

De SVN-geschiedenis plaatst de fout op 1 maart 2026. Prime Slider-versie 4.1.9, met SVN-revisie r3471891, voegde toen de Biggopti-API-JavaScript toe en gebruikte display_id zonder escaping in het id-attribuut. Daarna kwam dezelfde aanpak in andere plugins terecht.

Latere releases voegden een op DOMParser gebaseerde sanitizer toe voor het inhoudsveld van de banner. Die verwijdert gevaarlijke HTML-tags en inline eventhandlers uit de inhoud, maar laat de onveilige id-attribuutinjectie bestaan. Op 10 mei veranderde het endpoint naar api-data-all-records; ook toen bleef het id-attribuut ongeëscaped.

Van JSON-record naar beheerderstoegang

De kwaadaardige display_id sluit het HTML-id-attribuut af en voegt een onanimationstart-eventhandler toe. Een CSS-animatie start die handler binnen 10 milliseconden. Daardoor haalt de browser een vervolgscripts op zodra een beheerder een willekeurige dashboardpagina opent, zonder zichtbare interactie.

De oudste mogelijke actieve datum van de XSS-campagne is 23 juni 2026. Het vergiftigde record gebruikte een promotiebericht voor een zomeractie met die start_date. De API-antwoorden bevatten op het moment van onderzoek nog de kwaadaardige gegevens.

Primair script: w2.js

Voor plugins die api-data-all-records gebruiken, laadt de aanval het primaire script w2.js. Dat script benadert eerst de command-and-controlserver (C2) op ia-cdn[.]com/fz/c met de origin van de getroffen site. De C2 geeft doelinstructies terug; bij de status skip of done stopt het script.

Als de aanval doorgaat, gebruikt het script de actieve X-WP-Nonce uit de beheerderssessie om via de WordPress REST API een nieuwe administrator aan te maken. Als dat niet lukt, probeert het de gebruikelijke formulierverzendingen in WordPress.

Vervolgens downloadt het vanaf de C2 een nepplugin als ZIP en installeert die via het normale formulier voor pluginuploads. De aanvallers maskeren die plugin met een neutraal klinkende slug zoals wp-smart-thumbnails. De ZIP bevat een webshell met de naam emer-run.php, die rechtstreeks via een URL wordt aangeroepen.

De webshell installeert daarna twee persistentiemodules in de map voor Must-Use-plugins. De aangetroffen voorbeelden droegen tijdstempels uit september 2025 om op legitieme bestanden te lijken; bestandsnamen kunnen per infectie verschillen. Een module maakt magisch inloggen als administrator mogelijk via ?_wplogin=<token> en richt zich op de beheerder die het langst geregistreerd staat. De andere module haakt in op WordPress-databasequeries, verbergt de aangemaakte accounts in de gebruikerslijst en verlaagt ook de weergegeven gebruikersaantallen.

Tijdens elke fase stuurt het script resultaten terug naar de C2 met navigator.sendBeacon. Die browser-API verstuurt data ook als de pagina sluit.

Alternatief script: x.js

Het alternatieve script x.js stond rechtstreeks op de infrastructuur van BdThemes en werd geleverd aan plugins met het endpoint api-data-records. Dit script maakt beheerdersgegevens die het deterministisch afleidt uit de hostnaam van de getroffen site.

De gebruikersnaam volgt het patroon bd_ plus een base36-hash van zes tekens. Het wachtwoord is eveneens uit die hash afgeleid en het account krijgt een e-mailadres op @wordpress.org. Omdat de gegevens voorspelbaar zijn, hoeven de aanvallers geen centrale lijst met gecompromitteerde sites te bewaren; incidentresponders kunnen de verwachte accountnaam en inloggegevens voor een verdacht domein zelf afleiden.

Het script gebruikt de sessie van de beheerder om wp-admin/user-new.php op te vragen, haalt daar een nonce op en verstuurt vervolgens het formulier om een administrator te maken. Daarna rapporteert het resultaat, de inloggegevens, de site-origin, de logout-URL en de pagina-URL aan de C2. Als de browser localStorage ondersteunt, schrijft het een vlag om de actie niet opnieuw uit te voeren.

Indicatoren van compromittering

Doorzoek zowel bestanden als de database en controleer accounts handmatig. De aanval kan nieuwe beheerders verbergen in de gebruikerslijst, dus vergelijk queryresultaten, de daadwerkelijke database en je verwachte accountinventaris.

  • Primair payloadadres: ia-cdn[.]com/fz/w2.js.
  • C2-beaconendpoint: ia-cdn[.]com/fz/c.
  • Vergiftigde API-endpoints, inmiddels opgeschoond: api[.]sigmative[.]io/prod/store/api/biggopti/api-data-all-records, api[.]sigmative[.]io/prod/store/api/biggopti/api-data-records en api[.]sigmative[.]io/prod/store/api/biggopti/x.js.
  • Webshellbestand: emer-run.php, MD5 1024732009983dd5e54b4cf5593f04d4.
  • MU-plugin voor magic login: class-wp-token-validate.php, MD5 7719cd98a35ffad2771f26d1ceab7d27.
  • MU-plugin voor stealth: class-wp-query-9d127ff3.php of een vergelijkbare naam volgens class-wp-query-*.php, MD5 9aadc3e5c5242b273bd17c5bdc358845.
  • MU-plugin vermomd als healthcheck: wp-cache-optimizer.php, MD5 e450ae5bc4bfc0d960dded06a76bb8e9.
  • Databaseoptie fz_emer_login_tokens, waarin magic-login-tokens staan.
  • Databaseoptie fz_emer_done_v1, een vlag die een afgeronde compromittering markeert.
  • Accounts met een e-mailadres op @wordpress.org of @developer.wordpress.org.
  • Gebruikersnamen die passen bij bd_ gevolgd door zes alfanumerieke tekens.

Tijdlijn van de aanval

  • 1 maart 2026: Prime Slider 4.1.9 krijgt Biggopti-API-JavaScript via SVN r3471891. display_id komt zonder escaping in een id-attribuut terecht; het endpoint is api-data-records.
  • 10 mei 2026: Het endpoint verandert naar api-data-all-records. De content krijgt een DOMParser-sanitizer, maar het id-attribuut blijft onveilig.
  • 23 juni 2026: De start_date in de vergiftigde API-campagne voor de zomeraanbieding markeert de vroegst mogelijke datum waarop de XSS actief was.
  • 6 augustus 2026, 22:40 UTC: De laatste wijzigingsdatum van het vergiftigde api-data-records-antwoord.
  • 7 augustus 2026, 09:11 UTC: De laatste wijzigingsdatum van het vergiftigde api-data-all-records-antwoord.
  • 7 augustus 2026: De aanval wordt in het wild waargenomen en gemeld bij het Threat Intelligence Team. De WordPress-pluginteam sluit de plugins dezelfde dag in afwachting van beoordeling.
  • 7 augustus 2026, 16:56 UTC: Onderzoekers leggen onderzoeksartefacten vast.
  • 8 augustus 2026: Beide API-endpoints leveren weer schone JSON.

Reikwijdte en detectie

De C2-domeinnaam hangt samen met de aanvallers achter de recente supplychainaanvallen op Advanced Responsive Video Embedder en OptinMonster. Hun doel is grootschalige, stille persistentie als administrator en remote code execution in WordPress-omgevingen.

Deze aanval onderscheidt zich van een klassieke supplychainaanval omdat geen enkel sourcebestand in de officiële WordPress.org-repository hoefde te veranderen. Een vertrouwde externe promotiefeed was genoeg om de kwetsbare weergavecode aan te vallen. Dat kwaadaardige JSON-records en x.js in de eigen bucket van BdThemes terechtkwamen, wijst op een ernstige compromittering van cloudopslagreferenties of interne infrastructuur.

Wordfence Premium, Care en Response, plus betalende gebruikers van Wordfence CLI, kregen op 7 augustus 2026 malwaresignaturen en WAF-regels voor deze aanval. Gratis gebruikers van Wordfence en Wordfence CLI krijgen dezelfde detectieregels na de gebruikelijke vertraging van 30 dagen.

Wordfence Care en Response bieden beveiligingsmonitoring en malwareverwijdering. Bij een incident onderzoekt het responsteam de oorzaak, verwijdert het malware en helpt het met gevolgen van de infectie. De Threat Intelligence-database bevat meer dan 4,4 miljoen unieke kwaadaardige samples; met de premiumsignatures detecteren de Wordfence-plugin en Wordfence CLI meer dan 99% van die samples en compromitteringsindicatoren. Wordfence CLI scant ook wanneer WordPress niet meer functioneert en vormt daarmee een extra serverlaag volgens het principe defense in depth.

Wat je nu moet doen

Inventariseer eerst alle sites waarop een van de zeven getroffen BdThemes-plugins staat. Controleer daarna de gebruikersdatabase, de pluginmappen en vooral de Must-Use-pluginmap op alle genoemde indicatoren. Zoek ook expliciet naar de twee databaseopties en naar uitgaande verzoeken naar de vermelde domeinen.

Behandel elke gevonden indicator als een volledige compromittering: verwijder niet alleen het verdachte account of bestand, maar onderzoek alle persistentiemechanismen en herstel vanuit een betrouwbare back-up waar nodig. Roteer beheerderswachtwoorden, API-sleutels en andere geheimen nadat je de omgeving hebt opgeschoond, want een webshell of magic-loginbackdoor geeft aanvallers opnieuw toegang.

Naomi Wijngaard

Naomi Wijngaard

Frontend-ontwikkelaar en CSS-kunstenaar. Het maken van animaties en interactieve websites is mijn passie. Fan van Svelte en SvelteKit.

Alle berichten

Word lid van de HelloWP-community!

Chat met ons over WordPress en webontwikkeling en deel ervaringen met andere ontwikkelaars.

- leden
- online
Deelnemen

We gebruiken cookies om je ervaring te verbeteren. Door verder te gaan, ga je akkoord met ons Cookiebeleid.