XSS in SSI printenv command – Apache Tomcat – CVE-2019-0221

Summary

Apache Tomcat had a vulnerability in its SSI implementation which could be used to achieve cross site scripting (XSS). This is only exploitable if SSI is enabled and the “printenv” directive is used which is unlikely in a production system.

The vendor has rated this as a Low severity issue. A fix was released in versions 7.0.94, 8.5.40 and 9.0.19. Users are encouraged to upgrade as soon as possible. CVE-2019-0221 has been assigned to track this issue.

Vulnerability Details

Server Side Includes (SSI) is a simple scripting language used server-side in some web servers for functionality like including files, echoing values of variables and displaying basic information about files. Note that these ARE NOT environment variables but are specific to SSI. They either have been set by the user or contain information about the incoming HTTP request (see full list here).

The “echo” directive prints out value of a single variable while the “printenv” directive prints out values of all variables. Both of these directives output HTML. The Apache Tomcat implementation correctly escapes XSS values when using the “echo” directive but not for the “printenv” directive. As the result, if an application is using this directive, an attacker can inject malicious input causing it to output and cause XSS.

Compare the code from the “echo” parameter which encodes the output correctly:

Screen Shot 2019-05-27 at 11.18.07 AM.pngVersus the code for the “printenv” parameter which DOES NOT encode the output:

Screen Shot 2019-05-27 at 11.21.13 AM.png

The fix is to add encoding as seen in this commit:

Screen Shot 2019-05-27 at 11.22.40 AM.png

In order to exploit this, several things have to true:

  1. SSI support has to be enabled in Apache Tomcat – either globally or on a specific web application. It is NOT ENABLED by default.
  2. A file with the “printenv” SSI directive must exist within the web application (usually “.shtml”).
  3. That file must be accessible to the attacker.

Steps To Replicate

1. Install a Java Runtime Environment (JRE) in Windows.

2. Download a vulnerable version of Tomcat and extract.

3. Modify the conf\context.xml file on line 19, to enable privileged context (this can also be done on individual applications instead of globally):

Context privileged="true">

4. Modify conf\web.xml to enable the SSI Servlet as per instructions here (this can also be done on individual applications instead of globally).

5. Put the following code in “webapps/ROOT/ssi/printenv.shtml”:

<html><head><title></title><body>
Echo test: <!--#echo var="QUERY_STRING_UNESCAPED" --><br/><br/>
Printenv test: <!--#printenv -->
</body></html>

6. Run Tomcat via the following command:

cd bin
catalina run

7. Call the following URLs to observe XSS (may need to use FireFox). Observe the difference between “echo” directive which escapes properly and the “printenv” directive which doesn’t escape properly

http://localhost:8080/ssi/printenv.shtml?%3Cbr/%3E%3Cbr/%3E%3Ch1%3EXSS%3C/h1%3E%3Cbr/%3E%3Cbr/%3E

http://localhost:8080/printenv.shtml?%3Cscript%3Ealert(%27xss%27)%3C/script%3E

Screenshots:

Screen Shot 2019-02-17 at 10.11.32 AM

Screen Shot 2019-02-17 at 10.10.55 AM.png

Vendor Response

This issue was responsibly reported to the vendor via the EU FOSSA bounty program operated by Intigriti. The vendor assigned CVE-2019-0221 to track this issue and provided a fix.

The vendor rated this issue as “Low Impact” on the following basis:

  • SSI is disabled by default
  • hardly anyone uses SSI
  • printenv is really a debug command that you would not expect to find
    used in a production system

The vendor also indicated that if there was a lower impact level, they would have used it as they consider the chances of a production system being exposed to this vulnerability to be very close to zero.

The vendor indicated that the following versions are vulnerable (no information is available on earlier versions):

  • Tomcat 9 – versions 9.0.0.M1 through 9.0.17 (9.0.18 is not affected)
  • Tomcat 8 – versions 8.5.0 to 8.5.39
  • Tomcat 7 – versions 7.0.0 to 7.0.93

Users are encouraged to upgrade to the following fixed versions or later:

  • Tomcat 9 – version 9.0.19 – details
  • Tomcat 8 – version 8.5.40 – details
  • Tomcat 7 – version 7.0.94 – details

