shiro-1.2.4反序列化漏洞分析

漏洞分析

将断点下在DefaultSecurityManager类的resolvePrincipals方法中

可控的cookie

shiro-1.2.4反序列化漏洞分析_第1张图片

第一步检查了是否principals为空

什么是principals:可以将shiro中的principals理解为已经成功登陆的用户的一个上下文,保存了认证用户的一些环境

  1. 如果principals为空的话,也就是当前用户没有已经认证的上下文,然后检查是否设置了rememberMe,也就是getRememberedIdentity方法
  2. shiro-1.2.4反序列化漏洞分析_第2张图片
    image.png

在这里,获取rememberMeManager,并且从rememberMeManager中获取认证用户的信息

  1. shiro-1.2.4反序列化漏洞分析_第3张图片
    image.png

    可以看到通过getRememberedSerializedIdentity取得了bytes变量的值,进去看看getRememberedSerializedIdentity是怎么取值的

shiro-1.2.4反序列化漏洞分析_第4张图片
image.png

这个地方是重点:
可以看到,通过WebUtils这个工具类获取了原生的res和req,然后从其中读取了cookie的值

shiro-1.2.4反序列化漏洞分析_第5张图片
image.png

在readValue中,获取了name为rememberMe的cookie的值,也就是我们在登陆的时候,如果选择rememberMe在cookie中生成的值,最后将cookie的值返回

image.png

硬编码的AES的key

现在我们返回了一个经过base64编码后的加密字符串,接下来对获取到的cookie值进行aes解密

  1. 先进行base64解码


    shiro-1.2.4反序列化漏洞分析_第6张图片
    image.png

    第一步先进行padding确保正确的base64解码结果,之后调用Base64.decode进行base64解码

  2. 进入Base64.decode函数


    image.png

    对获取到的字符串将其转换为byte数组

之后调用参数为字节数组的decode方法


shiro-1.2.4反序列化漏洞分析_第7张图片
image.png

在这个方法中,将这个字节数组进行base64解码,并且返回对应解码后结果的字节数组

  1. 再回到getRememberedPrincipals方法中,这一步我们已经获取到了base64解码以后的字节数组


    shiro-1.2.4反序列化漏洞分析_第8张图片
    image.png

之后需要将这个字节数组变为principals对象

  1. 进入convertBytesToPrincipals


    shiro-1.2.4反序列化漏洞分析_第9张图片
    image.png

    image.png

可以看到getCipherService的返回值为aes加密服务

继续跟入decrypt函数

shiro-1.2.4反序列化漏洞分析_第10张图片
image.png

如果cipherService不为空的时候,会调用对应cipherService的decrypt函数

在这里我们需要传入一个加密的字节数组,一个解密的key

  1. 进入getDecryptionCipherKey函数,看一下怎么获取到解密的key


    image.png

这里直接返回了对应的decryptionCipherKey属性,看下这个属性是怎么被赋值的


image.png

通过调用setDecryptionCipherKey来赋值,再搜索setDecryptionCipherKey的调用


shiro-1.2.4反序列化漏洞分析_第11张图片
image.png

通过setCipherKey来赋值,继续寻找setCipherKey的调用
shiro-1.2.4反序列化漏洞分析_第12张图片
image.png

可以发现,在类的构造方法中,对Key进行了赋值,而且这个key是一个常量,跟入看一下这个常量的值


image.png

可以发现,这个key的值是硬编码的一段字符串,而aes是对称加密算法,我们可以自己去伪造rememberMe的值
  1. 进入对应的decrypt方法


    shiro-1.2.4反序列化漏洞分析_第13张图片
    image.png

这里进行了iv的初始化,可以看到iv的值,之后调用了decrypt方法

  1. shiro-1.2.4反序列化漏洞分析_第14张图片
    image.png

在这里进行了cookie的解密,可以通过动态调试获取到所有解密所需的key,iv,加密模式,最后获取到解密以后的数据

反序列化

image.png

可以看到获取到的byteSource中有一段很熟悉的特征:rO0AB...,这是java序列化后的数据,这代表了,解密以后的数据其实是一个java对象序列化之后的结果,那么在之后必定会进行java序列化对象的反序列化操作,继续向下跟

shiro-1.2.4反序列化漏洞分析_第15张图片
image.png

在这个地方调用了deserialize方法对获取到的数据进行反序列化操作

image.png

看一下getSerializer()的返回值


image.png

所以进入DefaultSerializerdeserilize方法:


shiro-1.2.4反序列化漏洞分析_第16张图片
image.png

image.png

image.png

将解密的数据用ObjectInputStream包装,并且调用了readObject方法,也就是反序列化的入口点

为什么可以利用

可以看到,整个漏洞是由几个漏洞串联起来的:

  1. Cookie的内容是用户可控的
  2. 最重要的一个地方:Cookie的加密字符串是硬编码的,所以导致我们可以任意伪造RememberMe Cookie的值
  3. 因为这个Cookie加密的其实是一个序列化后的对象,所以在后面进行反序列化的时候,因为我们可以伪造cookie,那么我们也就可以控制反序列化时候的对象,从而导致反序列化漏洞

你可能感兴趣的:(shiro-1.2.4反序列化漏洞分析)