{"id":260,"date":"2026-08-09T10:45:20","date_gmt":"2026-08-09T08:45:20","guid":{"rendered":"https:\/\/helloblog.io\/de\/bdthemes-supply-chain-angriff-json-api\/"},"modified":"2026-08-09T10:45:20","modified_gmt":"2026-08-09T08:45:20","slug":"bdthemes-supply-chain-angriff-json-api","status":"publish","type":"post","link":"https:\/\/helloblog.io\/de\/bdthemes-supply-chain-angriff-json-api\/","title":{"rendered":"BdThemes-Plugins: Supply-Chain-Angriff \u00fcber manipulierte JSON-API"},"content":{"rendered":"\n<p>Ein kompromittierter externer Datenstrom kann eine WordPress-Installation angreifen, obwohl im Plugin-Verzeichnis keine einzige Quelldatei ver\u00e4ndert wurde. Genau dieses Muster traf mehrere Plugins von BdThemes: Manipulierte JSON-Antworten lieferten JavaScript in jedes eingeloggte <code>wp-admin<\/code>-Dashboard und verschafften Angreifern dauerhaften Administratorzugriff.<\/p>\n\n\n\n<p>Die betroffenen Plugins sind im offiziellen WordPress-Plugin-Verzeichnis vor\u00fcbergehend geschlossen, w\u00e4hrend das WordPress-Plugins-Team sie pr\u00fcft. Wenn du eines dieser Plugins betreibst, solltest du deine Installation sofort auf die unten aufgef\u00fchrten Kompromittierungsindikatoren pr\u00fcfen.<\/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\">Warum dieser Angriff besonders gef\u00e4hrlich ist<\/h4>\n\n\n<p>Ein Plugin-Update oder eine manipulierte Datei auf dem Server war f\u00fcr den Angriff nicht n\u00f6tig. Der Schadcode kam \u00fcber eine Remote-API, lief im Browser eines angemeldeten Administrators und konnte dadurch neue Administratoren anlegen sowie weitere Malware installieren.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Betroffene Sicherheitsl\u00fccke und Plugins<\/h2>\n\n\n\n<p>Die Biggopti Library enth\u00e4lt in mehreren Versionen eine Cross-Site-Scripting-Schwachstelle (XSS). XSS bedeutet, dass Angreifer eigenen Webcode in eine Seite einschleusen k\u00f6nnen, den der Browser anschlie\u00dfend im Kontext der betroffenen Website ausf\u00fchrt. Hier betrifft die L\u00fccke den Wert <code>display_id<\/code>, den die Sigmative-API liefert.<\/p>\n\n\n\n<p>Die Schwachstelle hat einen CVSS-Score von <strong>5,4 (Medium)<\/strong> und ist ungepatcht. Weil die Ausgabe nicht ausreichend maskiert wird, kann ein Angreifer mit Schreibzugriff auf den Sigmative-API-Server beliebige Skripte in ausgelieferten Seiten platzieren. Jeder Aufruf einer pr\u00e4parierten Seite f\u00fchrt den Code dann aus.<\/p>\n\n\n\n<p>Die folgende Software ist betroffen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/bdthemes-element-pack-lite\">Element Pack Addons for Elementor &#8211; Elementor Widgets, Elementor Templates, Elementor Addons<\/a> (<code>bdthemes-element-pack-lite<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/live-copy-paste\">Live Copy Paste for Elementor &#8211; Cross Domain Copy Paste &#038; Page Duplicator<\/a> (<code>live-copy-paste<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/pixel-gallery\">Pixel Gallery Addons for Elementor &#8211; Easy Grid, Creative Gallery, Drag and Drop Grid, Custom Grid Layout, Portfolio Gallery<\/a> (<code>pixel-gallery<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/bdthemes-prime-slider-lite\">Prime Slider Addons for Elementor &#8211; Widgets, Templates &#038; Elementor Addons<\/a> (<code>bdthemes-prime-slider-lite<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/smart-admin-assistant\">Smart Admin Assistant &#8211; Dashboard and Site Enhancements<\/a> (<code>smart-admin-assistant<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/ultimate-post-kit\">Ultimate Post Kit Addons for Elementor<\/a> (<code>ultimate-post-kit<\/code>)<\/li>\n\n\n<li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/ultimate-store-kit\">Ultimate Store Kit &#8211; Addon For WooCommerce, EDD and Elementor<\/a> (<code>ultimate-store-kit<\/code>)<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">So nutzte die manipulierte API die Biggopti-Komponente aus<\/h2>\n\n\n\n<p>BdThemes liefert mit den Plugins die interne Komponente <em>Biggopti<\/em> aus. Sie l\u00e4dt Werbebanner von einem API-Server und zeigt sie im WordPress-Adminbereich an. Hinter der API stehen statische JSON-Dateien in einem durch Cloudflare gesch\u00fctzten DigitalOcean-Spaces-Bucket, nicht etwa ein dynamischer Application Server.<\/p>\n\n\n\n<p>Jedes Plugin mit Biggopti registriert auf <code>admin_init<\/code> ein clientseitiges JavaScript-Asset. Dieses Asset l\u00e4uft dadurch bedingungslos bei jedem Laden einer beliebigen <code>wp-admin<\/code>-Seite. Es l\u00e4dt Banner-Daten vom API-Endpoint und baut daraus einen Hinweis im Document Object Model (DOM).<\/p>\n\n\n\n<p>Dabei \u00fcbernimmt der Code <code>display_id<\/code> aus der JSON-Antwort direkt in das HTML-Attribut <code>id<\/code>. Er maskiert den Wert im Browser nicht:<\/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>\/\/ Nicht maskierter Wert aus der Remote-JSON-Antwort\nvar f = t.display_id || t.id || &quot;default&quot;;\n\n\/\/ Der Wert landet im HTML-Attribut id\nvar m = &quot;bdt-admin-biggopti-api-biggopti-&quot; + f;\nA = 'id=&quot;' + m + '&quot;';\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\">\/\/ Nicht maskierter Wert aus der Remote-JSON-Antwort<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">var<\/span><span style=\"color:#E1E4E8\"> f <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> t.display_id <\/span><span style=\"color:#F97583\">||<\/span><span style=\"color:#E1E4E8\"> t.id <\/span><span style=\"color:#F97583\">||<\/span><span style=\"color:#9ECBFF\"> \"default\"<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">\/\/ Der Wert landet im HTML-Attribut id<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">var<\/span><span style=\"color:#E1E4E8\"> m <\/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\"> f;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#79B8FF\">A<\/span><span style=\"color:#F97583\"> =<\/span><span style=\"color:#9ECBFF\"> 'id=\"'<\/span><span style=\"color:#F97583\"> +<\/span><span style=\"color:#E1E4E8\"> m <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#9ECBFF\"> '\"'<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Sp\u00e4ter im selben Code maskiert Biggopti das Attribut <code>data-display-id<\/code> dagegen korrekt. Die Funktion ersetzt <code>&amp;<\/code>, <code>&lt;<\/code>, <code>&gt;<\/code>, und Anf\u00fchrungszeichen, bevor sie den Wert ausgibt. Diese Absicherung sch\u00fctzt jedoch nicht die zuvor eingef\u00fcgte <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 escapeDisplayId(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\"> escapeDisplayId<\/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>Die unmaskierte Attribut-Injektion kam am 1. M\u00e4rz 2026 mit Prime Slider 4.1.9 in SVN-Revision <code>r3471891<\/code> hinzu und wurde anschlie\u00dfend in weitere Plugins \u00fcbernommen. Sp\u00e4tere Versionen erg\u00e4nzten zwar einen auf <code>DOMParser<\/code> basierenden Sanitizer f\u00fcr das Bannerfeld <code>content<\/code>, der gef\u00e4hrliche HTML-Tags und Inline-Handler entfernt. Das <code>id<\/code>-Attribut blieb jedoch weiterhin unmaskiert.<\/p>\n\n\n\n<p>Ein unbefugter Akteur ersetzte die legitimen JSON-Antworten im Storage-Bucket durch pr\u00e4parierte Datens\u00e4tze. Der manipulierte Wert <code>display_id<\/code> schlie\u00dft das <code>id<\/code>-Attribut, f\u00fcgt einen <code>onanimationstart<\/code>-Handler ein und startet eine CSS-Animation. Sie l\u00f6st den Handler nach rund zehn Millisekunden aus, sobald ein Administrator irgendeine Dashboard-Seite l\u00e4dt.<\/p>\n\n\n\n<p>Der manipulierte Datensatz trug unter anderem einen <code>display_id<\/code>, der mit <code>SAFE&quot; onanimationstart=eval(String.fromCharCode(...)) style=animation:wrapperSlideInTop .01s ease-out both<\/code> begann. Der kodierte Handler lud ein externes Skript von <code>https:\/\/api.sigmative.io\/prod\/store\/api\/biggopti\/x.js?_=1<\/code> nach und f\u00fchrte dessen Inhalt aus. Als Titel tarnte sich der Banner als \u201eBuild more. Pay less. This Summer\u201c.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Zweistufige Payloads erzeugten Administratorzugriff und Persistenz<\/h2>\n\n\n\n<p>Die Event-Handler luden je nach verf\u00fcgbarer Infrastruktur unterschiedliche Skripte. Beide Varianten arbeiteten im authentifizierten Browser-Kontext des Administrators und konnten daher dessen Berechtigungen f\u00fcr WordPress-Anfragen missbrauchen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prim\u00e4re Payload: w2.js<\/h3>\n\n\n\n<p>Plugins, die den Endpoint <code>api-data-all-records<\/code> nutzten, erhielten die prim\u00e4re Payload <code>w2.js<\/code>. Sie f\u00fchrte eine mehrstufige Kompromittierung aus:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li><strong>C2-Pr\u00fcfung:<\/strong> Das Skript kontaktierte <code>ia-cdn[.]com\/fz\/c<\/code> und \u00fcbermittelte die Origin der betroffenen Website. Meldete der Command-and-Control-Server (C2) den Status <code>skip<\/code> oder <code>done<\/code>, brach das Skript ab.<\/li>\n\n\n<li><strong>Anlegen eines fremden Administratorkontos:<\/strong> Das Skript verwendete den in der aktiven Administratorsitzung vorhandenen Header <code>X-WP-Nonce<\/code>, um \u00fcber die WordPress-REST-API einen Administrator anzulegen. Falls das scheiterte, nutzte es normale Formular\u00fcbermittlungen als R\u00fcckfallweg.<\/li>\n\n\n<li><strong>Installation einer Webshell:<\/strong> Das Skript lud ein gef\u00e4lschtes Plugin-ZIP vom C2-Server und installierte es \u00fcber das Standardformular f\u00fcr Plugin-Uploads. Das Plugin tarnte sich unter dem Slug <code>wp-smart-thumbnails<\/code> oder \u00e4hnlich unauff\u00e4lligen Slugs. Es enthielt die direkt per URL aufrufbare Webshell <code>emer-run.php<\/code>.<\/li>\n\n\n<li><strong>Persistenz \u00fcber Must-Use-Plugins:<\/strong> Der Aufruf von <code>emer-run.php<\/code> installierte zwei Persistenzmodule im Verzeichnis f\u00fcr Must-Use-Plugins. Die untersuchten Exemplare waren auf September 2025 zur\u00fcckdatiert, um sich in Dateisystem-Zeitstempel einzuf\u00fcgen. Dateinamen k\u00f6nnen je nach Infektion abweichen. Das erste Modul erlaubte einen nicht authentifizierten Admin-Login \u00fcber <code>?_wplogin=&lt;token&gt;<\/code> und zielte auf das am l\u00e4ngsten registrierte Administratorkonto. Das zweite Modul hakte sich in WordPress-Datenbankabfragen ein, versteckte die angelegten fremden Konten aus der Admin-Benutzerliste und verringerte die angezeigte Gesamtzahl der Benutzer entsprechend.<\/li>\n\n\n<li><strong>Exfiltration:<\/strong> Das Skript \u00fcbermittelte die Ergebnisse jeder Ausf\u00fchrungsphase mit <code>navigator.sendBeacon<\/code> an den C2-Server.<\/li>\n\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Alternative Payload: x.js<\/h3>\n\n\n\n<p>Die zweite Payload <code>x.js<\/code> lag direkt auf der BdThemes-Infrastruktur. Sie traf Plugins, die den Endpoint <code>api-data-records<\/code> verwendeten. Das Skript leitete Administratorzugangsdaten deterministisch aus dem Hostnamen der betroffenen Website ab.<\/p>\n\n\n\n<p>Daf\u00fcr berechnete es aus den Zeichen des Hostnamens einen 32-Bit-Hash, wandelte dessen Absolutwert in Base36 um und nutzte die ersten sechs Zeichen. Daraus entstanden Benutzernamen im Muster <code>bd_<\/code> plus sechsstelliger Base36-Hash und Passw\u00f6rter im Muster <code>Bd@26!<\/code> plus Hash plus <code>x<\/code>. Als E-Mail-Adresse verwendete das Skript <code>&lt;Benutzername&gt;@wordpress.org<\/code>.<\/p>\n\n\n\n<p>Die festen Zugangsdaten ersparen den Angreifern eine zentral gespeicherte Liste kompromittierter Websites. Bei einem Verdacht kannst du den erwarteten Benutzernamen und das Passwort aus dem Domainnamen ableiten und gezielt danach suchen.<\/p>\n\n\n\n<p>Anschlie\u00dfend rief das Skript <code>\/wp-admin\/user-new.php<\/code> mit den Cookies der aktuellen Sitzung ab, extrahierte Nonce und Logout-URL aus dem HTML und sendete eine Formularanfrage mit <code>role=administrator<\/code>. Es speicherte bei Erfolg ein lokales <code>localStorage<\/code>-Flag, erkannte Weiterleitungen mit Status 301, 302 oder <code>opaqueredirect<\/code> als Erfolg und meldete auch vorhandene Benutzernamen, fehlende Nonces, Fehler und Fehlschl\u00e4ge. Die Meldung enthielt Status, Zugangsdaten, Website-Origin, Logout-URL und aktuelle Seiten-URL; <code>navigator.sendBeacon<\/code> diente als erster \u00dcbertragungsweg, ein <code>fetch()<\/code>-POST mit <code>no-cors<\/code> und <code>keepalive<\/code> als R\u00fcckfallweg.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Einordnung und Reichweite<\/h2>\n\n\n\n<p>Die C2-Domain wird denselben Akteuren zugeordnet, die in den vorangegangenen zwei Monaten auch hinter den Supply-Chain-Angriffen auf <a href=\"https:\/\/www.wordfence.com\/blog\/2026\/07\/wordfence-prism-detected-backdoored-wordpress-plugin-within-two-hours-of-it-being-introduced\/\">Advanced Responsive Video Embedder<\/a> und <a href=\"https:\/\/optinmonster.com\/security-incident-tampered-script-served-via-optinmonster-and-trustpulse\/#what-to-check-and-do\">OptinMonster<\/a> standen.<\/p>\n\n\n\n<p>Die Kampagne zielte auf breite, unauff\u00e4llige Admin-Persistenz und Remote Code Execution in sehr vielen WordPress-Umgebungen. Sie ben\u00f6tigte keinen direkten Zugriff auf die einzelnen Websites: Das Manipulieren eines Werbe-Feeds reichte aus, weil dessen Anzeigecode die XSS-Schwachstelle enthielt.<\/p>\n\n\n\n<p>Dass die b\u00f6sartigen JSON-Datens\u00e4tze und <code>x.js<\/code> direkt im Bucket des Anbieters lagen, weist auf einen schwerwiegenden vorgelagerten Kompromiss von Cloud-Storage-Zugangsdaten oder interner BdThemes-Infrastruktur hin.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kompromittierungsindikatoren pr\u00fcfen<\/h2>\n\n\n\n<p>Pr\u00fcfe Benutzerliste, Plugin-Verzeichnisse, Must-Use-Plugins und die Optionstabelle der Datenbank auf die folgenden Indikatoren. Die beiden manipulierten API-Endpoints waren bis zum 8. August 2026 wieder bereinigt, doch eine bereits erfolgte Kompromittierung bleibt dadurch bestehen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Externe Ressourcen<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Prim\u00e4re Payload: <code>ia-cdn[.]com\/fz\/w2.js<\/code><\/li>\n\n\n<li>C2-Beacon-Endpoint: <code>ia-cdn[.]com\/fz\/c<\/code><\/li>\n\n\n<li>Manipulierter Vendor-API-Endpoint, inzwischen bereinigt: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/api-data-all-records<\/code><\/li>\n\n\n<li>Manipulierter Vendor-API-Endpoint, inzwischen bereinigt: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/api-data-records<\/code><\/li>\n\n\n<li>Manipulierte Payload auf der Vendor-Infrastruktur, inzwischen bereinigt: <code>api[.]sigmative[.]io\/prod\/store\/api\/biggopti\/x.js<\/code><\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Dateisystem und Datenbank<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Webshell: <code>emer-run.php<\/code> mit MD5 <code>1024732009983dd5e54b4cf5593f04d4<\/code><\/li>\n\n\n<li>MU-Plugin f\u00fcr Magic Login: <code>class-wp-token-validate.php<\/code> mit MD5 <code>7719cd98a35ffad2771f26d1ceab7d27<\/code><\/li>\n\n\n<li>MU-Plugin f\u00fcr Tarnung: <code>class-wp-query-9d127ff3.php<\/code> oder ein \u00e4hnlich benanntes <code>class-wp-query-*.php<\/code>; MD5 <code>9aadc3e5c5242b273bd17c5bdc358845<\/code><\/li>\n\n\n<li>MU-Plugin mit Tarnbezeichnung \u201eHealth Check\u201c: <code>wp-cache-optimizer.php<\/code> mit MD5 <code>e450ae5bc4bfc0d960dded06a76bb8e9<\/code><\/li>\n\n\n<li>Datenbankoption <code>fz_emer_login_tokens<\/code>, die Magic-Login-Token speichert<\/li>\n\n\n<li>Datenbankoption <code>fz_emer_done_v1<\/code>, die eine abgeschlossene Kompromittierung markiert<\/li>\n\n\n<li>Konten mit E-Mail-Adressen der Domains <code>@wordpress.org<\/code> oder <code>@developer.wordpress.org<\/code><\/li>\n\n\n<li>Benutzernamen nach dem Muster <code>bd_<\/code> gefolgt von sechs alphanumerischen Zeichen<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Zeitlicher Ablauf<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>1. M\u00e4rz 2026:<\/strong> Biggopti-API-JavaScript wird in Prime Slider 4.1.9 aufgenommen, SVN-Revision <code>r3471891<\/code>. <code>display_id<\/code> flie\u00dft unmaskiert in ein <code>id<\/code>-Attribut; der API-Endpoint lautet <code>api-data-records<\/code>.<\/li>\n\n\n<li><strong>10. Mai 2026:<\/strong> Der Endpoint wechselt zu <code>api-data-all-records<\/code>. Ein <code>DOMParser<\/code>-Sanitizer kommt f\u00fcr das Feld <code>content<\/code> hinzu, das <code>id<\/code>-Attribut bleibt unmaskiert.<\/li>\n\n\n<li><strong>23. Juni 2026:<\/strong> Das Feld <code>start_date<\/code> der manipulierten API-Kampagne tr\u00e4gt diesen Zeitpunkt f\u00fcr den \u201eSummer Sale\u201c-Hinweis. Ab diesem Datum k\u00f6nnte die XSS fr\u00fchestens aktiv gewesen sein.<\/li>\n\n\n<li><strong>6. August 2026, 22:40 UTC:<\/strong> Letzte \u00c4nderung am manipulierten <code>api-data-records<\/code>.<\/li>\n\n\n<li><strong>7. August 2026, 09:11 UTC:<\/strong> Letzte \u00c4nderung am manipulierten <code>api-data-all-records<\/code>.<\/li>\n\n\n<li><strong>7. August 2026:<\/strong> Der Angriff wird in freier Wildbahn beobachtet und das Threat-Intelligence-Team erh\u00e4lt die Meldung.<\/li>\n\n\n<li><strong>7. August 2026:<\/strong> Das WordPress-Plugin-Verzeichnis schlie\u00dft die Plugins bis zum Abschluss der Pr\u00fcfung.<\/li>\n\n\n<li><strong>7. August 2026, 16:56 UTC:<\/strong> Untersuchungsartefakte werden gesichert.<\/li>\n\n\n<li><strong>8. August 2026:<\/strong> Beide API-Endpoints liefern wieder sauberes JSON.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Jetzt kontrollieren und bereinigen<\/h2>\n\n\n\n<p>Deaktiviere die betroffenen BdThemes-Plugins, solange sie geschlossen sind, und pr\u00fcfe anschlie\u00dfend alle Benutzerkonten, insbesondere versteckte oder verd\u00e4chtige Administratoren. Durchsuche <code>wp-content\/plugins<\/code>, das Verzeichnis <code>wp-content\/mu-plugins<\/code> sowie die Optionstabelle nach s\u00e4mtlichen genannten Dateien, Hashes und Optionsnamen.<\/p>\n\n\n\n<p>Behandle jeden Fund als vollst\u00e4ndige Website-Kompromittierung: entferne fremde Konten und Backdoors, pr\u00fcfe die Integrit\u00e4t der Installation und rotiere Zugangsdaten. Da die Plugin-Dateien auf dem Server unver\u00e4ndert bleiben konnten, reichen dateibasierte Integrit\u00e4tspr\u00fcfungen allein nicht aus; kontrolliere zwingend auch Datenbank und Must-Use-Plugins.<\/p>\n\n\n\n<p>F\u00fcr Wordfence Premium, Care, Response und zahlende Wordfence-CLI-Kunden standen Malware-Signaturen und WAF-Regeln zur Erkennung dieser Supply-Chain-Kompromittierung seit dem 7. August 2026 bereit. Kostenlose Wordfence- und Wordfence-CLI-Nutzer erhalten diese Signaturen und Regeln nach der \u00fcblichen Verz\u00f6gerung von 30 Tagen. Der Wordfence-Scanner und Wordfence CLI erkennen mit dem Premium-Signatursatz nach eigenen Angaben mehr als 99 Prozent der \u00fcber 4,4 Millionen bekannten Malware-Samples und Kompromittierungsindikatoren; Wordfence CLI kann auch auf Serverebene scannen, wenn WordPress nicht mehr funktionsf\u00e4hig ist.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Referenzen \/ Quellen<\/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\">Wordfence Prism Detected Backdoored WordPress Plugin Within Two Hours of It Being Introduced<\/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>Manipulierte JSON-Werbebanner kompromittierten mehrere BdThemes-Plugins ohne ge\u00e4nderte Plugin-Dateien. Pr\u00fcfe jetzt Benutzer, Must-Use-Plugins und Datenbankoptionen auf die IoCs.<\/p>\n","protected":false},"author":11,"featured_media":259,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[53,12,133,132,123],"class_list":["post-260","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sicherheit","tag-malware","tag-plugins","tag-supply-chain","tag-wordpress-sicherheit","tag-xss"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/posts\/260","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/comments?post=260"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/posts\/260\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/media\/259"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/media?parent=260"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/categories?post=260"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/de\/wp-json\/wp\/v2\/tags?post=260"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}