/oct 17, 2017

How we found exploitable zero-days in the open-source GlassFish server with the Security Graph Language

By Ming Yi Ang

We have long had a thesis that when free open-source software projects are forked into commercial versions, then the free open-source version no longer gets the same subsequent level of security updates as the commercial version. Phrased into a question, are the free versions of open-source core products left out in the cold? Earlier this year we were asked by a customer if we could apply our knowledge of open-source security to look at GlassFish Server, a reference implementation for Java EE. Specifically they wanted to know if there were vulnerabilities present in the free GlassFish Open Source Edition that had been patched in the commercial version.

In this post, we disclose vulnerabilities in the open-source version of GlassFish that we discovered using our domain specific language for identifying vulnerabilities, the Security Graph Language (SGL). These issues were all reported to Oracle on 03 May 2017. We worked through a responsible coordinated disclosure process with them and they have published updates protecting users earlier today. Through our disclosure, 4 new Common Vulnerabilities and Exploits (CVEs) for the Oracle GlassFish Server were credited to us.

GlassFish

GlassFish was first released in 2005 by Sun Microsystems. In 2010, Oracle bought Sun Microsystems and committed to a roadmap which included a commercial version called Oracle Glassfish Server. In 2010, commercial support for the Oracle GlassFish Server was discontinued and replaced by the Oracle WebLogic Server. While commercial support was discontinued, security fixes continue to be released in the Oracle Critical Patch Update (CPU) process for users of the commercial product. Aside from the Oracle GlassFish Server, the other version of GlassFish is known as the GlassFish Open Source Edition which is the open-source Java EE Reference Implementation.

Security Graph Language (SGL)

The Security Graph Language (SGL) is the industry’s first Domain Specific Language (DSL) designed to identify security issues in open-source code. With SGL, we put the world’s open-source into a graph database and are then able to traverse the graph of software dependencies for any given project.

To provide an illustration, below is an example of finding the Java libraries which could be vulnerable to External Entity Expansion (XXE) attack(s).

let xml_new = method(class_name: within('javax/xml/parsers/DocumentBuilderFactory',
  'javax/xml/stream/XMLInputFactory'),
  method_name: within('newInstance', 'newFactory')) in
let xml_set_feature = method(class_name:'javax/xml/parsers/DocumentBuilderFactory',
  method_name:'setFeature') in
let xml_set_property = method(class_name:'javax/xml/stream/XMLInputFactory',
  method_name:'setProperty') in
let results = xml_new called_by
  not(union(calls xml_set_feature, xml_set_property)) in results
# Example of a XXE pattern formed to find similar XXE bugs

SGL empowers us with super-powers to express a security pattern and enumerate the entire graph of libraries with ease.

Issues discovered in open-source GlassFish Server

We found a total of 23 issues in the open-source GlassFish server. Of those 23 issues, 10 fixed by Oracle, while 13 were not fixed as the GlassFish versions affected are no longer being maintained.

Out of the 10 issues that were fixed issues, 7 had no previous CVE, and all of them affected the latest version of the GlassFish Open Source Edition at the time of discovery.

Disclosure Timeline

4 April 2017 - Discovered 21 direct issues in GlassFish
3 May 2017 - Contacted maintainer
4 May 2017 - Maintainer responded
4 May 2017 - Provided Information to the maintainer
6 May 2017 - Tracking number received
2 June 2017 - Contacted maintainer to follow up with our 30-day disclosure policy
7 June 2017 - Maintainer requested an extension
22 June 2017 - Maintainer seek clarification on some issues
22 June 2017 - Provided clarification to maintainer
28 June 2017 - Provided more information to maintainer
13 July 2017 - Seek for updates from maintainer
14 July 2017 - Maintainer requested an extension
26 August 2017 - Maintainer provided granular tracking numbers for individual issue
8 September 2017 - Maintainer published GlassFish Open Source Edition 5.0
27 September 2017 - Seek for updates from maintainer
28 September 2017 - Maintainer asked for an extension till 17 October 2017
17 October 2017 - Maintainer releases October CPU 2017
17 October 2017 - Published details on the issues

The remainder of this post will contain information on all 23 disclosed direct issues.

Summary of Issues

The table below provides an overview of the 10 issues that were fixed through our disclosure.