Bounty Information

This report satisfied the requirement of the EU FOSSA bounty program and a bounty has been paid.

References

Apache SSI reference: see here – mod_include
CVE-ID: CVE-2019-0221
CVSS 2.0 Score: pending
CVSS 3.0 Score: pending
Tomcat SSI documentation: see here
Vendor advisory: see here

Credits

Text of the advisory written by Yakov Shafranovich.

Timeline

2019-02-17: Initial report submitted to the platform
2019-02-19: Initial report validated by the platform
2019-03-12: Report accepted by the vendor
2019-05-17: Public advisory issued by the vendor
2019-05-27: Public disclosure by reporter

Exploring the File System via Jenkins Credentials Plugin Vulnerability – CVE-2019-10320

Summary

The recently fixed vulnerability in the Jenkins Credentials plugin (fixed in v2.1.19) allowed users with certain permissions to confirm existence of a file on the server’s file system. While this doesn’t allow an attacker to view the file content, the ability to obtain information about the file system can be leveraged for other attacks. In this post we will explain how to reproduce this vulnerability.

It is also possible to load credentials from a valid PKCS#12 files on the Jenkins server, and obtain access to the contents of those credentials via a job. That may be addressed in a future blog post.

PLEASE NOTE: This is only exploitable by users that have sufficient access to the Jenkins server to add or update credentials. Usually anonymous users do not have that level of access.

Prerequisites

You will need to download, install and initialize Jenkins following these instructions. DO NOT install any plugin during the installation process. When done, you should be able to login to Jenkins via the following URL: “http://localhost:8080/“.

Installing the Vulnerable Plugin

1. Download the vulnerable plugin (v2.1.18) from the Jenkins update site as an HPI file:

updatesite

