How BitFire Blocks CVE-2026-65437: CleanTalk Anti-Spam Stored XSS

WordPress 漏洞研究

BitFire's FREE WAF blocks the malicious request URIs behind CVE-2026-65437 before WordPress runs, keeping CleanTalk SpamFireWall die-page XSS from firing.

Unauthenticated CVSS 7.2 High Script execution on site origin Stored Cross-Site Scripting
BitFire·漏洞通报研究发表
咨询CVE-2026-65437
组件Anti-Spam by CleanTalk – Spam Protection Without CAPTCHA
相关来源lib/Cleantalk/ApbctWP/Firewall/SFW.php (diePage() placeholder substitution; same pattern in AntiFlood.php and AntiCrawler.php)
执行摘要

WordPress 管理员需要了解什么

CleanTalk Anti-Spam, installed on more than 200,000 WordPress sites, ships firewall interstitial pages that echo the raw request URI without output escaping. In versions 6.82 and earlier, a denied or test request whose target carries HTML metacharacters has that target substituted straight into a single-quoted href attribute, letting attacker script execute on your site's origin. The same attacker-controlled URL and User-Agent are persisted in the plugin's firewall log table. Fixed in 6.83. BitFire's FREE WAF stops the attack earlier: it inspects the request target before WordPress boots and blocks requests carrying XSS payloads, so the poisoned interstitial is never rendered.

一目了然

主要事实

  • No login, nonce, or capability check guards the firewall check; it runs for anonymous visitors on every front-end request.
  • Raw $_SERVER['REQUEST_URI'] is substituted into the SpamFireWall, Anti-Flood, and Anti-Crawler die pages with no escaping in 6.82.
  • The {REQUEST_URI} placeholder lands inside a single-quoted href attribute in die_page_sfw.html, so metacharacters break out and inject script.
  • CVSS 7.2: network-exploitable, low complexity, no privileges required, changed scope (C:L/I:L).
  • 6.83 wraps every die-page substitution in esc_url(), esc_html(), and esc_attr(), breaking attribute-context injection.
  • BitFire FREE WAF detects XSS payloads in the request target and blocks them before WordPress loads the plugin.
01
漏洞概述

了解曝光

WordPress 网站受影响的组件、攻击路径和实际风险。

受影响的组件Anti-Spam by CleanTalk – Spam Protection Without CAPTCHA
潜在影响范围200000安装
攻击技术stored cross-site scripting
已发表2026-09-30
BitFire's FREE WAF reads every request target before WordPress executes, so the crafted URI behind CVE-2026-65437 is detected and blocked before CleanTalk's firewall can render one line of poisoned HTML.
02
技术分析

该漏洞如何发挥作用

研究详细信息、受影响的版本、利用行为和补救指南。

Unauthenticated Stored XSS in the SpamFireWall Die Pages

CleanTalk's SpamFireWall hooks init at priority 1 and runs for every front-end request, anonymous included. When it denies a visitor — IP matched in the SFW table, Anti-Flood or Anti-Crawler limits tripped, or ?sfw_test_ip= forcing the test page — the plugin renders a 403 interstitial and dies. In 6.82, SFW.php captures $_SERVER['REQUEST_URI'] unsanitized, maps it to the {REQUEST_URI} placeholder, and injects it with str_replace into a single-quoted href attribute in die_page_sfw.html. Metacharacters in the request target break out of the attribute, so attacker-controlled markup and script execute on your site's origin. Anti-Flood and Anti-Crawler die pages repeat the same unescaped substitutions, and ?debug=1 adds raw header and $_SERVER dumps to the output.

BitFire FREE WAF Stops the Poisoned Request Before WordPress Runs

CVE-2026-65437 lives entirely in what the request carries: the malicious payload must ride in the URI for the die page to echo it. That is exactly the data BitFire's WAF inspects. BitFire FREE's web application firewall evaluates every URL, query string, and request target before WordPress loads a single plugin, detecting cross-site scripting syntax and common evasion patterns. A request target crafted for this CVE is flagged and blocked at the request layer — init never fires, Firewall::run() never executes, and no interstitial is ever rendered with attacker markup inside. This is behavior-based protection, so it needs no CVE-specific virtual patch. BitFire's WAF ships in BitFire FREE for eligible non-commercial sites; commercial sites need the appropriate commercial license.