CVE /
NON CVE
Issue Summary 3.x
(Maven)
3.0.1.x
(Oracle)
3.1.2.x
(Oracle)
4.0.x,
4.1.x
(Maven)
5.0
(Maven)
Non CVE 1 Information Disclosure via MessageFormat parameters N.A. N.A. N.A.
Non CVE 2 Cross-Site Scripting (XSS) via configNameSection N.A.
Non CVE 3 Deserialization flaw
Non CVE 4 Denial of Service (DoS) via file upload requests N.A. N.A.
Non CVE 5 Handle Proxy Header (HTTPoxy) in CGISERVLET
Non CVE 6 Deprecated SSLv3 enabled by default N.A. N.A.
Non CVE 7 Security Manager Bypass
CVE-2016-3607 Remote Code Execution (RCE) via NULL byte injection N.A. N.A.
CVE-2016-3608 Directory Traversal via unicode encoding payload N.A. N.A.
CVE-2016-5477 Directory Traversal via unicode encoding payload N.A. N.A.

The remaining 13 issues were not fixed in the Open Source Edition as it affects versions which are no longer maintained.

CVE /
NON CVE
Issue Summary 3.0.x
(Maven)
3.1.x
(Maven)
3.2.x
(Maven)
Non CVE 8,
Not fixed
Information Disclosure via error message N.A.
Non CVE 9,
Not fixed
Information Disclosure via server.log N.A.
CVE-2011-0807 Remote Code Execution (RCE) via default admin account
CVE-2011-1511 Information Disclosure via TRACE requests N.A.
CVE-2011-3559 Denial of Service (DoS) via range header
CVE-2011-5035 Denial of Service (DoS) via hash table collisions
CVE-2012-0081 Unauthorized creation of Domain via admin-cli N.A.
CVE-2012-0104 Denial of Service (DoS) via conversion of named encoding into Charsets
CVE-2012-0550 Cross-Site Request Forgery (CSRF) via REST component
CVE-2012-0551 Cross-Site Scripting (XSS) via administrator console
CVE-2012-3155 Denial of Service (DoS) via administrator console
CVE-2013-1508 Cross-Site Scripting (XSS) via REST component
CVE-2013-1515 Cross-Site Scripting (XSS) via administration console

Credited Common Vulnerabilities and Exploits (CVEs)

From the list of issues above, the following 4 CVEs were credited to us by the maintainers on the commercial version of Oracle GlassFish Server, and these were included in today's release of the Oracle CPU October 2017.

CVE Issue Summary
Non CVE 7,
CVE-2017-10385
Security Manager Bypass
Non CVE 3,
CVE-2017-10391
Deserialization flaw
Non CVE 5,
CVE-2017-10393
Handle Proxy Header (HTTPoxy) in CGISERVLET
Non CVE 2,
CVE-2017-10400
Cross-Site Scripting (XSS) via configNameSection

How we discovered these issues

We took several approaches to discover these issues.

One of our approaches was to collect several known bugs, from other application servers, and test if GlassFish contained similar bugs. As an example used SGL to enumerate a known XXE pattern over the entire call graph of the project.

Security Manager bypass

The issue of Security Manager bypass is not new, and the requirements to introduce this weakness is loose. This issue was also present in a similar application server, the Apache Tomcat. To reconstruct an existing issue like in CVE-2016-0763, we can construct an SGL query which contains the vulnerable pattern like the following:

sgl> let set_global_context = method(class_name:'org/apache/naming/factory/ResourceLinkFactory', method_name:'setGlobalContext') in
let get_security_manager = method(class_name:'java/lang/System', method_name:'getSecurityManager') in
let check_permission = method(class_name:'java/lang/SecurityManager', method_name:'checkPermission') in
set_global_context called_by not(union(calls get_security_manager, calls check_permission))

  method(module_name:'null', class_name:'org/apache/catalina/core/NamingContextListener', method_name:'lifecycleEvent', descriptor:'(Lorg/apache/catalina/LifecycleEvent;)')

The query above would display all methods that calls the setGlobalContext method, and not make a call to both the getSecurityManager and checkPermission methods.

To take it a step further, we can now use the identified method to display all affected libraries by adding a single traversal step, method_in_library.

sgl> set_global_context called_by not(union(calls get_security_manager, calls check_permission)) method_in_librarylibrary(language:'java', coord1:'org.glassfish.main.web', coord2:'web-core', version:'4.1.1')
  library(language:'java', coord1:'org.glassfish.main.web', coord2:'web-core', version:'4.0-b72')
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1')
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1.1')
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1.2')
  …

The results above were subsequently verified and we catalogued the vulnerability as "Non CVE 7" in the table of listing above.

Improper Handling of File

Before Java 7 Update 40, file manipulation during Java Object Deserializable happens when handling a File object which contained a NULL byte. The following SGL query would allow us to instances of readObject defined in GlassFish, and makes a call to java/io/File's getPath method.

