从漏洞挖掘的角度深入分析shiro反序列化漏洞

前言

相信大家在找工作还是hvv面试的时候,shiro反序列化这种标志性的漏洞是最常问的,我们应该大都是通过背漏洞原理来蒙混过关,而且就在上个月也是通过shiro反序列化为入口,成功打穿一个医院的内网,最近恰好小迪老师分析了shiro反序列化漏洞,我也跟着搭建环境,深入的了解了一下这个漏洞的原理。

环境配置

idea+tomcat9+jdk1.8+shiro1.2.4

示例代码下载:https://github.com/apache/shiro/releases

示例代码位置

从漏洞挖掘的角度深入分析shiro反序列化漏洞

在idea打开并添加版本(不然会报500错误)

从漏洞挖掘的角度深入分析shiro反序列化漏洞

启动服务成功搭建好环境

从漏洞挖掘的角度深入分析shiro反序列化漏洞

shiro

介绍:

Apache Shiro 是Java 的一个安全框架。Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE 环境,也可以用在JavaEE 环境。Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与Web 集成、缓存等。简单地说就是一个身份权限验证组件

特征:

cookie中带有rememberme=字段

从漏洞挖掘的角度深入分析shiro反序列化漏洞

shiro反序列化漏洞分析

漏洞原理:

客户端:恶意序列化payload–>AES加密–>BASE64编码–>通过cookie中的rememberme字段传入

服务端:接受到cookie中的rememberme字段数据–>BASE64解码–>AES解密–>反序列化恶意payload

在整个过程中比较关键的条件就是AES加密需要知道服务端硬编码的密钥key,我们可以通过爆破等方式来获取key从而进行漏洞利用

寻找漏洞点代码位置

这里以反序列化代码审计搜索readObject()方法入手

从漏洞挖掘的角度深入分析shiro反序列化漏洞

找到了DefaultSerializer.java文件中的deserialize方法(注解如下):