If Your Site Was Affected, Investigate for Persistence

Update to CleanTalk 6.83 immediately — the release escapes every die-page substitution with esc_url(), esc_html(), and esc_attr() before the str_replace injection, so metacharacters can no longer terminate the attribute. The disclosure is a stored XSS: the attacker's URL and User-Agent persist in the apbct_sfw_logs table and are exported to CleanTalk's service, and the plugin source alone does not pin down every place that data may surface. Patching closes the known path; it does not undo a compromise that already happened. Script that ran in an administrator's browser can act with that session's authority. Run BitFire PRO Threat Hunter to sweep for backdoor administrator accounts, hidden database triggers, long-running PHP processes, and droppers that can restore malware — then remove every persistence mechanism and rotate credentials.

Block CVE-2026-65437 at the Request Layer with BitFire

CVE-2026-65437 turns a spam filter into an XSS delivery page, but the attack dies at BitFire's request layer: the FREE WAF detects the XSS payload in the request target and blocks it before WordPress or CleanTalk ever executes. Pair that prevention with fast patching to 6.83 and, for any site that ran 6.82 or earlier, a BitFire PRO Threat Hunter investigation to rule out leftover persistence. Deploy BitFire today and make the next vulnerable plugin irrelevant.

03
来源审查

易受攻击和固定的代码

相关来源位于 lib/Cleantalk/ApbctWP/Firewall/SFW.php (diePage() placeholder substitution; same pattern in AntiFlood.php and AntiCrawler.php).

之前弱势行为
// lib/Cleantalk/ApbctWP/Firewall/SFW.php 6.82 (diePage())
'{CLEANTALK_URL}'  => $apbct->data['wl_url'],
'{REMOTE_ADDRESS}' => $result['ip'],
'{REQUEST_URI}'    => $request_uri,
'{COOKIE_DOMAIN}'  => $this->cookie_domain,

foreach ($replaces as $place_holder => $replace) {
    $this->sfw_die_page = str_replace($place_holder, $replace, $this->sfw_die_page);
}
之后纠正行为
// lib/Cleantalk/ApbctWP/Firewall/SFW.php 6.83 (diePage())
'{CLEANTALK_URL}'  => esc_url($apbct->data['wl_url']),
'{REMOTE_ADDRESS}' => esc_html($result['ip']),
'{REQUEST_URI}'    => esc_url($request_uri),
'{COOKIE_DOMAIN}'  => esc_html($this->cookie_domain),

foreach ($replaces as $place_holder => $replace) {
    $this->sfw_die_page = str_replace($place_holder, $replace, $this->sfw_die_page);
}
04
零日保护

防止第一个利用请求

BitFire 在漏洞被公开之前以及其他供应商有时间开发签名或补丁之前,在零天保护 WordPress 服务器。

01 · 验证停止未知客户端

在之前未知的漏洞代码到达 WordPress 之前,机器人控制和浏览器验证会阻止不受信任的自动化客户端。

02·检测阻止恶意行为

常规 WAF 保护可识别危险的请求行为和恶意负载,而无需等待特定于漏洞的签名。

03 · 预防遏制运行时攻击

RASP 遵循 PHP 内部的执行,防止对受保护的文件、帐户和数据库内容进行未经授权的更改。

BitFire · WordPress 保护零日准备就绪
BitFire 结合了经过验证的客户端控制、基于行为的 WAF 检测和运行时 RASP 实施,可在漏洞利用名称、CVE、签名或供应商补丁之前保护 WordPress。
关于作者

科里·马什

Cory 拥有 20 多年的互联网安全经验,是 BitFire 项目的首席开发人员。

阅读 BitFire 安全研究 →
保护您的 WordPress 网站

在下一个漏洞到来之前添加保护。

BitFire 将机器人控制、请求检查、恶意软件检测和运行时保护结合在一个 WordPress 安全平台中。

Protect my site free →