sgl> let glassfish_class = class(regex 'org.glassfish.*') in
let read_object = method(method_name:'readObject') in
let get_path = method(class_name:'java/io/File', method_name:'getPath') in
glassfish_class defines read_object where(calls get_path)

From the result set, we could narrow the results further by adding more known pattern of codes that would introduce a weakness to the project. We found that we could also reach glassfish_class by traversing the graph in the reverse direction.

get_path called_by read_object where(defined_by glassfish_class)

This was useful by reducing the number of traversals, and allowed us to reach the callers of a method, instead of tracing the calls. It is useful to perform static analysis of callers where a vulnerable method is already known, demonstrated by the following example.

The results from the above query was then catalogued as "CVE-2016-3607" as it was found to closely match an existing CVE for the commercial Oracle GlassFish Server.

Usage of SSLv3

SSLv3 has been deprecated by the IETF. In GlassFish, there is a method setSsl3Enabled which is set by default to true and as you can see SGL returns the versions affected.

sgl> let set_ssl3_enabled = method(method_name:'setSsl3Enabled') in
set_ssl3_enabled called_by method_in_library

  ...
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1')
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1.1')
  library(language:'java', coord1:'org.glassfish.main.extras', coord2:'glassfish-embedded-all', version:'4.1.2')
  library(language:'java', coord1:'org.glassfish.main.security', coord2:'security', version:'4.1')
  library(language:'java', coord1:'org.glassfish.main.security', coord2:'security', version:'4.1.1')
  library(language:'java', coord1:'org.glassfish.security', coord2:'security', version:'3.1.1-b09')
  library(language:'java', coord1:'org.glassfish.security', coord2:'security', version:'3.1.1-b10')
  library(language:'java', coord1:'org.glassfish.main.security', coord2:'security', version:'3.1.2')
  library(language:'java', coord1:'org.glassfish.main.security', coord2:'security', version:'3.1.2.2')
  library(language:'java', coord1:'org.glassfish.common', coord2:'glassfish-mbeanserver', version:'3.1')
  library(language:'java', coord1:'org.glassfish.common', coord2:'glassfish-mbeanserver', version:'3.1.1')
  library(language:'java', coord1:'org.glassfish.common', coord2:'glassfish-mbeanserver', version:'3.1-b26')
  library(language:'java', coord1:'org.glassfish.common', coord2:'glassfish-mbeanserver', version:'3.1-b27')
  ...

After we have reviewed the results and confirming that the weakness exists, we have catalogued this vulnerability as "Non CVE 6".

Denial of Service (DoS) via File Upload Requests

We then took an existing vulnerability in Apache Commons Fileupload library, CVE-2016-3092, and tried to detect all instances which contained this issue where the method did not throw an IllegalArgumentException.

sgl> let multipartstream_init = method(class_name:'org/apache/catalina/fileupload/MultipartStream', method_name:'<init>', descriptor:'(Ljava/io/InputStream;[BILorg/apache/catalina/fileupload/MultipartStream$ProgressNotifier;)') in
let illegal_argument_exception = method(class_name:'java/lang/IllegalArgumentException', method_name:'<init>', descriptor:'(Ljava/lang/String;)' in
multipartstream_init not(calls illegal_argument_exception)

With the above SGL query, we found multiple leads which led us to believe that GlassFish Open Source was similarly affected. With a little further investigation, we concluded that GlassFish Open Source was vulnerable to a Denial of Service (DoS) weakness and have catalogued this vulnerability as "Non CVE 4".

Continuous Security with the Security Graph Language

By expressing software issues into SGL queries, and continuously building up the amount of SGL queries, the Security Graph Language is an integral part of continuous security by automatically identifying issues as new software gets published.

Similarly, as new SGL queries gets expressed, the query would be ran over the entire world of open-source to collect a result set of issues. The funneled result set obtained by the SGL queries narrows the space of software to allow Security Researchers to efficiently confirm, publish, and produce new security advisories and patches.

Summary

Users of the GlassFish Open Source Edition should update to version 5.0 as soon as possible. Oracle will not be releasing patches for version 3, and will only be releasing fixes for version 4 at a later date.

SGL, together with our knowledgebase of vulnerabilities is proving very powerful to discover new issues in open-source projects.

Related Posts

By Ming Yi Ang

Ming is a security researcher who is passionate about building security automation tools to aid the discovery of various security issues. Through the discovery from the tools, he has since made contributions to various open-source projects by responsibly disclosing the vulnerability findings he encounters from his research.