Brevo (Sendinblue) CDN Supply-Chain Attack — ClickFix Lures & the "Web Media Optimizer" WordPress Backdoor
Executive Summary
What happened. On 2026-09-14 an attacker used a long-lived Cloudflare API key with full account permissions — hardcoded in Brevo's application source code — to create a malicious Cloudflare Worker that rewrote content at the CDN edge for Brevo's own site and for JavaScript files (sdk-loader.js, the Brevo Conversations widget, and the Brevo forms script) embedded on customer websites. Sansec places the active malware-serving window at roughly 16:05-20:13 UTC; Brevo's own stated exposure window is 16:07-20:30 UTC. All attacker-controlled subdomains stopped resolving on 2026-09-15. Sansec estimates over 100,000 websites were affected because trust was inherited transitively through a simple <script> tag — no individual customer had to be compromised.
The payload had two branches. (1) Every visitor could be shown a fake "Cloudflare, verify you are human" page that used the ClickFix social-engineering technique: copy a command to the clipboard, then walk the victim through Win+R → paste → Enter to execute it via PowerShell or mshta. (2) On WordPress sites embedding an affected Brevo widget, if the visiting browser showed signs of being an authenticated WordPress administrator, the script instead attempted to silently install a plugin called "Web Media Optimizer" from an attacker-controlled CDN subdomain. That plugin behaves as a persistent backdoor: it hides itself from the WordPress admin plugin list, copies itself into the mu-plugins (must-use plugins) directory for persistence outside normal plugin management, carries a hardcoded authentication key that lets the attacker generate valid admin sessions without a password, and periodically polls for updated payload URLs.
Root cause. A long-lived Cloudflare API key with full account permissions was stored in Brevo's application source code and obtained by the attacker, letting them create Cloudflare Workers, routes, and DNS records across Brevo's zones without triggering the alerting a short-lived, narrowly-scoped token would have. Evidence (identical Last-Modified timestamps on rewritten assets, unified Cloudflare-DNS control of five Brevo apex domains) points to CDN-edge content rewriting rather than a breach of Brevo's origin servers — meaning file-integrity checks against the origin would not have caught this.
Relationship to the prior Sept 10 incident. Several sources describe a separate, earlier incident on 2026-09-10 in which attackers exploited a SAML SSO misconfiguration to access 138 Brevo customer accounts (including Trezor) and run phishing campaigns; Brevo's own status-page write-up confirms this SSO incident and its remediation. Whether the two incidents are connected is, per SecurityAffairs, a question Brevo had not answered as of the reporting cycle covered by this pack's sources — treat them as two related but distinct events; this pack's detections target the 2026-09-14 Cloudflare Worker / ClickFix / Web Media Optimizer incident.
Defender priority: This is a third-party script supply-chain exposure, not a bug in your own code. The two actionable planes are: (1) hunt your own endpoints and WordPress estate for the ClickFix execution chain and the Web Media Optimizer plugin using the queries and log hunts below, and (2) reduce the blast radius of the next compromised third-party script with Subresource Integrity (SRI) and a restrictive Content-Security-Policy on any page that embeds Brevo (or any third-party) JavaScript — see §12.
Source Review & Web Hunter Notes
| Tier | Source | Key finding | Carry fwd |
|---|---|---|---|
| 1 Vendor | Brevo status.brevo.com incident write-up | Brevo's own account of the SEPARATE 2026-09-10 SAML SSO incident (138 accounts, root cause = auth scope bug). No technical indicators for the 09-14 Cloudflare incident are in this write-up; Brevo's words on 09-14 are only available second-hand via direct quotation in SecurityAffairs. | partial (context only) |
| 2 Press | BleepingComputer — "Brevo supply-chain attack injected ClickFix scripts on customer sites" | Full IOC set: 4 attacker domains, cdn10.sendibt1.com/p/wm.zip, plugin name + SHA-256, root cause, affected properties, "not affected" list. | yes |
| 2 Research | Sansec — "Brevo supply chain attack hits 100k+ sites" | Minute-level timeline, injection mechanism (appended loader snippet), clean-vs-injected script hashes, C2 API path list, detection log signatures, remediation guidance ("search for POST to /wp-admin/update.php?action=upload-plugin"). | yes |
| 2 Press | SecurityWeek — "Brevo Supply Chain Attack Injects Malware Into 100,000 Websites" | Corroborates timeline, root cause, exposure window, affected pages, prior Sept 10 SSO incident context. | yes |
| 2 Press | SecurityAffairs — "Brevo Supply-Chain Attack Infected Over 100,000 Websites" | Direct quote of Brevo's own incident notice on root cause; mu-plugins persistence detail; notes the open question of whether the 09-10 and 09-14 incidents are linked. | yes |
| 3 Press | CyberInsider — "100,000+ WordPress sites infected via Brevo supply chain attack" | Corroborates cdn10.sendibt1.com, /p/wm.zip, f.js loader filename, timeline. | partial |
| 3 Press | IT-Connect.tech — "Brevo ClickFix Attack Hits WordPress Sites" | Corroborates cdn10.sendibt1.com, "Web Media Optimizer" plugin name, ClickFix Win+R/Ctrl+V instruction wording, timeline. | partial |
| 3 Press | CyberNews — "Brevo hack: 100,000+ websites serve malware for hours" (search-summary; direct fetch returned HTTP 403) | Corroborates timeline and affected properties narratively; no atomic IOC in this pack traces to this source alone. | partial (narrative only) |
Intel gaps / perishability: Of the atomic host indicators, only cdn10.sendibt1.com / /p/wm.zip / "Web Media Optimizer" are corroborated by two or more independently fetched sources. The four other attacker domains (glegchner.com, corralos.beer, yelahaye.surf, boiseno.club) and the plugin SHA-256 appear in only one saved snapshot (BleepingComputer) — per this pack's two-source rule for prevent/critical, they ship as detect-tier indicators, not blocklist-tier. All attacker infrastructure stopped resolving on 2026-09-15, so these are historical/retrospective hunting indicators, not a live blocking need — see §4 and §10. No published report recovered the actual "Web Media Optimizer" plugin source code, so its full capability set is described narratively by researchers, not independently verified by this pack's authors.
Hunt Brief & Attack Chain
Hunt hypotheses (fidelity-ordered)
| # | Hypothesis | MITRE | Telemetry | Conf |
|---|---|---|---|---|
| H1 | A Windows endpoint's explorer.exe spawns powershell.exe, mshta.exe, or cmd.exe with an encoded or remote-fetch command line shortly after Run-dialog activity — the ClickFix clipboard-paste-and-execute pattern. | T1204.004 / T1059.001 / T1218.005 | ProcessRollup2 | HIGH |
| H2 | A browser process (chrome.exe, msedge.exe, firefox.exe) directly spawns a script host or command interpreter — a browser-triggered ClickFix variant. | T1204.004 / T1059.001 | ProcessRollup2 | MED |
| H3 | An instrumented host issues a DNS query for one of the four attacker domains or an attacker-repurposed sendibt1.com subdomain. | T1071.001 | DnsRequest | HIGH |
| H4 | A script host (powershell.exe, curl.exe, bitsadmin.exe, certutil.exe) downloads a file referencing wm.zip or sendibt1.com. | T1105 / T1059.001 | ProcessRollup2 | HIGH |
| H5 | A monitored host writes a file matching the Web Media Optimizer plugin filename (wm.zip) or its SHA-256 hash to disk. | T1505.003 | ZipFileWritten / PeFileWritten | HIGH |
| H6 | A file write lands inside a WordPress wp-content/mu-plugins path — the plugin's persistence mechanism — on a web-server host with Falcon coverage. ⚠ validate in tenant | T1505.003 | PeFileWritten | MED |
| H7 | Native WordPress/web-server access logs show a POST to /wp-admin/update.php?action=upload-plugin followed by a GET to /wp-admin/plugins.php?action=activate on 2026-09-14 — off-sensor for Falcon, the highest-fidelity WordPress-side signal per Sansec. | T1505.003 | Native web/access log | HIGH |
Attack chain
| Step | Action | Telemetry / hunt angle |
|---|---|---|
| 1 · Initial access (T1552.001) | Attacker obtains a long-lived, full-permission Cloudflare API key hardcoded in Brevo's own application source code. | Off-sensor — vendor-side credential exposure. Root-cause lesson for §12. |
| 2 · Infrastructure abuse (T1584 / T1195.002) | Attacker creates a malicious Cloudflare Worker + supporting routes/DNS records to rewrite content at the CDN edge for Brevo's own domains and embedded scripts. | Off-sensor — Cloudflare account activity, not EDR-visible. |
| 3 · Delivery (T1195.002) | Rewritten sdk-loader.js / brevo-conversations.js / forms script append a loader that pulls f.js from an attacker *.sendibt1.com subdomain, on every page that embeds the affected Brevo widget. | DNS/network egress from the visitor's browser process. H3. |
| 4a · Visitor branch — ClickFix (T1204.004) | Regular visitors see a fake "verify you are human" page instructing them to paste a clipboard command into Win+R. | ProcessRollup2: explorer.exe → powershell/mshta/cmd with suspicious CommandLine. H1/H2. |
| 4b · Admin branch — plugin backdoor (T1505.003) | If the visiting session looks like a logged-in WordPress admin, the script instead fetches wm.zip ("Web Media Optimizer") from cdn10.sendibt1.com/p/wm.zip and attempts silent plugin installation. | Native web log: POST to /wp-admin/update.php?action=upload-plugin. Falcon (if sensor on the web host): ZipFileWritten/PeFileWritten. H4/H5/H7. |
| 5 · Persistence (T1505.003) | Plugin hides from the WordPress plugin list and copies itself into wp-content/mu-plugins, which WordPress auto-loads without appearing as a manageable plugin. | File write into mu-plugins path. H6. Filesystem-vs-admin-panel plugin count mismatch. H7. |
| 6 · Command & control (T1071.001 / T1102) | Plugin carries a hardcoded auth key for attacker-generated admin sessions and periodically polls for updated payload URLs from its C2. | Periodic outbound connections from the web host; recurring admin-session creation with no matching interactive login. |
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| Domain | cdn10.sendibt1.com | high | prevent | Hosted the "Web Media Optimizer" plugin archive at /p/wm.zip. Corroborated by 4 independent sources (BleepingComputer, Sansec, CyberInsider, IT-Connect). Attacker-controlled subdomain of a legitimate Brevo apex domain; safe to block — Brevo revoked/cleaned this after 2026-09-15. |
| URL | https://cdn10.sendibt1.com/p/wm.zip | high | prevent | Malicious WordPress plugin archive download. 2+ independent sources. |
| Domain | glegchner.com | medium | detect | Web Media Optimizer C2 (/ads.php). Single-sourced (BleepingComputer only) — ships detect-only per two-source rule for prevent/critical. |
| Domain | corralos.beer | medium | detect | ClickFix lure delivery (/a412dkoq.js). Single-sourced (BleepingComputer). |
| Domain | yelahaye.surf | medium | detect | Associated malicious domain per BleepingComputer's IOC set. Single-sourced. |
| Domain | boiseno.club | medium | detect | Associated malicious domain per BleepingComputer's IOC set. Single-sourced. |
| SHA-256 | f359ab0d2f732b54dd3300065f4d6553f4df1b67454b71fd81197e26f02af4a8 | medium | detect | "Web Media Optimizer" plugin archive hash (VirusTotal, per BleepingComputer). Single-sourced — ships detect-only per two-source rule. |
| Domain | cdn.sendibt1.com / cdn2 / cdn3 / cdn4 / cdn9 / cdn11.sendibt1.com | medium | detect | Additional attacker-repurposed CDN subdomains used to serve the rewritten loader/f.js. Single-sourced (Sansec). |
| Filename | wm.zip | medium | detect | Generic filename — pair with the hash or full URL for fidelity; do not block on filename alone. |
| Artifact (plugin name) | "Web Media Optimizer" | high | hunt | Named in 3 independent sources (BleepingComputer, SecurityAffairs, IT-Connect). Not a network-blockable IOC — audit for its presence in the WP plugin directory and mu-plugins. |
| Behavioral | Injected loader snippet appended to sdk-loader.js / brevo-conversations.js that dynamically creates a <script> tag pointing at an attacker *.sendibt1.com subdomain | high | detect | Sansec. See §10 Script Integrity Reference for clean-vs-injected hash comparisons. |
Deliberately excluded from this table: the Cloudflare-anycast IPs reported for some *.sendibt1.com records (e.g. in the 104.21.x.x and 188.114.x.x ranges). Those are shared Cloudflare edge addresses used by millions of unrelated sites — blocking or alerting on them produces overwhelming false positives and provides no attribution value once the DNS records themselves are gone. Hunt on the domain names and the plugin artifact, not the shared IP space behind Cloudflare's proxy.
Affected Surface & Telemetry Matrix
| Surface | Required telemetry | Priority | Gap risk |
|---|---|---|---|
| Windows endpoints of anyone who browsed an affected site 2026-09-14 16:00-21:00 UTC | ProcessRollup2 / SyntheticProcessRollup2, DnsRequest | Critical | Low — standard Falcon sensor coverage |
| WordPress hosts embedding a Brevo forms/chat/SDK snippet, where the logged-in admin visited the site that day | ZipFileWritten / PeFileWritten (if Falcon-instrumented), native web/access logs (always) | Critical | High — most WordPress hosting is not Falcon-instrumented; native log hunting (§7) is the primary detection here |
| Web-server / hosting infrastructure behind those WordPress sites | Native access/error logs, file-integrity monitoring on wp-content | High | Medium — depends on hosting provider log retention |
| Browsers (all, regardless of OS) rendering the ClickFix overlay | Browser process telemetry (Windows-only for the documented PowerShell/mshta execution path); no equivalent macOS/Linux execution primitive is documented in these sources | High | Medium — ClickFix as documented here targets Windows clipboard-to-Run; non-Windows visitor impact is a documented gap, not confirmed absent |
Coverage reality: the highest-fidelity WordPress-side signal (H7 — the admin plugin-upload POST) lives in native web/access logs, not Falcon telemetry, unless the web server itself runs a Falcon sensor with file-write monitoring enabled for PHP/zip writes under wp-content — validate this in your tenant before relying on Q5/Q6 as your only WordPress detection.
ATT&CK Mapping
| Tactic | Technique | Observed behavior | Query / control |
|---|---|---|---|
| Resource Development | T1584 Compromise Infrastructure | Malicious Cloudflare Worker + routes/DNS created using the stolen API key | Off-sensor; §12 credential hygiene |
| Initial Access / Credential Access | T1552.001 Unsecured Credentials: Credentials in Files | Long-lived full-permission Cloudflare API key hardcoded in application source code | Off-sensor (vendor-side); §12 secret-scanning + scoped tokens |
| Initial Access | T1195.002 Supply Chain Compromise: Software Supply Chain | CDN-edge rewrite of trusted third-party JavaScript served to 100,000+ downstream sites | §12 SRI / CSP |
| Execution / User Execution | T1204.004 Malicious Copy and Paste (ClickFix) | Fake "verify you are human" overlay instructs victim to paste and run a clipboard command | Q1, Q2, Q3 |
| Execution | T1059.001 Command and Scripting Interpreter: PowerShell | PowerShell invoked from Run dialog / browser with encoded or remote-fetch command line | Q2, Q3, Q4 |
| Execution | T1218.005 System Binary Proxy Execution: Mshta | mshta.exe used as an alternate ClickFix execution vector | Q2, Q3 |
| Command & Control | T1071.001 Application Layer Protocol: Web Protocols | DNS/HTTP to attacker domains and C2 API paths | Q1 |
| Command & Control | T1105 Ingress Tool Transfer | Script host downloads wm.zip from attacker CDN | Q4 |
| Persistence | T1505.003 Server Software Component: Web Shell | "Web Media Optimizer" plugin: hides from plugin list, persists via mu-plugins, hardcoded backdoor auth key | Q5, Q6, native H7 |
Native Audit-Log Hunts (non-CQL)
The single highest-fidelity WordPress-side signal for this campaign lives in your web server / WAF access logs, not EDR. Run these on every WordPress host that embeds a Brevo forms, Conversations, or SDK-loader snippet.
On the WordPress web/access log
- Plugin upload: search 2026-09-14 (and a few days either side, given the "late August" key-theft window) for a
POSTto/wp-admin/update.php?action=upload-plugin. - Plugin activation: a
GETto/wp-admin/plugins.php?action=activateshortly after that POST is the confirming second half of the signature (per Sansec's published remediation guidance). - Hidden-plugin check: list the contents of
wp-content/plugins/andwp-content/mu-plugins/on disk (SSH/SFTP/hosting file manager) and diff against what the WordPress admin "Plugins" screen shows. Web Media Optimizer is designed to hide from that screen — a plugin present on disk but absent from the admin list is the tell. - Injected-script check: inspect served HTML/JS for
script[src*="file.js"](a commonly reported default loader filename in this campaign family) or ascripttag carrying adata-cattribute — both reported as injection artifacts. - Script hash check: compute SHA-256 of the embedded
sdk-loader.js/brevo-conversations.jsas served to visitors and compare against the clean vs. injected hashes in §10's Script Integrity Reference.
On the WordPress admin session / auth log
- Review admin login activity around 2026-09-14 16:00-21:00 UTC for sessions with no corresponding interactive login event — a symptom of the plugin's hardcoded backdoor auth key generating sessions without credentials.
- Force a credential reset and session invalidation for any admin account active on an affected site during the exposure window, out of caution, even without confirmed compromise.
On the endpoint (non-Falcon fallback — AV/EDR-agnostic)
- Check clipboard history / recent Run-dialog (Win+R) MRU entries for base64 or URL-bearing strings on machines whose users browsed an affected site during the window.
- Per Sansec's guidance: anyone who followed the ClickFix instructions and executed the pasted command should run a full anti-virus/EDR scan immediately, not wait for a hunt cycle.
CrowdStrike LogScale CQL Hunt Queries
All attacker domains stopped resolving 2026-09-15 — these are retrospective hunts against the 2026-09-14 window and general-purpose detections for the ClickFix/backdoor-plugin technique class going forward, not a live-blocking need.
Looks for: any instrumented host resolving one of the four attacker domains or an attacker-repurposed sendibt1.com subdomain. FP: very low — these are not shared/legitimate hosting domains, just retired campaign infrastructure.
// HUNT: DNS resolution to Brevo ClickFix / Web Media Optimizer attacker infrastructure // MITRE: T1071.001 | CONF: high FP: low COST: low | REQUIRES: DnsRequest #event_simpleName=/^DnsRequest$/ | DomainName=/^(glegchner\.com|corralos\.beer|yelahaye\.surf|boiseno\.club|cdn10\.sendibt1\.com|cdn\.sendibt1\.com|cdn2\.sendibt1\.com|cdn3\.sendibt1\.com|cdn4\.sendibt1\.com|cdn9\.sendibt1\.com|cdn11\.sendibt1\.com)$/i | table([ComputerName, aid, UserName, DomainName], limit=200)
Looks for: the canonical ClickFix pattern — a user pastes a command into the Win+R Run dialog, so explorer.exe is the direct parent of powershell.exe, mshta.exe, or cmd.exe, carrying an encoded, hidden-window, or remote-fetch command line. FP: some IT helpdesk/RMM tools and support scripts legitimately launch PowerShell this way — baseline against your fleet before promoting to Detect.
// HUNT: ClickFix clipboard-to-Run-dialog execution chain // MITRE: T1204.004 / T1059.001 / T1218.005 | CONF: high FP: medium COST: low | REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // TUNING: exclude known signed IT helpdesk / RMM tools that legitimately spawn PowerShell from explorer.exe on your fleet #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ParentBaseFileName=/^explorer\.exe$/i | FileName=/^(powershell|powershell_ise|mshta|cmd)\.exe$/i | CommandLine=/(-enc|-e |-en |-w hidden|-windowstyle hidden|frombase64string|iex|invoke-expression|http(s)?:\/\/)/i | table([ComputerName, aid, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Looks for: a browser process directly spawning a script host or command interpreter — covers ClickFix variants that trigger execution without a visible Run-dialog step. FP: browser updaters, native messaging hosts, and some extensions legitimately spawn helper processes; validate your ParentBaseFileName/FileName pairs against known-good browser child processes before promoting.
// HUNT: Browser process spawning script host / command interpreter // MITRE: T1204.004 / T1059.001 / T1218.005 | CONF: medium FP: medium COST: low | REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // TUNING: exclude signed browser updater/helper binaries and native-messaging hosts observed in your environment #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ParentBaseFileName=/^(chrome|msedge|firefox|iexplore)\.exe$/i | FileName=/^(powershell|mshta|cmd|wscript|cscript)\.exe$/i | table([ComputerName, aid, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Looks for: PowerShell or a common LOLBin downloader fetching wm.zip or referencing sendibt1.com in its command line. FP: low — these strings are campaign-specific.
// HUNT: Script-host download of the Web Media Optimizer plugin archive (wm.zip) // MITRE: T1105 / T1059.001 | CONF: high FP: low COST: low | REQUIRES: ProcessRollup2, SyntheticProcessRollup2 #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^(powershell|curl|bitsadmin|certutil)\.exe$/i | CommandLine=/(wm\.zip|sendibt1\.com|cdn10\.sendibt1)/i | table([ComputerName, aid, UserName, FileName, CommandLine], limit=200)
Looks for: a file write matching the plugin archive's filename or its published SHA-256. FP: low for the hash match; the filename alone (wm.zip) is generic, so treat a filename-only hit as lower fidelity than a hash hit. Coverage note: this fires only on hosts with a Falcon sensor and file-write visibility — most WordPress hosting is not Falcon-instrumented; §7's native log hunt is the primary WordPress-side detection.
// HUNT: Web Media Optimizer malicious plugin archive written to disk // MITRE: T1505.003 | CONF: high FP: low COST: low | REQUIRES: ZipFileWritten, PeFileWritten #event_simpleName=/^(ZipFileWritten|PeFileWritten)$/ | FileName=/^wm\.zip$/i OR SHA256HashData=/^f359ab0d2f732b54dd3300065f4d6553f4df1b67454b71fd81197e26f02af4a8$/i | table([ComputerName, aid, UserName, FileName, FilePath, SHA256HashData], limit=200)
Looks for: any file write into a wp-content/mu-plugins path — the plugin's documented persistence mechanism. ⚠ validate in tenant — file-write event coverage for PHP content on Linux-hosted WordPress varies by sensor configuration; this is far more reliable on a Windows-hosted CMS. FP: legitimate must-use plugins and managed-hosting platform files also live here — baseline your known-good mu-plugins writers first.
// HUNT: File write into WordPress mu-plugins directory (Web Media Optimizer persistence) // MITRE: T1505.003 | CONF: medium FP: medium COST: low | REQUIRES: PeFileWritten ⚠ validate in tenant — Linux/PHP file-write coverage varies by sensor config // TUNING: exclude known-good managed-hosting platform writers and legitimate must-use plugin deployment processes on your fleet #event_simpleName=/^PeFileWritten$/ | FilePath=/wp-content[\\\/]mu-plugins/i | table([ComputerName, aid, UserName, FileName, FilePath], limit=200)
Custom IOA Recommendations
| IOA name | Pattern | Exclusions | Path |
|---|---|---|---|
| ClickFix Run-Dialog Execution | explorer.exe → powershell/mshta/cmd with encoded/hidden-window/remote-fetch CommandLine | Signed IT helpdesk/RMM tools baselined per-fleet | Investigate → Detect after baseline (Q2) |
| Brevo Campaign DNS Resolution | DnsRequest to any of the 11 listed attacker/repurposed domains | None expected — retired campaign infra only | Detect immediately (Q1) |
| Web Media Optimizer Artifact Drop | ZipFileWritten/PeFileWritten matching filename wm.zip or the published SHA-256 | None for the hash match; filename-only hits reviewed manually | Detect immediately (Q5) |
| Browser-Spawned Shell (ClickFix variant) | chrome/msedge/firefox → powershell/mshta/cmd/wscript/cscript | Signed browser updater/helper binaries, native messaging hosts | Investigate-only (Q3) |
The highest-fidelity WordPress-side detection (native H7 — the admin plugin-upload POST) belongs in your web server/WAF log pipeline, not a Falcon IOA — most WordPress hosting never reports to the Falcon sensor.
Machine-Readable IOC Appendix
type,value,action,severity,expiration,description,tags domain,cdn10.sendibt1.com,prevent,critical,2026-12-20,Brevo ClickFix attack -- attacker-controlled CDN subdomain hosting the Web Media Optimizer malicious WordPress plugin archive; 2+ independent sources,campaign:brevo-clickfix-2026-09 url,https://cdn10.sendibt1.com/p/wm.zip,prevent,critical,2026-12-20,Brevo ClickFix attack -- malicious WordPress plugin archive download URL; 2+ independent sources,campaign:brevo-clickfix-2026-09 domain,glegchner.com,detect,high,2026-12-20,Brevo ClickFix attack -- Web Media Optimizer plugin C2 (/ads.php); single-sourced (BleepingComputer) -- detect only per two-source rule,campaign:brevo-clickfix-2026-09 domain,corralos.beer,detect,high,2026-12-20,Brevo ClickFix attack -- ClickFix lure delivery (/a412dkoq.js); single-sourced (BleepingComputer),campaign:brevo-clickfix-2026-09 domain,yelahaye.surf,detect,medium,2026-12-20,Brevo ClickFix attack -- associated malicious domain; single-sourced (BleepingComputer),campaign:brevo-clickfix-2026-09 domain,boiseno.club,detect,medium,2026-12-20,Brevo ClickFix attack -- associated malicious domain; single-sourced (BleepingComputer),campaign:brevo-clickfix-2026-09 sha256,f359ab0d2f732b54dd3300065f4d6553f4df1b67454b71fd81197e26f02af4a8,detect,high,2026-12-20,Brevo ClickFix attack -- Web Media Optimizer malicious WordPress plugin archive hash (VirusTotal); single-sourced -- detect only per two-source rule,campaign:brevo-clickfix-2026-09 domain,cdn.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 domain,cdn2.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 domain,cdn3.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 domain,cdn4.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 domain,cdn9.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 domain,cdn11.sendibt1.com,detect,medium,2026-12-20,Brevo ClickFix attack -- attacker-repurposed CDN subdomain; single-sourced (Sansec),campaign:brevo-clickfix-2026-09 filename,wm.zip,detect,medium,2026-12-20,Brevo ClickFix attack -- malicious WordPress plugin archive filename; generic, pair with hash/URL for fidelity,campaign:brevo-clickfix-2026-09
# C2 / loader API paths reported by Sansec (relative to attacker malware hosts;
# single-sourced -- hunt/enrich only, do not block on generic paths alone):
# /f.js - main loader
# /api/v1/0044d4a - fingerprint submission (POST)
# /api/v1/e08a3c4 - proof-of-work token request
# /api/v1/8e4c615 - fingerprint submission variant
# /api/v1/f659473 - token request variant
# /api/v1/4aff112?tk= - clipboard command delivery
# /api/v1/b832c14?e= - event beacon (click, copy, fallback, failure, close)
# /api/v1/4ead0ff?tk= - image beacon
# /image.php?tk= - image beacon variant
# C2 "cloak" response -- identical body returned to non-victims/crawlers/scanners:
# response hash: 4af488d79aef7daa12b1c18f0cce28b7edadccb8b6b0fb8d50d1d53a9a7c2df7
# body: {"s":0,"r":"https:\/\/www.google.com"}
# Injection artifacts in served HTML/JS:
# script[src*="file.js"] - commonly reported default loader filename
# script[data-c] - custom attribute set by the injection
# Search access logs for 2026-09-14 (plus a few days either side): # POST /wp-admin/update.php?action=upload-plugin # GET /wp-admin/plugins.php?action=activate (shortly after the POST) # Filesystem-vs-admin-panel mismatch check: # ls -la wp-content/plugins/ wp-content/mu-plugins/ # # compare against what wp-admin/plugins.php actually lists -- # # Web Media Optimizer is designed to hide from that screen # Injected-script detection in served pages: # grep -r 'script\[src\*="file.js"\]' . # or view-source for the pattern # grep -r 'data-c=' .
# Per Sansec. Informational / enrichment only -- NOT for blocking (these are # tampered variants of Brevo's own legitimate scripts, already offline since # 2026-09-15). Use to verify your embedded scripts weren't served a tampered # variant during the exposure window, and as SRI reference hashes going forward. # # CLEAN (legitimate): # sdk-loader.js fe8447fd1ec4dca652b71db2c749fcc24a5bec3875f3654042169fb2418aed09 # brevo-conversations.js 26166cd87ff07e7a50317a24126d14b262e842c5715585636dee3ab3f227ddca # # INJECTED VARIANTS observed during the 2026-09-14 exposure window: # sdk-loader.js (-> cdn2) 58a5c601c9df7ca2120435588fc39f97712d9b878795f6ee500590099a432308 # sdk-loader.js (-> cdn11) f67d572d2d30407b3f470904326411450763108980cdad89550fbb221fb06782 # brevo-conversations.js (-> cdn4) 9b62c12bc5c7feb9802f58e6cf75a368690df3c754e37cc64483a92acacf87a5
Detection Validation Gates
| Gate | Check | Pass criterion |
|---|---|---|
| Telemetry ready | ProcessRollup2/SyntheticProcessRollup2 and DnsRequest flowing from endpoint fleet; PeFileWritten/ZipFileWritten confirmed present (or absent, and documented) on any Falcon-instrumented web hosts | Events queryable in Falcon within last 24h |
| Benign baseline | Run Q2/Q3/Q6 against 7-30 days of history before promoting to Detect | Known-good exclusions identified and added via TUNING notes |
| WordPress log access confirmed | Confirm access to web server/WAF logs covering 2026-09-14 for every WordPress host embedding a Brevo snippet | Logs retained and searchable for the exposure window |
| Script integrity check run | Compare live embedded Brevo script hashes against §10 Script Integrity Reference | No match to a listed injected-variant hash |
| Positive test | In a lab, replicate the explorer.exe → powershell.exe chain with a benign encoded command; confirm Q2 fires | Query returns the test event |
Hardening — Tiered & Deployable
- Security awareness: ClickFix-specific warning. No legitimate site or CAPTCHA will ever ask a user to open Win+R and paste/run a command. This single message closes the highest-volume branch of this attack (the visitor overlay). MITRE M1017 (User Training).
- Block
mshta.exeexecution via AppLocker/WDAC on endpoints that have no legitimate business need for it (most do not). Removes one of the two documented ClickFix execution vectors outright. MITRE M1038 (Execution Prevention). - Deploy Q1/Q2/Q4/Q5 as Detect and run the §7 WordPress log hunts against 2026-09-14 access logs on every host embedding a Brevo snippet, immediately.
- Enable PowerShell Script Block Logging + Constrained Language Mode for non-admin, non-signed scripts, so an encoded ClickFix payload is both logged and constrained even if it runs. MITRE M1040 (Behavior Prevention on Endpoint) / M1042.
- WordPress hardening: enforce MFA on
wp-admin, restrict access to/wp-admin/update.phpand/wp-admin/plugins.phpby source IP/VPN at the WAF, and deploy file-integrity monitoring onwp-content/pluginsandwp-content/mu-pluginsso an unauthorized plugin write alerts even without EDR on the host. MITRE M1032 (Multi-factor Authentication) / M1047 (Audit) / M1022 (Restrict File and Directory Permissions). - Third-party script containment — Content-Security-Policy. Set a
script-src/connect-srcallowlist on every page embedding third-party JavaScript (Brevo or otherwise), so that if a trusted CDN is tampered with again, the browser itself blocks the injected script from loading new hosts or beaconing to unlisted domains. ⚠ best-practice, no formal CIS/vendor benchmark covers this specific supply-chain scenario — grounded in the W3C CSP specification and standard defense-in-depth practice, not a named framework control.
- Subresource Integrity (SRI) on embedded third-party scripts where the vendor supports versioned/immutable script URLs — pins the exact byte content expected, so a CDN-edge rewrite (exactly this attack) causes the browser to refuse the script rather than execute it. ⚠ best-practice, no formal benchmark — W3C SRI spec. Requires coordination with any vendor (Brevo or otherwise) whose script URL is not a stable, hashable asset.
- Vendor / third-party script risk management: stand up automated monitoring that diffs and hashes every third-party script your sites embed on a recurring basis, alerting on any change outside a known release cadence. MITRE M1047 (Audit) as applied to supply-chain surface.
- If you manage your own Cloudflare (or any CDN) API credentials: replace any long-lived, full-permission Global API Key with narrowly-scoped, short-lived Cloudflare API Tokens; never hardcode them in application source — use a secrets manager, and run repository secret-scanning to catch the exact root-cause pattern that enabled this campaign. MITRE M1047 (Audit) / general credential-hygiene best practice for T1552.001.
Deployable Playbooks
Playbook A — Windows: block mshta.exe and harden PowerShell against ClickFix (AppLocker + registry)
MITRE: T1204.004 / T1218.005 / T1059.001 → M1038, M1040, M1042 | Estimated deploy time: 1-2 hours (Immediate tier), 1 pilot ring for Constrained Language Mode | Prerequisites: Windows 10/11 or Server 2016+, Group Policy or Intune management, local admin on target endpoints | Reboot required: No (AppLocker/registry changes apply on next policy refresh or PowerShell session; no reboot needed)
# Step 1 -- AppLocker deny rule for mshta.exe (GPO path shown; PowerShell equivalent below) # GPO path: Computer Configuration > Windows Settings > Security Settings > # Application Control Policies > AppLocker > Executable Rules # Add a Deny rule: Path = %SYSTEM32%\mshta.exe, applied to Everyone # PowerShell equivalent (local testing before GPO rollout): New-AppLockerPolicy -RuleType Path -User Everyone -Action Deny ` -Path "%SYSTEM32%\mshta.exe" -XMLPolicy | Set-AppLockerPolicy -Merge # Verify: Get-AppLockerPolicy -Effective -Xml | Select-String "mshta" # Rollback: # Remove the Deny rule from the linked GPO (or the local policy) and run: gpupdate /force # No reboot required; AppLocker re-evaluates on next process launch after policy refresh.
# Step 2 -- Enable PowerShell Script Block Logging (visibility even if execution isn't blocked) $path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' New-Item -Path $path -Force | Out-Null New-ItemProperty -Path $path -Name 'EnableScriptBlockLogging' -Value 1 -PropertyType DWORD -Force | Out-Null Write-Output "PowerShell Script Block Logging enabled." # Verify: (Get-ItemProperty $path -Name EnableScriptBlockLogging -EA SilentlyContinue).EnableScriptBlockLogging # Expect: 1 # Rollback: Remove-ItemProperty -Path $path -Name 'EnableScriptBlockLogging' -EA SilentlyContinue # No reboot required; takes effect for new PowerShell sessions.
Compatibility note: pilot the mshta.exe deny rule on a small ring first — a small number of legacy line-of-business HTA-based tools may depend on it. Search Event ID 8004 (AppLocker) for blocked launches during pilot.
Playbook B — WordPress: lock down plugin installation and monitor mu-plugins (shell / WP-CLI)
MITRE: T1505.003 → M1022, M1032, M1047 | Estimated deploy time: 2-4 hours | Prerequisites: SSH/SFTP or hosting-panel file access, WP-CLI installed, ability to edit wp-config.php and web-server config | Reboot required: No
# Step 1 -- Audit current state: disk vs. admin-panel plugin list
wp plugin list --path=/var/www/html
ls -la /var/www/html/wp-content/plugins/ /var/www/html/wp-content/mu-plugins/
# Any plugin present on disk but NOT in the `wp plugin list` output is a hiding-plugin candidate -- investigate before proceeding.
# Step 2 -- Disable in-dashboard plugin/theme installation and file editing
# Add to wp-config.php (before "That's all, stop editing!"):
# define('DISALLOW_FILE_MODS', true); // blocks plugin/theme install+update+edit from wp-admin
# NOTE: this also blocks LEGITIMATE plugin updates from the dashboard -- pair with a
# controlled update process (WP-CLI, staging-then-deploy, or a managed host's own pipeline).
# Step 3 -- File-integrity baseline for wp-content
find /var/www/html/wp-content -type f \( -name "*.php" -o -name "*.zip" \) -exec sha256sum {} \; > /var/backups/wp-content-baseline-$(date +%F).sha256
# Step 4 -- Recurring integrity check (cron, e.g. daily)
sha256sum -c /var/backups/wp-content-baseline-$(date +%F).sha256 2>&1 | grep -v ": OK"
# Any FAILED or new/missing file warrants investigation.
# Verify Step 2:
grep DISALLOW_FILE_MODS /var/www/html/wp-config.php
# Expect: define('DISALLOW_FILE_MODS', true);
# Rollback:
# Remove (or set to false) the DISALLOW_FILE_MODS line in wp-config.php to restore
# dashboard-based plugin management. No service restart required.
Playbook C — Any site embedding third-party JavaScript: CSP + SRI containment
MITRE: T1195.002 → best-practice (W3C CSP/SRI specs; no single CIS control covers third-party-script supply chain) | Estimated deploy time: 2-6 hours plus a monitoring period for CSP report-only tuning | Prerequisites: ability to edit site HTTP response headers or HTML <head>; an inventory of every third-party script domain the site legitimately loads | Reboot required: No (web server / CDN config reload only)
# Step 1 -- Ship CSP in Report-Only mode first to avoid breaking legitimate embeds # HTTP response header (nginx example): add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https://sibforms.com https://cdn.brevo.com; connect-src 'self' https://cdn.brevo.com; report-uri /csp-violations;" always; # Step 2 -- After a monitoring period with no unexpected legitimate violations, enforce it: add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://sibforms.com https://cdn.brevo.com; connect-src 'self' https://cdn.brevo.com;" always; # Any future attempt by a tampered/injected script to load a NEW attacker domain (e.g. a # repeat of *.sendibt1.com-style abuse or the four ClickFix domains in this pack) is blocked # by the browser itself, even though the script content changed at the CDN edge. # Step 3 -- Where the vendor serves an immutable/versioned script URL, pin it with SRI: # <script src="https://cdn.brevo.com/js/sdk-loader.js" # integrity="sha256-BASE64_OF_KNOWN_GOOD_HASH" # crossorigin="anonymous"></script> # NOTE: SRI requires the vendor to serve a byte-stable script at that URL; if the vendor # rotates content at that same URL for legitimate reasons, SRI will break the embed -- # validate with the vendor before enforcing. # Verify: curl -sI https://your-site.example.com/ | grep -i content-security-policy # Rollback: # Remove the add_header line (or revert to Report-Only) and reload the web server: nginx -t && systemctl reload nginx
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Falcon-contain any endpoint flagged by Q1/Q2/Q3/Q4; take any WordPress host with a confirmed Web Media Optimizer plugin off the public network or place behind maintenance mode pending eradication. | SOC + Web/IT Ops | Containment IDs, host list from Q1-Q6 |
| Eradicate | Remove the plugin from both wp-content/plugins and wp-content/mu-plugins (check both — it hides from the admin list but not the filesystem); force-reset all WordPress admin credentials and invalidate sessions for any account active during 2026-09-14 16:00-21:00 UTC; on Windows endpoints, run a full AV/EDR scan and review Run-dialog/clipboard history for anyone who browsed an affected site that day. | Web/IT Ops + IR | Removed-file list, credential-reset log, scan results |
| Recover | Restore plugin/theme state from a known-clean backup predating 2026-09-14 where available; re-enable dashboard plugin management only after DISALLOW_FILE_MODS-gated review; verify embedded Brevo (or other third-party) script hashes against §10's clean references before re-enabling normal operation. | Web/IT Ops | Restore logs, script-hash verification record |
| Post-incident | Deploy CSP/SRI (Playbook C) on all sites embedding third-party scripts; enable file-integrity monitoring on wp-content fleet-wide; if your organization manages its own Cloudflare/CDN API credentials, audit for hardcoded long-lived keys and rotate to scoped tokens (root-cause lesson from this campaign). | SecEng + Web/IT Ops | CSP header rollout record, FIM coverage report, credential-rotation log |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1584 / T1552.001 | Stolen Cloudflare API key, malicious Worker creation | — | — | GAP (vendor-side, off-sensor) |
| T1071.001 | DNS resolution to attacker/repurposed domains | Q1 | Brevo Campaign DNS Resolution | Good |
| T1204.004 / T1059.001 / T1218.005 | ClickFix clipboard-to-Run execution (explorer.exe path) | Q2 | ClickFix Run-Dialog Execution | Good |
| T1204.004 / T1059.001 | ClickFix browser-triggered variant | Q3 | Browser-Spawned Shell | Partial |
| T1105 | wm.zip download via script host | Q4 | — | Good |
| T1505.003 | Plugin archive written to disk (hash/filename) | Q5 | Web Media Optimizer Artifact Drop | Partial (Falcon-instrumented web hosts only) |
| T1505.003 | mu-plugins persistence write | Q6 | — | Partial — ⚠ validate in tenant |
| T1505.003 | Admin plugin-upload POST / activation GET (native web log) | — | — | GAP (off-sensor; native log hunt §7 is primary) |
Known gaps: the root cause (stolen Cloudflare API key, malicious Worker) and the highest-fidelity WordPress-side signal (admin plugin-upload POST) are both off-sensor for Falcon — recoverable only from Cloudflare account audit logs and web-server access logs respectively. Closing the primary WordPress gap means running §7's native log hunts on every site embedding a Brevo (or other third-party) snippet, not waiting on EDR coverage.
Validation: telemetry-ready and benign-baseline gates (§11) must pass before Q2/Q3/Q6 are promoted from Investigate to Detect.
Hunt Summary Ticket
TITLE: Brevo CDN Supply-Chain Attack — ClickFix Lures & Web Media Optimizer WordPress Backdoor
SEVERITY: High impact (~100,000 sites, per Sansec) / Critical for confirmed WP plugin installs
SCOPE: Windows endpoints of visitors to Brevo-embedding sites 2026-09-14 16:00-21:00 UTC;
WordPress hosts embedding Brevo forms/Conversations/SDK-loader scripts
HYPOTHESIS: Stolen Cloudflare API key -> malicious Worker rewrites trusted 3rd-party JS ->
ClickFix clipboard execution (visitors) + silent plugin backdoor (WP admins)
QUERIES: Q1 DNS-to-attacker-infra · Q2 ClickFix Run-dialog chain · Q3 browser-spawned shell ·
Q4 wm.zip download · Q5 plugin artifact drop (hash/filename) · Q6 mu-plugins write
DO FIRST: 1) Run §7 WordPress log hunts on every Brevo-embedding site for 2026-09-14
2) Deploy Q1/Q2/Q4/Q5 as Detect 3) Block mshta.exe via AppLocker (Playbook A)
4) Check wp-content/mu-plugins on disk vs. admin panel on every WP host
FINDINGS: <record DNS/process hits, plugin artifact matches, WP log signature hits>
GAPS: Root cause (stolen API key/Worker) and admin plugin-upload POST are off-sensor;
4 of 5 attacker domains + the plugin hash are single-sourced (detect-only, not prevent)
ACTIONS: Falcon-contain flagged hosts; force WP admin credential reset for exposure-window
sessions; deploy CSP/SRI (Playbook C) on all 3rd-party-script embeds
OWNER: <assign> VERSION: v0.1 · 2026-09-20
Changelog
cdn10.sendibt1.com and its /p/wm.zip URL are corroborated by 2+ independent snapshots and ship as prevent/critical; the four other attacker domains and the plugin SHA-256 are single-sourced (BleepingComputer only) and ship detect-only.References
| Tier | Source | Used for | Accessed |
|---|---|---|---|
| 1 Vendor | Brevo status.brevo.com incident write-up | Brevo's own account of the related Sept 10 SSO incident (context; no 09-14 technical indicators) | 2026-09-20 |
| 2 Press | BleepingComputer — Brevo supply-chain attack injected ClickFix scripts on customer sites | Full IOC set (4 domains, cdn10.sendibt1.com/wm.zip, plugin name + hash), root cause, affected properties | 2026-09-20 |
| 2 Research | Sansec — Brevo supply chain attack hits 100k+ sites with Wordpress backdoors and Clickfix malware | Minute-level timeline, injection mechanism, clean/injected script hashes, C2 API paths, WP log detection signature | 2026-09-20 |
| 2 Press | SecurityWeek — Brevo Supply Chain Attack Injects Malware Into 100,000 Websites | Timeline, root cause, scope corroboration | 2026-09-20 |
| 2 Press | SecurityAffairs — Brevo Supply-Chain Attack Infected Over 100,000 Websites | Direct quote of Brevo's incident notice; mu-plugins persistence detail; Sept 10/14 linkage question | 2026-09-20 |
| 3 Press | CyberInsider — 100,000+ WordPress sites infected via Brevo supply chain attack | Corroboration: cdn10.sendibt1.com, /p/wm.zip, f.js loader filename | 2026-09-20 |
| 3 Press | IT-Connect.tech — Brevo ClickFix Attack Hits WordPress Sites | Corroboration: cdn10.sendibt1.com, plugin name, ClickFix instruction wording | 2026-09-20 |
| 3 Press | CyberNews — Brevo hack: 100,000+ websites serve malware for hours (search-summary; direct fetch returned HTTP 403) | Narrative timeline/scope corroboration only | 2026-09-20 |