Apache Tomcat Arbitrary Upload Vulnerability (CVE-2017-12615)
In the evening of 9/19/2017, Apache Tomcat official bulletin announced a public vulnerability advisory report. This report pointed out that if Apache Tomcat has been configured to turn on the switch of the HTTP method PUT, the current web server will face being hacked by the RCE vulnerability. And this vulnerability is granted the CVE ID 2017-12615. Hackers can use this bug to upload malicious JSP script file and achieve remote code execution.
The key to the exploitation of the vulnerability is the container needs to be turned on the HTTP method PUT. From the annotation of the file /conf/web.xml, it seems that the default value is true which means that the default condition is that the PUT method and the DELETE method is turned off.
So, the parameter readonly should be added on and given the value false so that the PUT method and the DELETE method could be turned on.
PUT /1.jsp::$DATA HTTP/1.1
PUT /1.jsp%20 HTTP/1.1
What is worth mentioning is that someone has reported the real-world vulnerability example to Wooyun platform in April 2015, however, he didn't realize that this bug is a new vulnerability in Tomcat and he has not even attributed the bug to the switch of PUT method.
We now take a code view of the vulnerability. Because the POC has been spread out, so we can firstly analyze the POC actually. From the fabricated POC, we can result that the primary point of the analysis should be focused on the url-pattern in web.xml. When the request wants to match the following url-pattern: <servlet-name>jsp</servlet-name>, the match will actually fail because the servlet-mapping will match the suffix of the file accurately. The regex in the servlet-mapping shows that it can only match suffix like .jsp or .jspx. So, the request should be forwarded by function file DefaultServlet.java rather that JspServlet.java.
Locate the file of DefaultServlet.java, the path is \src\java\org\apache\catalina\servlets\DefaultServlet.java. And then locate the doPut() function. In this function, the code firstly plays a role of judgment to ensure the value of readonly attribute and whether the input of the Fileinput I/O is null.
After the basic condition judgment, the main function put() executes. If the result of the judgment before was true, it would use the attribute rebind in resources. If not, it would use attribute bind.
Then analyze the attributes of resources. Firstly check the process of the file generation, evidently, it uses ProxyDirContext.
Locate the ProxyDirContext, the path is /src/java/org/apache/naming/resources/ProxyDirContext.java. It uses function dirContext() to definite the function bind().
Locate the dirContext() in FileDirContext.java, the path is \src\java\org\apache\naming\resources\FileDirContext.java. Check the function bind() and find that it recalls the function rebind(), it means that the function rebind() is the core function in PUT method.
Locate the function rebind(). After checking the main body of the function directly, the function creates a file but it does not validate the name of the file. So the progress can result that the POC actually exploit the bypass of the Winodows filename creation.
The Tomcat official has announced the version 7.0.81 of the product. This version has fixed the vulnerability of CVE-2017-12615. After analyzing the code of the patch it is apparently that the developers have added a condition judgment file == null in the first line of function bind() and function rebind()
Viewing the function file() remind me that using File class to create an object in java code. Trace the function file() and I found that developers actually customize a new function file() extended from the File class. The function import a test function validate() and this is the main effective point of this patch.
Bypass the Patch
PUT /1.jsp%20 HTTP/1.1
This kind of request creates a new file via bypassing the function bind(). After the use File class to creates files, Java security manager will use function normalize() to regenerate the URL path in the request. The function will delete the malicious "/" and form it into a real shell.jsp. I have reproduced the bypass in the 5.x-9.x version of Tomcat.
Temporary Bug fix
Forbid the HTTP method PUT.