无 Java 依赖的 Shiro 靶场

文章讲述了Yakit安全插件如何检测ApacheShiro的反序列化漏洞,包括ShiroRememberMe漏洞检测逻辑,使用Vulinbox靶场进行测试和验证,以及针对不按套路出牌的环境的应对策略。
摘要由CSDN通过智能技术生成

图片

背景

Apache Shiro 中一个已知的反序列化漏洞——Shiro-550,它尽管存在已久,但由于其自带的加密特性和影响力,在近几年的安全演练中受到了特别关注。Yakit 中也很早就添加了 Shiro 相关的漏洞检测插件,但在 YAK 引擎的更新迭代中,一些 bug 影响了一些漏洞的检出。为了确保我们没有无意中破坏了现有的功能(这称为回归错误),我们对一些插件进行了内置化,同时结合 vulinbox 靶场当作测试靶场,对目前的几个社区呼声较高的插件来了一波 "出厂检验"。

01 Shiro RememberMe 反序列化漏洞检测

shiro 漏洞相关的原理以及利用工具已经有很多师傅分享了。如今主流的检测 Shiro Key 的方式是由 l1nk3r师傅分享的,使用一个空的 SimplePrincipalCollection序列化后和要检测的 Key 进行加密作为 payload 发送,判断响应头中的 deleteMe 个数。

在总结和学习了很多师傅的检测逻辑后,目前 Yakit shiro 插件的检测逻辑如下:

  1. 首先发送一个 Cookie: rememberMe= 随机值,记录响应头 deleteMe 的个数

  2. 判断 Set-Cookie 中的值是 rememberMe 还是 remeberMe,作为后续的关键字

  3. 结合上一步获取的关键字,开始发送使用 Key 加密后的反序列化 SimplePrincipalCollection 数据,判断 deleteMe 的个数是否小于第一步中统计的个数,如果小于(一般是减少1)则代表本次使用的 Key 正确

  4. 通过获取的正确的 Key ,使用四条最为常见的利用链配合 Header 回显,进行盲打

  5. 如果回显盲打不成功,使用 dnslog 进行利用链的探测

使用的四条回显链分别为,CB183NOCC、CB192NOCC、CCK1、CCK2

在步骤 d 中,为了保证回显的随机性,我们执行的操作是:先加载回显的 Class 文件,在 Class 常量池中找到我们预设的常量值,替换为随机值,得到修改后的 Class 字节码。

得益于 Yaklang 完善的 java 字节码相关的基础设施,上述的操作十分的简单,仅需如下几行代码即可完成:

图片

完整的代码可以直接在 Yakit 插件商店查看

同时 Shiro 插件内也会发出至多三个风险:

当 a,b 步骤通过时,插件会发出一个风险提示——检测到 Shiro(Cookie) 框架使用

当 c 步骤通过时,插件会发出第二个风险提示——(Shiro 默认 KEY)

当 d 步骤通过时,插件会发出第三个风险提示——(Shiro Header 回显)

当 d 不通过且 e 步骤通过时,插件会发出第三个风险提示——(Shiro 利用链探测)

02 Vulinbox Shiro 靶场设计

在知道了我们 Shiro 插件的检测逻辑后,我们就可以开始写对应的靶场逻辑了,根据上面的检测逻辑,我们的靶场逻辑如下:

  1. 启动靶场时,随机使用 Shiro Key 列表中的一个当作默认的 Key,随机使用 Gadget 列表(CB183NOCC、CB192NOCC、CCK1、CCK2)中的一个,模拟可利用链

  2. 为了简单,在非在 SimplePrincipalCollection  序列化加密后的 payload 请求的响应头中添加 Set-Cookie: rememberMe=deleteMe

  3. 获取 Cookie rememberMe 的值,Base64 解码后再使用第一步中的默认 Key 进行 AES/GCM 解密

  4. 判断解密后的数据是否是一个正常的 Java 序列化对象,如果是,反序列化Java对象流,判断是否包含值为org.apache.shiro.subject.SimplePrincipalCollection 的 ClassName,如果包含,去掉响应头中的 Set-Cookie: rememberMe=deleteMe 字段

  5. 如果上一步 SimplePrincipalCollection 没有检测到,我们会根据启动时随机使用的Gadget进行判断,也就是尝试进行org.apache.commons.beanutils.BeanComparator、org.apache.commons.collections.keyvalue.TiedMapEntry、org.apache.commons.collections4.keyvalue.TiedMapEntry 的判断,以及在 Header 中回显

