On 10th of April, information regarding a Remote Code Execution (RCE) vulnerability in Apache Tomcat was published. Apache Tomcat, often referred to as Tomcat Server, is an open-source Java Servlet Container developed by the Apache Software Foundation. A quick Shodan search reveals that Apache Tomcat is deployed on over 70,000 servers.
Figure 1 Apache Tomcat has been deployed on over 70,000 servers
The vulnerability was found by an external security researcher and reported to the Apache Tomcat security team via the bug bounty program sponsored by the EU FOSSA-2 project.
Tomcat servers running on Windows platform with enableCmdLineArguments in CGI Servlet enabled are vulnerable due to a bug in the way the JRE passes command line arguments to Windows. The CGI Servlet is disabled by default.
In Apache Tomcat, file web.xml defines default values for all web applications loaded into an instance of Tomcat. One of the default servlets provided as default is the Common Gateway Includes (CGI) servlet. This servlet supports execution of external applications that conform to the CGI spec. Typically, this servlet is mapped to the URL pattern “cgi-bin/*”, which means that any CGI applications that are executed must be present within the web application. enableCmdLineArguments parameter within a CGI servlet is used to generate command line parameters generated from a query string.
The main function to create a process in Windows is CreateProcess. One of the parameters used by the CreateProcess function is lpCommandLine. This parameter contains the command line to be executed and can have a maximum length of 32,768 characters.
While creating a new subprocess, the lpCommandLine parameter can use GetCommandLine function to retrieve the command-line string for the current process. In order to provide arguments to the subprocess in the form of argc and argv, processes call the function CommandLineToArgvW which takes the supplied string and splits it into an array. It uses spaces to delineate each item in the array.
As mentioned above, the bug lies in the way JRE passes the command line arguments to Windows. The problem with using CommandLineToArgvW is that spaces within the command line are interpreted as different arguments unless they are within double quotes. Thus, creating a new subprocess without properly encoding spaces and double quotes can lead to improper conversion of command line string to arguments and create an opportunity to execute malicious code.
To mitigate against this vulnerability, the developers of Apache Tomcat modified the codebase to disallow improperly decoded arguments. They’ve introduced a new parameter within the CGI servlet. cmdLineArgumentsDecoded is used when enableCmdLineArguments is true. It defines the pattern that individual decoded command line arguments must match otherwise the request will be rejected. For the Windows platform this pattern is defined by the RegEx, “[[a-zA-Z0-9\Q-_.\\/:\E]+]”. This pattern for Windows eliminates the issues that arise from using spaces and double quotes within a command line string. For all the other platforms this pattern is defined by the RegEx, “.*”.
Figure 2 Git commit to the vulnerable CGIServlet.java file
Command execution attempts to exploit this vulnerability target applications which use CGI scripts on user provided input. Malicious requests published on the internet so far concatenate different commands together. Sample malicious requests:
BIG-IP ASM customers under any supported BIG-IP version are already protected against this vulnerability. The exploitation attempt will be detected by over 300 existing “Command Execution” attack signatures for Windows platform.
Figure 3 Attack signatures for command execution on windows platform
For customers with applications running on Apache Tomcat servers, supported BIG-IP versions contain over 150 attack signatures for Tomcat servers.
Figure 4 Attack signatures for command execution on Tomcat servers