shiro反序列化命令执行漏洞
2016年,序列行漏Apache Shiro 1.2.4版本被曝出一个编号为CVE-2016-4437的化命漏洞。攻击者构造一个恶意的令执序列化对象,Base64编码后塞进Cookie里的序列行漏rememberMe字段,服务端反序列化时直接触发远程命令执行。化命这个漏洞的令执根因在于Shiro使用了硬编码的AES密钥——默认key是"kPH+bIxk5D2deZiIxcaaaA==",而很多开发者从未修改过它。序列行漏 Shiro的化命RememberMe功能本意是让用户勾选"记住我"后,下次访问不用重新登录。令执流程大致是序列行漏这样:用户登录成功后,Shiro把身份信息序列化,化命用AES加密,令执再Base64编码,序列行漏写入Cookie。化命下次请求带着这个Cookie过来,令执Shiro取出密文,Base64解码,AES解密,然后反序列化还原对象。问题就卡在最后一步——Java反序列化本身不校验数据来源,只要字节流符合序列化格式,就能还原成对象。如果攻击者能控制这个字节流,就能构造一条利用链,在反序列化过程中执行任意代码。 Shiro在1.2.4及之前的版本中,AES密钥直接写死在代码里。虽然官方在1.2.5版本开始改为随机生成密钥,但大量老系统没有升级,或者升级后没有重新配置密钥,仍然沿用默认值。攻击者拿到这个公开的密钥,就能自己加密恶意payload,服务端解密后照单全收。 实际攻击中,利用工具如ysoserial可以生成各种利用链的payload。常见的包括CommonsCollections、CommonsBeanutils等,具体用哪条链取决于目标环境classpath里有哪些库。生成payload后,用默认密钥AES加密,Base64编码,作为rememberMe Cookie的值发送出去。如果目标存在漏洞,命令就会被执行。 我见过一个真实案例:某企业内网系统用了Shiro 1.2.4,运维人员觉得内网安全就没管。结果攻击者通过一个SSRF漏洞跳到内网,再配合Shiro反序列化,直接拿到了服务器权限。整个链条里,Shiro这个点成了最关键的突破口。 最直接的方式是发送一个rememberMe Cookie,观察响应。如果返回的Set-Cookie里rememberMe的值被清空或者变成deleteMe,说明服务端尝试反序列化但失败了,可能存在漏洞。更准确的方法是使用Burp插件或专门的检测工具,它们会生成一个DNSlog payload,如果收到DNS请求,就确认漏洞存在。 不过要注意,有些WAF会拦截rememberMe里的恶意内容。这时候可以尝试改变payload的编码方式,或者分段发送。另外,Shiro的版本信息不一定暴露在响应头里,需要结合其他指纹来判断。 升级到Shiro 1.2.5以上版本能解决默认密钥的问题,但还不够。新版本允许自定义密钥,如果开发者图省事继续用默认的或者简单的密钥,风险依然存在。正确的做法是生成一个足够随机的AES密钥,通过配置文件或环境变量注入,并且定期轮换。 另一个思路是禁用RememberMe功能。如果业务上不需要,直接在配置里关掉,省心。如果必须用,可以考虑实现自定义的Serializer,在反序列化前做白名单校验。但这需要改代码,很多团队不愿意动。 还有个细节:Shiro的rememberMe Cookie默认是Base64编码的,但有些中间件或框架会对Cookie做额外处理。攻击者有时候需要调整payload的长度或填充方式,才能绕过这些限制。这说明漏洞利用不是一成不变的,得根据目标环境灵活调整。 Shiro反序列化漏洞从2016年到现在,依然是渗透测试中的高频考点。根本原因不是技术多复杂,而是默认配置不安全加上升级不及时。很多系统上线后就没再动过,密钥还是那个密钥,版本还是那个版本。攻击者不需要多高明的手段,只要知道这个默认密钥,就能轻松得手。密钥硬编码是致命伤
怎么判断目标有没有问题
修复不只是升级版本
-
上一篇
-
下一篇
- 随机阅读
- 搜索
-
- 友情链接
-