稍微有些复杂的是在 d,e 两步。

不过得益于 Yaklang 完善的 Java 序列化相关的基础设施,我们可以轻易地判断一个数据流是否是 Java 序列化对象流,并且将其反序列化。其实也就是早已添加在 Codec 模块中的 Java 相关的功能。

图片

现在来到了 e 步骤 :

我们使用的四条回显链分别为,CB183NOCC、CB192NOCC、CCK1、CCK2,其中

CB183 和 CB192 的 SerialVersionUID 是不一样的,所以除了类名org.apache.commons.beanutils.BeanComparator我们也要判断 SerialVersionUID , 上图中的 serial_version字段在经过转换后,其实就是常见的 -3490850999041592962 这种 SerialVersionUID 了。

UID 和 类名的问题解决了,我们开始着手构造出符合 payload 预期结果的 fake Header 回显。

熟悉这四条链的师傅应该能知道,这四条链有一个共同点,那就是可以利用 TemplatesImpl 执行字节码,可以更加直观的感受一下:

图片

发现了十分熟悉的 yv66,那接下来的思路就简单多了,反序列化 Java 对象流(也就是解密后的payload) -> 拿到 Class 字节码 -> 解析 Class 字节码 -> 遍历常量池,找到 setHeader 的传入值 -> 靶场 Server 响应头添加对应回显 -> Shiro 插件检出(Shiro Header 回显)风险。

03 Vulinbox Shiro 靶场漏洞检出

让我们直接启动靶场来看看实际的效果,先启动 Vulinbox 靶场 ,如下图,我们可以看到本次启动随机使用的 Shiro Key IduElDUpDDXE677ZkhhKnQ== 和 gadget CCK1:

图片

随后我们在 Yakit 中的插件调试功能中,选择 Shiro 插件,输入 Vulinbox 靶场中的 Shiro 地址,点击执行插件。

图片

可以发现检出了三个风险,分别是:发现 shiro 框架、发现 shiro 默认 Key 、发现 shiro 回显。

查看一下风险详细信息,Shiro Key 和利用链符合预期,响应头也存在 Vhmymv: emImhYiW。

图片

靶场效果完美符合预期,赶紧添加一个测试用例,设置检出预期值 ,提交代码后自动跑个 CI, 有了这一层保障,也不用担心再出现回归错误啦~

04 不按套路出牌的环境

在修改完插件后,为了测试其健壮性,找了一些使用了 Shiro 框架的进行测试,发现其中一个网站连 Shiro 框架都没有探测出来。

图片

经过测试发现必须在 body 中存在 rememberMe=1 或者 rememberMe=true 时,才会进入后续的 Cookie rememberMe 处理流程。

图片

勾选 Shiro 插件,开启 MITM 劫持,成功检出,这种边缘情况也确实不太好处理,好在还有被动扫描的模式。

总结

本次以 Shiro 靶场为例展开说明,其实现在内置的 4 个插件,均有对应的靶场和检出预期值

最后想说说,Yak的一些基础设施库确实很好用,很多功能都可以直接拿来即用,但是也缺少了很多接口的使用文档。未来我们不仅会持续补充和完善文档,而且也会合理利用 CI/CD 配合测试,提供插件评估机制,构建更加可靠的插件生态

Yak官方资源

Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值