
新做的海报,比较精简了这个。
文章目录
-
-
- 0、前言
- [1、什么是 Apache Shiro?](#1、什么是 Apache Shiro?)
- [2、什么是 Java 序列化与反序列化?](#2、什么是 Java 序列化与反序列化?)
- [3、什么是 Java 反序列化漏洞?](#3、什么是 Java 反序列化漏洞?)
- [4、Shiro 反序列化漏洞核心原理](#4、Shiro 反序列化漏洞核心原理)
-
- [1、正常的 RememberMe 免登录流程](#1、正常的 RememberMe 免登录流程)
- 2、两个致命的漏洞核心
- [缺陷 2:反序列化无任何安全校验](#缺陷 2:反序列化无任何安全校验)
- 5、完整的攻击流程
- 6、漏洞家族与影响范围
- 7、小结
-
0、前言
这是 Java Web 安全领域最经典、最常见的远程代码执行(RCE)漏洞之一,攻击者可通过该漏洞直接控制目标服务器。
虽然知识比较基础,但是依旧要声明,保护网络安全,是网络知识的正确用法。
1、什么是 Apache Shiro?
Apache Shiro 是 Java 生态里应用最广泛的轻量级安全框架,比 Spring Security 更简单易用,绝大多数 Java Web 项目都会用它来实现:
- 用户登录身份认证
- 页面 / 接口权限控制
- 会话管理
- 加密功能
其中,记住我(RememberMe)免登录功能,就是这个漏洞的唯一入口。
2、什么是 Java 序列化与反序列化?
- 序列化:将 Java 对象转换成字节流,用于网络传输、文件存储、数据库保存。
- 反序列化:将字节流还原成 Java 对象,在内存中恢复对象的所有信息。
而这个漏洞之所以是反序列化漏洞,是因为Java 在反序列化一个对象时,会自动执行这个对象里的readObject()方法。如果这个方法里写了恶意代码,反序列化的瞬间就会被执行!
3、什么是 Java 反序列化漏洞?
如果攻击者能完全控制反序列化的输入(也就是那个字节流),就能构造一个恶意的 Java 对象,在里面写入要执行的系统命令(比如创建管理员、打开远程控制、删除文件)。
目标服务器拿到这个恶意字节流,反序列化的时候,就会自动执行恶意代码,服务器直接被攻击者控制,这就是远程代码执行(RCE)漏洞。
4、Shiro 反序列化漏洞核心原理
最经典的核心漏洞编号为CVE-2016-4437(俗称 Shiro-550),后续所有的 Shiro 反序列化漏洞,都是基于这个核心原理的补丁绕过。
1、正常的 RememberMe 免登录流程
漏洞完全是围绕 RememberMe 功能的流程展开的,必须先看懂正常业务的完整步骤:
1、用户登录网站,勾选「记住我」,输入账号密码登录成功。
2、Shiro 把用户的身份信息(用户名、权限等)序列化成字节流。
3、用AES 对称加密算法对字节流加密(加密和解密用同一个密钥)。
4、把加密后的字节流做 Base64 编码,变成一串可读的字符串。
5、把这个字符串放到 Cookie 中,命名为rememberMe,下发给用户浏览器。
6、用户下次访问网站,浏览器自动携带这个rememberMe Cookie。
7、Shiro 收到 Cookie 后,执行反向操作:Base64 解码 → AES 解密 → 反序列化,还原出用户身份,实现免密登录。
2、两个致命的漏洞核心
Shiro 的设计缺陷,让攻击者可以完美模仿这个流程,构造恶意请求:
缺陷 1:硬编码的全局默认密钥(最核心)
Shiro 1.2.4 及更早的版本,把 AES 加密的密钥直接写死在了开源源码里,全世界所有人都能拿到这个密钥:
python
kPH+bIxk5D2deZiIxcaaaA==
这意味着,任何人都能用这个密钥,加密自己构造的恶意数据,让服务器完美解密通过。
缺陷 2:反序列化无任何安全校验
Shiro 拿到解密后的数据,直接无脑执行反序列化,没有任何校验:
- 不检查数据是不是合法的用户身份信息
- 不限制只能反序列化哪些可信的类
- 不校验数据有没有被篡改
只要数据能解密成功,就直接反序列化,攻击者构造的恶意对象会被完美执行。
5、完整的攻击流程
攻击者利用漏洞的完整步骤,完全对应正常的业务流程,只是把用户身份信息换成了恶意代码:
- 1、构造恶意 Payload:用工具(ysoserial)生成恶意序列化对象(也叫「利用链 / Gadget Chain」,比如常用的 CC 链、CB 链),里面写入要执行的系统命令(比如反弹 shell、执行 ping 命令)。
- 2、加密恶意数据:用 Shiro 的默认密钥,对恶意序列化对象进行 AES 加密(和 Shiro 的加密模式完全一致:AES-CBC,PKCS5Padding 填充)。
- 3、编码生成 Cookie:把加密后的字节流做 Base64 编码,生成最终的rememberMe Cookie 值。
- 4、发送恶意请求:把构造好的 Cookie 放到 HTTP 请求中,发送给目标网站。
- 5、服务器触发漏洞:Shiro 按正常流程处理:Base64 解码 → AES 解密(密钥正确,解密成功) → 反序列化恶意对象。
- 6、获得服务器控制权:反序列化时,恶意对象的readObject()方法被执行,攻击者的命令在服务器上运行,目标服务器被完全控制。
6、漏洞家族与影响范围
除了核心的 Shiro-550,官方修复后又出现了多次补丁绕过,形成了完整的漏洞家族:
| 漏洞编号 | 俗称 | 影响版本 | 核心原理 |
|---|---|---|---|
| CVE-2016-4437 | Shiro-550 | Shiro ≤ 1.2.4 | 默认硬编码 AES 密钥,无反序列化校验,最核心的基础漏洞 |
| CVE-2019-12422 | Shiro-721 | 1.2.5 ≤ Shiro ≤ 1.4.1 | 修复了硬编码密钥,但 AES-CBC 模式存在填充提示攻击,可通过合法 Cookie 爆破出密钥 |
| CVE-2020-1957 | Shiro ≤ 1.5.3 | 绕过官方的类黑名单校验,可利用新的利用链触发反序列化 | |
| CVE-2021-41303 | Shiro ≤ 1.7.1 | 再次绕过补丁,通过特定加密模式和利用链触发漏洞 |
无论 Shiro 版本多新,只要 AES 密钥泄露(默认密钥、弱密钥、配置文件泄露等),就一定存在反序列化漏洞! 版本升级只是修复了默认硬编码的问题,解决不了密钥泄露后的根本风险。
不是所有用 Shiro 的网站都能被攻击,必须同时满足:
1、目标开启了 RememberMe 功能。
2、攻击者获取到了 AES 加密密钥(默认密钥、弱密钥爆破、密钥泄露等)。
3、目标项目里存在可用的反序列化利用链(比如引入了 Commons-Collections、Commons-Beanutils 等依赖包)。
7、小结
学习复现环境建议是Vulhub。
工具比较推荐
- ShiroAttack2
- ysoserial
至于Burp Suite这样的工具,都是必备的,不过多罗列。