CleanTalk Anti-Spam. Spam Firewall & Bot protection < 6.79 - Unauthenticated Stored Cross-Site Scripting
Description
The CleanTalk Anti-Spam. Spam Firewall & Bot protection plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to 6.79 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<6.79What Changed in the Fix
Changes introduced in v6.79
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-8071 (CleanTalk Anti-Spam Stored XSS) ## 1. Vulnerability Summary The **CleanTalk Anti-Spam** plugin for WordPress is vulnerable to **Unauthenticated Stored Cross-Site Scripting (XSS)** in versions prior to 6.79. The vulnerability exists because the plugin log…
Show full research plan
Exploitation Research Plan: CVE-2026-8071 (CleanTalk Anti-Spam Stored XSS)
1. Vulnerability Summary
The CleanTalk Anti-Spam plugin for WordPress is vulnerable to Unauthenticated Stored Cross-Site Scripting (XSS) in versions prior to 6.79. The vulnerability exists because the plugin logs data from unauthenticated web requests (such as headers or request parameters) for security monitoring and spam analysis but fails to properly sanitize this data before storing it in the database and fails to escape it when displaying the logs in the WordPress admin dashboard.
2. Attack Vector Analysis
- Endpoint: Any frontend page or the specific
admin-ajax.phpendpoint used for bot detection. - Vulnerable Hook: The plugin's Firewall components (
AntiCrawler,SFW,AntiFlood) which execute during theinitorplugins_loadedphase. - Vulnerable Parameter: The
User-AgentHTTP header or thect_bot_detector_event_dataPOST parameter (inferred fromAPBCT_BOT_DETECTOR_SCRIPT_URLand minified JS). - Authentication Required: None (Unauthenticated).
- Preconditions: The "Spam Firewall" or "Anti-Crawler" feature must be enabled (often default or enabled during setup to provide protection).
3. Code Flow
- Entry Point: An unauthenticated user sends a request to the WordPress site.
- Initialization:
cleantalk.phpinitializes the global$apbctstate and loads the Firewall modules. - Detection: Classes like
Cleantalk\ApbctWP\Firewall\AntiCrawlerorCleantalk\ApbctWP\Firewall\SFWprocess the request. If the request triggers a "spam" or "bot" signature (e.g., rapid requests or a suspiciousUser-Agent), the plugin prepares to log the event. - Data Collection: The plugin retrieves the
User-AgentviaCleantalk\ApbctWP\Variables\Server::get('HTTP_USER_AGENT'). - Storage (Sink): The data is stored in the database (typically in the
wp_cleantalk_sfw_logsorwp_cleantalk_logstable) without sufficient sanitization. - Rendering (Sink): An administrator navigates to the CleanTalk settings page (
options-general.php?page=cleantalk). The plugin retrieves the logs viaapbct_settings__display(ininc/cleantalk-settings.php) or an AJAX call to render the log table. TheUser-Agentis echoed directly into the HTML withoutesc_html()oresc_attr().
4. Nonce Acquisition Strategy
This vulnerability involves Unauthenticated Injection. The storage of the payload occurs when the plugin logs a "suspicious" request. Therefore, no nonce is required to perform the injection.
However, to verify the XSS via a browser-based PoC, we must ensure the admin views the logs. If the log page uses AJAX to load entries, we can identify the nonce used for the admin-side log retrieval:
- Navigate to:
/wp-admin/options-general.php?page=cleantalk - Shortcode/Script: The plugin enqueues scripts using
wp_localize_script. - JS Variable: In the admin context, CleanTalk often uses
ctAdminCommonorapbctAdmin. - Acquisition:
// In browser_eval: window.ctAdminCommon?.nonce || window.apbctAdmin?.nonce
5. Exploitation Strategy
The goal is to inject a payload into the logs that will execute when an admin views the "Spam Firewall" logs.
Step 1: Trigger a Logged Event
We will send a request designed to be flagged as a bot or spam, carrying our payload in the User-Agent header.
- Tool:
http_request - URL:
https://<target>/ - Method:
POST - Headers:
User-Agent: <img src=x onerror="alert('CVE-2026-8071_XSS')">Content-Type: application/x-www-form-urlencoded
- Body:
ct_checkjs=1&test_spam=1(Standard parameters to ensure the plugin processes the request as a form submission).
Step 2: Trigger the Firewall (Alternative)
If the above doesn't log, we trigger the "Anti-Crawler" by hitting the site multiple times with the same payload until a block page appears.
6. Test Data Setup
- Plugin Configuration:
- Install
cleantalk-spam-protectversion 6.78. - Activate the plugin.
- Go to Settings -> Anti-Spam and ensure "Spam Firewall" and "Anti-Crawler" are enabled.
- Set a dummy API key if required (e.g.,
111111111).
- Install
- Page Setup: No specific shortcode is required for the injection, as the Firewall operates on all requests.
7. Expected Results
- The malicious
User-Agentstring is written to thewp_cleantalk_sfw_logstable. - When an admin visits
/wp-admin/options-general.php?page=cleantalkand clicks on the "Logs" or "Spam Firewall" tab, an alert box withCVE-2026-8071_XSSappears.
8. Verification Steps
After sending the http_request, use wp_cli to confirm storage:
# Check if the payload exists in the CleanTalk log tables
wp db query "SELECT * FROM wp_cleantalk_sfw_logs WHERE user_agent LIKE '%onerror%';"
wp db query "SELECT * FROM wp_cleantalk_logs WHERE user_agent LIKE '%onerror%';"
To verify the lack of escaping in the output:
# Capture the admin settings page output (simulating an admin)
# Search for the unescaped img tag
wp eval 'include_once "wp-admin/includes/plugin.php"; $_GET["page"]="cleantalk"; apbct_settings__display();' | grep "onerror"
9. Alternative Approaches
- Payload in Referer: If
User-Agentis sanitized, repeat the process using theRefererheader. - Request URL Injection: Send a request to a URL containing the payload:
https://<target>/?s=<script>alert(1)</script>. Some versions of CleanTalk log the full request URI. - Bot Detector AJAX: If the public JS is active, use
browser_evalto trigger the bot detector AJAX call (apbct_email_checkorct_get_cookie) with a malicious payload in the data object.
Summary
The CleanTalk Anti-Spam plugin is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) due to the unsafe logging of request headers and parameters. An attacker can inject malicious scripts into logs by sending a specially crafted request that triggers the plugin's 'Spam Firewall' or 'Anti-Crawler' features, which then executes when an administrator views the logs in the dashboard.
Vulnerable Code
// In various Firewall components (AntiCrawler, SFW), the plugin collects request data // such as the User-Agent without sufficient sanitization before storage. // Path: Cleantalk\ApbctWP\Variables\Server::get('HTTP_USER_AGENT') // In the administration dashboard, the stored logs are rendered. // The plugin fails to use esc_html() or esc_attr() when displaying collected metadata. // File: inc/cleantalk-settings.php (logic within apbct_settings__display) // Example of unsafe retrieval in the rendering logic: $ua = $log_entry['user_agent']; echo "<td>" . $ua . "</td>"; // Unsafe rendering of stored XSS payload
Security Fix
@@ -4,7 +4,7 @@ Plugin Name: Anti-Spam by CleanTalk Plugin URI: https://cleantalk.org Description: Max power, all-in-one, no Captcha, premium anti-spam plugin. No comment spam, no registration spam, no contact spam, protects any WordPress forms. - Version: 6.78 + Version: 6.79 Author: CleanTalk - Anti-Spam Protection <welcome@cleantalk.org> Author URI: https://cleantalk.org Text Domain: cleantalk-spam-protect @@ -189,6 +189,28 @@ ), 'long_description' => true, ), + 'sfw__anti_crawler' => array( + 'type' => 'checkbox', + 'title' => 'Anti-Crawler' . $additional_ac_title, // Do not to localize this phrase + 'class' => 'apbct_settings-field_wrapper', + 'parent' => 'sfw__enabled', + 'description' => + __( + 'Plugin shows SpamFireWall stop page for any bot, except allowed bots (Google, Yahoo and etc).', + 'cleantalk-spam-protect' + ) + . '<br>' + . __( + 'Anti-Crawler includes blocking bots by the User-Agent. Use Personal lists in the Dashboard to filter specific User-Agents.', + 'cleantalk-spam-protect' + ) + . '<br><b>' + . __( + 'This option works only when SpamFireWall is enabled.', + 'cleantalk-spam-protect' + ) . '</b>', + 'long_description' => true, + ),
Exploit Outline
The exploit is achieved by submitting an unauthenticated request that triggers the plugin's security logging mechanisms while carrying a payload in an HTTP header. 1. Target the site with an HTTP POST request to any frontend page. 2. Set the 'User-Agent' header to a JavaScript payload, such as: <img src=x onerror="alert('XSS')">. 3. Include common parameters like 'test_spam=1' to ensure the request is analyzed by the Spam Firewall. 4. If the request is flagged as a 'bot' or 'spam' event, the plugin stores the malicious User-Agent string in the 'wp_cleantalk_sfw_logs' database table. 5. When an administrator later logs in and navigates to the 'Anti-Spam' settings page or the 'Spam Firewall' logs tab, the stored payload is rendered directly into the HTML table without escaping, triggering the script execution in the administrator's context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.