public T deserialize(byte[] serialized) throws SerializationException {    // 检查传入的字节数组是否为null    if (serialized == null) {        String msg = "参数不能为null。";        throw new IllegalArgumentException(msg);    }
// 创建一个ByteArrayInputStream,将字节数组包装成输入流 ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
// 创建一个BufferedInputStream,提高读取性能 BufferedInputStream bis = new BufferedInputStream(bais);
try { // 创建一个ObjectInputStream,用于从输入流中读取对象 ObjectInputStream ois = new ClassResolvingObjectInputStream(bis);
// 使用ObjectInputStream读取对象,并进行类型转换(泛型T) @SuppressWarnings({"unchecked"}) T deserialized = (T) ois.readObject();
// 关闭ObjectInputStream ois.close();
// 返回反序列化后的对象 return deserialized; } catch (Exception e) { // 捕获异常,如果发生异常则抛出SerializationException String msg = "无法反序列化参数字节数组。"; throw new SerializationException(msg, e); }}

跟踪到AbstractRememberMeManager.java中的convertBytesToPrincipals方法调用了deserialize

从漏洞挖掘的角度深入分析shiro反序列化漏洞

可以看到传入了bytes参数

跟踪漏洞点传入的参数是否为用户可控

跟进看看bytes是否可控 同文件下的getRememberedPrincipals方法定义了bytes然后调用convertBytesToPrincipals方法给bytes解密

从漏洞挖掘的角度深入分析shiro反序列化漏洞

DefaultSecurityManager.java文件中的getRememberedIdentity方法调用了getRememberedPrincipals

从漏洞挖掘的角度深入分析shiro反序列化漏洞

继续跟进 同文件下的resolvePrincipals方法调用了getRememberedIdentity

从漏洞挖掘的角度深入分析shiro反序列化漏洞

同文件下的createSubject方法调用了resolvePrincipals

从漏洞挖掘的角度深入分析shiro反序列化漏洞

同文件下的login方法调用了createSubject

从漏洞挖掘的角度深入分析shiro反序列化漏洞

传入了token, info, subject 

继续跟进login方法

并没有搜索到哪里调用了login方法传参了,换个思路

从漏洞挖掘的角度深入分析shiro反序列化漏洞

由方法名可推测,登录处肯定是会调用该方法,采用断点动态调试功能跟踪

从漏洞挖掘的角度深入分析shiro反序列化漏洞

输入测试用的账号密码 点击登录

从漏洞挖掘的角度深入分析shiro反序列化漏洞

成功断下来了,可以看到token是我们输入的账号密码等等参数值

从漏洞挖掘的角度深入分析shiro反序列化漏洞

接下来逆着往回走看看token和subject是从哪里传入的

从漏洞挖掘的角度深入分析shiro反序列化漏洞

继续步出 ,从动态调试可以看到是AuthenticatingFilter类中的executelogin方法调用了login

从漏洞挖掘的角度深入分析shiro反序列化漏洞

之前为什么没搜到呢,查看该文件路径,发现和之前搜索路径有出入

从漏洞挖掘的角度深入分析shiro反序列化漏洞
从漏洞挖掘的角度深入分析shiro反序列化漏洞

我们采用动态调试的方法找到了该文件,阅读该方法代码 可以看到token是从createToken方法中得到的,继续跟踪createToken方法

从漏洞挖掘的角度深入分析shiro反序列化漏洞

到这里我们终于跟踪到了反序列化对象在哪里传入,并且是参数可以由我们控制的,可以构造恶意的序列化payload传入即可造成反序列化漏洞

总结图

从漏洞挖掘的角度深入分析shiro反序列化漏洞

构造恶意的序列化payload

构造前提

在我们跟踪传入的参数的时候发现,该参数经过了很多方法的处理,其中包括比较敏感的decrypt(解密)等方法,那我们构造payload时必然要用加密函数处理才能将正确的序列化payload传入deserialize方法。

寻找加密函数

我们在跟踪漏洞点的时候可以看到decrypt方法上面就有一个encrypt方法

从漏洞挖掘的角度深入分析shiro反序列化漏洞

最简单的判断加密方式的方法:在此下断点,动态调试,看看在加密的时候都传入了什么参数进而来判断加密方式

从漏洞挖掘的角度深入分析shiro反序列化漏洞

由名称(密码服务)和稍微了解过密码学的应该可以一眼丁真看出是AES加密的cbc模式。

我们对payload进行aes加密然后让服务端正常解密的话,需要知道AES的密钥(key),这个是硬编码在代码中的,我们在动态调试的参数中也能看到

从漏洞挖掘的角度深入分析shiro反序列化漏洞

但是这个key是以字节数组的形式,我们用脚本转换为真正的key:

kPH+bIxk5D2deZiIxcaaaA==

从漏洞挖掘的角度深入分析shiro反序列化漏洞

当然我们也可以跟踪代码在代码中找到硬编码的key

从漏洞挖掘的角度深入分析shiro反序列化漏洞

这样我们就解决了加密

base64解码方法

跟踪的过程中还有一个敏感方法处理了参数

从漏洞挖掘的角度深入分析shiro反序列化漏洞

跟进这个方法可以看到是对cookie中的rememberme值做了base64解码

从漏洞挖掘的角度深入分析shiro反序列化漏洞

那我们构造payload就要进行base64编码

整个流程

再回到漏洞原理就已经能彻底理解了

客户端:恶意序列化payload–>AES加密–>BASE64编码–>通过cookie中的rememberme字段传入

服务端:接受到cookie中的rememberme字段数据–>BASE64解码–>AES解密–>反序列化恶意payload

dnsurl链测试漏洞

生成dnsurl序列化payload

从漏洞挖掘的角度深入分析shiro反序列化漏洞
从漏洞挖掘的角度深入分析shiro反序列化漏洞

将此payload进行aes加密和base64编码

从漏洞挖掘的角度深入分析shiro反序列化漏洞

通过cookie传入服务端

从漏洞挖掘的角度深入分析shiro反序列化漏洞

成功利用

从漏洞挖掘的角度深入分析shiro反序列化漏洞

接下来就是寻找反序列化链条执行命令,下篇再更新~

文末

感谢各位师傅们能看到文末,从刚开始学习网安交的第一个弱口令漏洞到现在正好一年,感觉反序列化漏洞相对其他漏洞来说应该是较难的,希望各位师傅都能坚持下去一起学习!

愿我们都能以拿到第一台机器shell的热情继续学习下去,为网上家园筑起属于我们的安全堤坝!

原文始发于微信公众号(艾克sec):从漏洞挖掘的角度深入分析shiro反序列化漏洞

版权声明:admin 发表于 2023年12月3日 下午5:57。
转载请注明:从漏洞挖掘的角度深入分析shiro反序列化漏洞 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...