2. Go to the Jenkins plugin manager, and click the advanced tab (“http://localhost:8080/pluginManager/advanced“) to get to the manual plugin installation page. Select the HPI file downloaded in the previous step and install it. Restart the Jenkins server (“http://localhost:8080/restart“) after the plugin has been installed.

plugin

3. Login to the Jenkins management page (“http://localhost:8080/manage“) and plugin manager (“http://localhost:8080/pluginManager/“) to confirm that the vulnerable plugin has been installed.

manage

plugin

Getting to the Vulnerable Page

1. Login to Jenkins, then go to “Credentials”, “System”, “Global Credentials”. Click the new option “Add Credentials” that appears on the left side. The user that you are using MUST have sufficient permissions to add or update credentials. You can also reach this page by going directly to “http://localhost:8080/credentials/store/system/domain/_/newCredentials“.

Screen Shot 2019-05-23 at 11.11.51 PM

Screen Shot 2019-05-23 at 11.12.28 PM.png

2. In the “Kind” drop down box select “Certificate”, and from the two radio buttons select “From a PKCS#12 file on Jenkins master”.

Screen Shot 2019-05-23 at 11.12.52 PM.png

Exploitation

Put in a valid path in the “file” box and click anywhere in the page to refresh. You will get an error message “The file xxxx doesn’t exists” if the file is not present, OR “Could not load keystore” if the file does exists. This would allow an attacker to explore the file system and confirm whether specific files exist or not. While file content cannot be viewed (unless they are PKCS#12 files), the attacker can use this technique to help advance other attacks.

Screen Shot 2019-05-23 at 10.37.48 PM.pngScreen Shot 2019-05-23 at 10.37.40 PM.png

References

CVE-ID: CVE-2019-10320
Vendor advisory: see here

Upcoming Advisory for Apache Tomcat Vulnerability – CVE-2019-0221

We will be releasing an advisory on a security vulnerability that was reported to the Apache Software Foundation, specifically in Apache Tomcat. This issue is being tracked under CVE-2019-0221. The issue was discovered by Nightwatch Cybersecurity Research and reported to Apache via the EU FOSSA-2 project, hosted by Intrigri.

UPDATE: Advisory has been posted here.

Related links:

  • Apache advisory – here
  • CVE entry – here
  • Tomcat security pages – v7, v8 and v9

Finding Unlisted Public Bounty and Vulnerability Disclosure Programs with Google Dorks

Introduction

Bug bounty/vulnerability disclosure platforms are used by companies to coordinate the reporting, triaging and in some case, rewarding,  of security vulnerabilities. In many platforms the various programs are not always public – some may be public, some maybe unlisted but public, some may be private and some may be invite-only. In this post we outline how we found a set of public programs that were not listed on the platform site but were findable via Google searches.

Embedded Forms

While most platforms host the program information, policies and submission pages on their own sites, their customers may occasionally want to embed or host a particular program on the site owned by the customer or one that is agnostic, not the platform. For these uses cases, some platforms have an embedding feature which allows customers to embed a submission form for vulnerabilities within the customer owned website or host it via a website that doesn’t appear to be connected to the platform vendor. Here is documentation for some of the platforms:

The problem is that if a company ends up embedding a form, it will get indexed by Google and can be found via a Google search. The trick is to look for something unique in the text of the form. Here is for example a vulnerability reporting form for Walmart, provided by BugCrowd – as you can see it says “Powered by BugCrowd”

Screen Shot 2019-05-02 at 7.40.02 PM

If you check the BugCrowd public list of programs, WalMart will not be listed:

Screen Shot 2019-05-02 at 9.10.49 PM

However, it may appear on the list such as the one from Disclose.IO:

Screen Shot 2019-05-04 at 11.48.15 PM.png

Google Dorking Other BugCrowd Embedded Forms

Now if you put the text from the form into Google as follows, you can find a bunch of other ones as well:

"powered by bugcrowd" -site:bugcrowd.com

These do not appear in the BugCrowd public list, and many of them are not in the Disclose.IO list. Example:

Screen Shot 2019-05-02 at 9.08.36 PM

What About HackerOne?

For HackerOne, a blog post shows an example of a form which looks very similar to a standard one.

Screen Shot 2019-05-02 at 9.19.01 PM

We tried Googling for the following query got no results:

"powered by hackerone" "submit vulnerability report"

Eventually, we just Google for the following and got many unrelated results:

"submit vulnerability report"

Among those, we were able to find a single embedded form from HackerOne for a non-public program. Because HackerOne uses an image for their “Powered By” message, it is probably harder to find or maybe not that many programs use the HackerOne forms yet 🙂 [Based on some additional feedback it looks like HackerOne forms are generated dynamically and may not be indexable by Google, see Lyft as an example]

Screen Shot 2019-05-02 at 9.21.34 PM

Screen Shot 2019-05-02 at 9.23.10 PM

Screen Shot 2019-05-02 at 9.24.50 PM

What About Synack?

While Synack doesn’t operate any public programs, they do offer a managed disclosure process which is hosted by “responsibledisclosure.com”. A simple Google Search against that site shows a bunch of programs (these are listed in Disclose.io):

site:responsibledisclosure.com

Screen Shot 2019-05-02 at 9.34.33 PM.png

Other Platforms?

We haven’t explored other platforms but feel free to do so yourself 🙂

Responses from the Platforms

This issue was reported to the three platforms listed above, here are their responses:

BugCrowd:

“We don’t guarantee that all public programs are listed directly on Bugcrowd.com – a number of companies leverage our Embedded Submission Form to host a Bugcrowd submission form (like you’re finding via these searches) directly on their own sites. Even though these programs aren’t directly advertised on our Programs page, they’re not meant to be considered private/secret. It’s up to the companies choosing to use this form to decide how and where they display it.

Nothing is being “leaked,” as any companies who do choose to run private programs that include an intake via our Embedded Submission Form understand what they’re doing: The Embedded Submission Form integration enables you to host a submission form from your own website rather than through Bugcrowd. This integration provides a streamlined workflow so that researchers can easily submit vulnerability reports directly to you, while allowing you to continue to manage and track submissions through Crowdcontrol.

You can manage and track submissions through Crowdcontrol for private and public programs. These are companies choosing to host our ESF on public/indexed pages, so the fact that they’re not listed at https://bugcrowd.com/programs is exactly what you’d expect.”

HackerOne:

“This feature is not intended to be private but to help ease programs’ engagement with the larger hacker community. We do caution programs, prior to setting up the feature, to understand that their program will no longer be private if the form is exposed in a public way. Beyond that, the program benefits from our normal private experience, and we do not include other call outs or invitations to the programs on HackerOne unless explicitly requested.

Some companies, like Punchh, use this feature to allow researchers to submit reports to their vulnerability disclosure program via their own website.”

Synack:

“Although we do not advertise our Responsible Disclosure programs, they are publicly accessible and not considered to be private information”

Timeline

2019-02-20: Reported to Synack and rejected
2019-02-22: Reported to BugCrowd and rejected
2019-05-02: Draft blog post shared with HackerOne, Synack and BugCrowd
2019-05-03: Comments received from platform vendors
2019-05-04: Blog post published

Remote Code Execution (RCE) in CGI Servlet – Apache Tomcat on Windows – CVE-2019-0232

Summary

Apache Tomcat has a vulnerability in the CGI Servlet which can be exploited to achieve remote code execution (RCE). This is only exploitable when running on Windows in a non-default configuration in conjunction with batch files.

The vendor released a fix in Tomcat versions 7.0.94, 8.5.40 and 9.0.19. Users are encouraged to upgrade as soon as possible. CVE-2019-0232 has been assigned to track this issue.

Vulnerability Details

Common Gateway Interface (CGI) is a standard protocol to allow web servers to execute command line programs / scripts via web requests. This protocol also allows passing of command line arguments to the script or program being executed via URL parameters. The protocol itself is defined in RFC 3875.

The following CGI request:

  • http://localhost:8080/cgi/test.bat?&dir

converts to:

  • test.bat &dir

Apache Tomcat supports execution of CGI scripts / programs in a non-default configuration via a special CGI servlet. This servlet also parses URL parameters and translates them into command line arguments. The actual execution of the CGI scripts happens via Java Runtime Environment (JRE)’s java.lang.Runtime class, exec() function.

When CGI support is enabled in Apache Tomcat in Windows, and command line argument passing is enabled, it is possible to cause command injection via parameter interpolation when calling a batch file (*.bat / *.cmd). This happens because “cmd.exe” performs interpolation on some special characters before execution which can cause other shell commands to be called. Neither Apache Tomcat or the Windows JRE perform any kind of input validation for these special characters. A partial list of these characters can be found here and here. Additional information about why this issue is specific to the Windows JRE can be found in this blog post by Markus Wulftange.

Steps To Replicate

1. Install a Java Runtime Environment (JRE) in Windows.

2. Download a vulnerable version of Tomcat and extract.

3. Modify the conf\context.xml file on line 19, to enable privileged context:

<Context privileged="true">

4. Modify conf\web.xml to enable the CGI Servlet by removing the comments around line 387 as follows and adding the following parameters (enableCmdLineArguments is only needed for Tomcat 9):

<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
  <param-name>cgiPathPrefix</param-name>
  <param-value>WEB-INF/cgi</param-value>
</init-param>
<init-param>
  <param-name>executable</param-name>
  <param-value></param-value>
</init-param>
<init-param>
  <param-name>enableCmdLineArguments</param-name>
  <param-value>true</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>

5. Enable the CGI servlet by removing comments around this – you also need to change the URL pattern to match the one in the previous step (“cgi”):

<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi/*</url-pattern>
</servlet-mapping>

6. Create a folder for the CGI files:

mkdir webapps\ROOT\WEB-INF\cgi

7. Place the following text into a batch file located in “webapps\ROOT\WEB-INF\cgi\test.bat”

@echo off
echo Content-Type: text/plain
echo.
echo Hello, World!

8. Run Tomcat via the following command:

cd bin
catalina run

9. Trigger the following URLs and observe the dir command being run:

http://localhost:8080/cgi/test.bat?&dir

s1

Additional Notes – Environment Variables and Path

By default, Tomcat doesn’t pass all of the environment variables from the parent process that runs Tomcat itself. That means that if you run “set”, you will not see any environment variables other than those set by Tomcat itself. This also means that you would need to spell out the directory path of the command you are trying to run. However, if the “passShellEnvironment” parameter is set to true, the variables from the parent process will be passed through and you can call any command in PATH as well as view those variables. If the command cannot be found, there will be a error in the console log “XXXX is not recognized as an internal or external command”.

Example of trying to run a command without a full directory including the Tomcat console logs:

s5 s6

Examples of running with the parameter being set or spelling out the directory path:

s8s9.PNG

Example of trying to view the environment variables without and with the passShellEnvironment parameter being set to “true”:

s3

s2.PNG

Additional Notes – Memory Leaks / Denial of Service

If the command being executed is a long running command, it maybe possible to cause a denial of service or a memory leak. This happens because Tomcat waits for the OS process to complete.

Here is an example of netstat being triggered:

screen4

screen3

Additional Notes – Other Commands and STDERR

The “executable” parameter indicates which executable should be used to run the script. By default, this is set to “perl” with the expectation that the files being executed are Perl scripts. If this is set to empty, then it is possible to execute batch files since those are executed by “cmd.exe”. HOWEVER, it seems that the command interpolation only happens with batch files – if this is set to real program, then command interpolation doesn’t necessary occur and this vulnerability may be not exploitable.

Also, if the command being triggered outputs to STDERR instead of STDOUT, that output doesn’t get piped back to the web request – instead it goes to the Tomcat console log.

Here is an example when “java.exe” is set as the executable parameter and produces output to STDERR:

b3

Vendor Response

This issue was responsibly reported to the vendor via the EU FOSSA bounty program operated by Intigriti. Vendor analysis indicated that the core cause for this issue has to do with the way the Java Runtime Environment (JRE) interprets command arguments in Windows specifically and doesn’t impact Apache Tomcat when used with other operating systems. The vendor assigned CVE-2019-0232 to track this issue and provided a fix.

The vendor fix consists of two parts:

  • Disabling command line arguments from being passed to the CGI servlet in the default configuration (“enableCmdLineArguments” set to “false“) for Tomcat 7 and 8  – this was already disabled by default in Tomcat 9.
  • Adding a new configuration parameter (“cmdLineArgumentsDecoded“) to the default CGI configuration that will be used for input validation if passing of command line arguments is enabled and will be set to the following regular expression (OS specific). Note that if the user changes this parameter, they may become vulnerable again.
    • Windows - [[a-zA-Z0-9\Q-_.\\/:\E]+]
    • Other operating systems - [.*]

Affected Versions and Mitigation

Apache Tomcat is only vulnerable to this issue if the following conditions are met:

  • Running on Windows
  • CGI support is enabled either via the web.xml for a specific web application or the server as whole (see documentation). This is disabled by default.
  • The “privileged” setting is set to “true” in the Context element. This is “false” by default.
  • Tomcat 9 onlyenableCmdLineArguments is set to “true” (enabled by default in Tomcat 7 and 8)
  • The “executable” parameter is empty, and the the CGI scripts being executed are batch files (either .bat or .cmd). It is not clear if other commands that use “cmd.exe” are vulnerable as well.

The vendor indicated that the following versions are vulnerable (no information is available on earlier versions):

  • Tomcat 9 – versions 9.0.0.M1 through 9.0.17 (9.0.18 is not affected)
  • Tomcat 8 – versions 8.5.0 to 8.5.39
  • Tomcat 7 – versions 7.0.0 to 7.0.93

Users are encouraged to upgrade to the following fixed versions or later:

IMPORTANT NOTE: even when running a fixed version, you SHOULD NOT change the “cmdLineArgumentsDecoded” configuration parameter to a different value. If you do, your installation may become vulnerable. If an upgrade is not possible, users can apply one of the following mitigations:

  • Disable CGI support (it is disabled by default)
  • Or set the “enableCmdLineArguments” parameter to “false“. This setting will disable command line arguments from being passed via the CGI servlet.

Bounty Information

This report satisfied the requirement of the EU FOSSA bounty program and a bounty has been paid.

References

Blog post on JRE behavior: see here (Markus Wulftange)
CGI Standard: RFC 3875
CVE-ID: CVE-2019-0232
CVSS v2.0 Score: 9.3 – (AV:N/AC:M/Au:N/C:C/I:C/A:C)
CVSS v3.0 Score: 8.1 – (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H)
Tomcat CGI Servlet source code: see GitHub
Vendor advisory: see here

Credits

Text of the advisory written by Yakov Shafranovich.

Timeline

2019-02-14: Initial report submitted to the platform
2019-02-17: Initial report validated by the platform
2019-03-03: Report acknowledged by the vendor
2019-03-14: Interim evaluation received from the vendor
2019-03-22: Communication with the vendor
2019-04-10: Public advisory issued by the vendor
2019-04-30: Public disclosure by reporter

Upcoming Advisory for Apache Tomcat Vulnerability – CVE-2019-0232

We will be releasing an advisory on a security vulnerability that was reported to the Apache Software Foundation, specifically in Apache Tomcat. This issue is being tracked under CVE-2019-0232. The issue was discovered by Nightwatch Cybersecurity Research and reported to Apache via the EU FOSSA-2 project, hosted by Intrigri.

UPDATE: The advisory has been published here.

Related links:

  • Apache advisory – here
  • CVE entry – here

Third Party Android App Storing Facebook Data Insecurely (Facebook Data Abuse Program)

Summary

A third-party Android application with Facebook API access was found to be copying user data into storage outside of Facebook, and storing it insecurely in two separate locations. This issue was reported to Facebook via their Data Abuse Bounty program and the insecure storage locations have been secured on November 12th, 2018. The Facebook app associated with this application has been removed from the Facebook platform but the Android application remains available in Google’s Play Store. The number of affected users is unknown. [ADDED: 02/15/2019 – Google has been notified].

Background

In April 2018, FaceBook announced a new Data Abuse Bounty program that rewards “people with first-hand knowledge and proof of cases where a Facebook platform app collects and transfers people’s data to another party to be sold, stolen or used for scams or political influence“.

In September 2018, we found an Android application in the Google Play store that purports to provide additional functionality to Facebook users that is not available through the platform. At the time of writing, the application had more than 1,000,000 downloads. After downloading the application, and examining it using JADX, we found that the application was using Facebook APIs to access data for the logged in user and copying to several storage locations outside of Facebook. Upon further examination, it was clear that at least two of such locations (a Firebase database and an API server) were making this data available without any authentication and without HTTPS. This would allow an attacker to mass download the user data accumulated by the application from its users.

We do not know for sure how many users have been impacted or exposed, but one of the databases accessed contained over 1,000,000 records. [ADDED: 02/15/2019 – The application purported to provide additional statistical information about the logged-in user’s Facebook account. There is a privacy policy within the application but it is ambiguous about the transfer of data].

Issue #1 – Storing user data in an public Firebase database

During our examination of the application, we located a Firebase database that the application was communicating with. The database was configured in test mode, which allowed anonymous public access by visiting the URL of “https://DATABASE.firebaseio.com/.json“. As seen in the attached screenshot, the database contained data obtained from Facebook. Aside from confirming the initial permission issue, we did not access or explore this database any further.

Screenshot:

likulator1

Issue #2 – Storing user data in a non-SSL server without authentication

During our examination of application, it become clear that the server that the application was communicating with, did not use SSL and was being accessed without authentication. As seen below, this would allow an attacker to download the data collected by the application from Facebook via a regular browser as well as spy on any connections between the application and the server. Aside from confirming the initial permission issue, we did not access or explore this database any further.

likulator2

likulator3

Vendor Response and Mitigation

We contacted the Facebook Data Abuse Bounty program but did not contact the vendor directly. After Facebook completed its review, the two insecure locations have been secured on November 12th, 2018. The Facebook app associated with this application has been removed from the Facebook platform but the Android application remains available in Google’s Play Store. [ADDED: 02/15/2019 – Google has been notified].

This discovery qualified under the terms of the Facebook Data Abuse Bounty Program and a bounty payment has been received.

References

Facebook report # 10101718616795015
Google reference # 8-7487000025062

Credits

This advisory was written by Yakov Shafranovich.

Timeline

2018-09-17: Initial report submitted to Facebook, initial response received
2018-11-12: Issued fixed
2018-11-27: Bounty decision received; sent disclosure request
2018-11-30: Facebook asked for additional time before disclosure
2019-01-15: Investigation has been finalized, FaceBook asked for a copy of the disclosure
2019-02-03: Draft disclosure shared for review
2019-02-14: Public Disclosure
2019-02-15: Minor updates; notification sent to Google

Content Injection in Amazon Kindle’s FireOS [CVE-2019-7399]

Summary

The FireOS operating system provided by Amazon for Fire tablet devices can be injected with malicious content by an MITM attacker. An attacker can also capture the serial number of the device. The root cause is lack of HTTPS for legal content (terms of use and privacy policy) within the settings section.

The issue was discovered in FireOS v5.3.6.3 and fixed by the vendor in v5.3.6.4 that was released in November 2018. Devices will automatically update to the latest version. CVE-2019-7399 has been assigned by MITRE to track this issue.

Vulnerability Details

FireOS is an operating system provided by Amazon for the Fire tablet devices.  It is a customized fork of Android. While monitoring network traffic on a test device, we observed that several calls from the settings section (terms of use and privacy policy) are done without HTTPS and can be injected with malicious content by an MITM attacker. It is also possible for the attacker to observe this traffic and capture the serial number (DSN) of the device.

Screenshots of the captured traffic:

Screenshot_2018-09-03-13-11-20 Screenshot_2018-09-03-13-11-26

Steps To Replicate (on Ubuntu 18.04)

1. Install the application on the Android device but do not start it.

2. Install dnsmasq and NGINX on the Linux host:

sudo apt-get install dnsmasq nginx

3. Modify the /etc/hosts file to add the following entry to map the domain name to the Linux host:

192.168.1.x www.kindle.com
192.168.1.x kindle.com

4. Configure /etc/dnsmasq.conf file to listen on the IP and restart DNSMASQ

listen-address=192.168.1.x
sudo /etc/init.d/dnsmasq restart

5. Add a file with malicious content (you may need to use sudo):

cd /var/www/html
mkdir support
echo powned >support/privacy
echo powned >support/terms

6. Modify the settings on the Kindle device to static, set DNS to point to “192.168.1.x”. AT THIS POINT – the Kindle device will resolve DNS against the Linux computer and serve the large servers file

7. Tap “Settings”, “Legal and Compliance”, and tap either “Terms of Use” or “Privacy”. Observe injected content.

Vendor Response and Mitigation

The issue was discovered in FireOS v5.3.6.3 and fixed by the vendor in v5.3.6.4 that was released in November 2018. Devices will automatically update to the latest version. MITRE assigned CVE-2019-7399 to track this issue.

References

Amazon tracking # PO135449968
CVE-ID: CVE-2019-7399

Credits

Text of the advisory written by Yakov Shafranovich.

Timeline

2018-09-03: Initial report to the vendor
2018-09-04: Report triaged and being reviewed by the vendor
2018-09-17: Communication from the vendor, issue still being reviewed
2019-01-10: Fix confirmed, communication regarding disclosure
2019-01-30: Vendor pinged about CVE assignment
2019-02-03: Draft advisory sent for review
2019-02-04: CVE issued by MITRE
2019-02-07: Public disclosure; minor syntax updates

Thoughts on the MSI/JAR Authenticode Bypass

Earlier today, Google’s VirusTotal published a blog post about a new way to bypass code signing in Windows via JAR files:

Microsoft Windows keeps the Authenticode signature valid after appending any content to the end of Windows Installer (.MSI) files signed by any software developer. This behaviour can be exploited by attackers to bypass some security solutions that rely on Microsoft Windows code signing to decide if files are trusted. The scenario is especially dangerous when the appended code is a malicious JAR because the resulting file has a valid signature according to Microsoft Windows and the malware can be directly executed by Java.

In short, an attacker can append a malicious JAR to a MSI file signed by a trusted software developer (like Microsoft Corporation, Google Inc. or any other well-known developer), and the resulting file can be renamed with the .jar extension and will have a valid signature according Microsoft Windows. For example, via the command “copy /b signed.msi + malicious.jar signed_malicious.jar”. The victim can be infected with just a double-click in such a file.

Here are some quick thoughts from our research team – note that we were not involved in this effort and have no insider knowledge. This is entirely based on public sources.

How can ZIP and EXE files be combined?

First of all, how is it possible that the same exact file can be executable both by Windows and Java? The trick lies in how Windows executable files work – as described in Microsoft’s documentation. Basically, the OS reads the file from the beginning, looking at the magic value of “MZ” followed by headers, then followed by the file content. We are going to assume that there is a table in the file that tells the reader how long each segment is, and therefore it is possible to append arbitrary data to the end of the file without it breaking.

A JAR file, however, is essentially a ZIP file. ZIP files have their index or central directory in the end of the file, and it is possible to prepend data in the beginning of the file and that file still being valid. That means that you can combine a Windows executable that is read from the beginning and rely on its headers and tables to tell the reader where to stop, and do the same for the ZIP content in the end of the file. Both files remain valid, while combined together. Also, while the example provided by VirusTotal is a JAR file, the same trick would work for other ZIP-based formats like Microsoft Office (DOCX/XSLX/etc), OpenOffice (ODT/ODS/etc), etc. Of course, this assumes that the software reading these files goes to the central directory of the ZIP and doesn’t check the magic value in the beginning.

Here is an modified example of PE files from Wikipedia, and a ZIP file example from OASIS, showing the direction in which file content is read:

revengpefile                  zip

Combined together:

revengpefile

zip

What is Microsoft Code Signing / Authenticode?

As per the original blog post and other technical documentation from Microsoft, the code signing in question is Authenticode which is used by Microsoft for Windows executables, drivers, and other files. The purpose it to make sure the file originated from a trusted publisher. There is also a command line tool included in Windows called “SignTool” which is used for signing and verifying files.

The way code signing works is described in a Microsoft technical document here. It is essentially a digital signature using PCKS7 and special X.509 certificates (code signing certificates issued by CAs). It is connected to the same PKI infrastructure as SSL certificates with some additional checks by CAs when issuing the certificate (not at sign time). Like all other digital signatures, it is essentially some sort of a hash signed by a private key of the holder of the certificate which is then verified by the public key in the X.509 certificate. The certificate itself is verified against public PKI infrastructure just like SSL.

Example appears below (from Microsoft documentation):screen shot 2019-01-16 at 8.00.15 pm

Bypassing Code Signing

In a standard digital signature scenario such as PGP or S/MIME, the entire content of the message is hashed to produce a message digest using a function like SHA. That hash is then digitally signed using the sender’s private key. Note that the entire message is hashed – this allowing the receiver to check if it was modified or not, not just bits and pieces.

One of the common refrains in security is “never roll your own crypto”, which in this case includes choosing what to hash. In the case of Authenticate, it appears that the file hash does not cover the entire file. As described in this document, information in the end of the file (after the second “remaining content” above) ARE NOT included in the hash (emphasis added):

Information past of the end of the last section. The area past the last section (defined by highest offset) is not hashed. This area commonly contains debug information. Debug information can generally be considered advisory to debuggers; it does not affect the actual integrity of the executable program. It is quite literally possible to remove debug information from an image after a product has been delivered and not affect the functionality of the program. In fact, this is sometimes done as a disk-saving measure. It is worth noting that debug information contained within the specified sections of the PE Image cannot be removed without invaliding the Authenticode signature.

Implications

This means that it is trivial to simply append another file like a JAR to the end of another digitally signed file, then rename it a JAR and have the resulting file look valid in Windows since the digital signature check will stop before reading the content of the JAR file. At the same time, the file will be executable by Java since it will read from the end ignoring any of the signed content appearing in the beginning. The same would apply for other ZIP based formats like Microsoft Word and this may allow an attacker to send a malicious document while masquerading it as a legit one. Additionally it appears from the blog post that some A/V and security products use the Authenticode signature as a shortcut to validate files so they don’t need to scan them.

Another possible use of this technique is to make attribution murky since some analysts may take the Authenticode signature at face value and not realize that the malware inside may not be from the publisher that signed the file.

An additional idea would be to use this trick to exfiltrate data out of an organization by putting the extra data in the end of the file. This assumes that the DLP and similar tools monitoring outbound traffic rely on the Authenticode signature as well.

Microsoft’s code signing method isn’t the only one that exists. Similar methods exists for Java, Adobe AIR, Android, MacOS, Debian, etc. Further research is needed to see if similar issues exist in other code signing schemes.

(Written by Yakov Shafranovich)