Loading

Shiro 550反序列化漏洞分析

Shiro 550反序列化漏洞分析

一、漏洞简介

影响版本:Apache Shiro < 1.2.4

特征判断:返回包中包含rememberMe=deleteMe字段。

Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。
那么,Payload产生的过程:

命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值

在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,Payload构造起来也是十分的简单。

二、环境搭建

下载后用idea配置tomcat启动:https://github.com/Medicean/VulApps/tree/master/s/shiro/1

image-20210928220044865

利用工具:https://github.com/wyzxxz/shiro_rce_tool

image-20210930144244696

三、漏洞分析

shiro会提供rememberme功能,可以通过cookie记录登录用户,从而记录登录用户的身份认证信息,即下次无需登录即可访问。而其中对rememberme的cookie做了加密处理,漏洞主要原因是加密的AES密钥是硬编码在文件中的,那么对于AES加密算法我们已知密钥,并且IV为cookie进行base64解码后的前16个字节,因此我们可以构造任意的可控序列化payload。

  • 通过在cookie的rememberMe字段中插入恶意payload,

  • 触发shiro框架的rememberMe的反序列化功能,导致任意代码执行。

  • shiro 1.2.24中,提供了硬编码的AES密钥:kPH+bIxk5D2deZiIxcaaaA==

1)加密过程

处理rememberme的类为org.apache.shiro.web.mgt.CookieRememberMeManager,它继承AbstractRememberMeManager类,当登录成功并且勾选了rememberme选项,那么此时将进入onSuccessfulLogin方法

image-20210930145350773

把断点下到rememberIdentity后,跟进rememberIdentity方法

image-20210930150030956

继续跟进rememberIdentity方法后,可以看到调用了convertPrincipalsToBytes方法后得到了个bytes,然后传入了rememberSerializedIdentity

image-20210930150117056

其实在convertPrincipalsToBytes中进行了加密操作,我们可以跟进查看

image-20210930150327306

可以看到通过序列化拿到了个bytes,然后在362行进行了encrypt操作,这里就是加密进行的地方了,跟进查看

image-20210930150940274

看471行,拿到了个CipherService类,这个类就是用来进行加密的,打开可以看到加密模式为CBC,Padding规则是PKCS5,加密方式为AES

image-20210930151207547

然后473行进行了加密操作,查看在其参数中的getEncryptionCipherKey方法,这个方法就是用来获取密钥的,此密钥硬编码在了类中,并进行了base64编码

image-20210930152334108

回到之前的encrypt方法中,等加密完成后,把值return给了前面说的的bytes,然后传进了rememberSerializedIdentity方法

image-20210930152813892

rememberSerializedIdentity方法中,把加密的字符串进行了Base64编码,然后设置到了cookie中

image-20210930152858104

2)解密过程

在shiro中,解密过程就是和加密过程相反的了,解密过程在AbstractRememberMeManager#getRememberedPrincipals方法中

image-20210930154228507

首先调用getRememberedSerializedIdentity方法,方法中获得了cookie中的rememberMe的值然后进行base64解码并返回给了bytes

image-20210930154613502

第二步就是调用convertBytesToPrincipals方法来进行解密

image-20210930154747209

跟进convertBytesToPrincipals方法

image-20210930154814180

先进行了decrypt解密,然后再进行的deserialize反序列化。

查看decrypt,这里和之前加密过程步骤差不多,用的密钥都是同一个

image-20210930155113371

查看反序列化方法deserialize

image-20210930155502621

getSerializer()返回的是一个默认的序列化对象DefaultSerializer

image-20210930155550111

跟进DefaultSerializer#deserialize看到了熟悉的反序列化

image-20210930155831320

四、漏洞修复

Apache Shiro 1.2.5版本的源码,修复方法就是shiro每次启动,都会随机生成一个新的key:https://github.com/apache/shiro/commit/4d5bb000a7f3c02d8960b32e694a565c95976848

img

posted @ 2021-10-07 22:32  Atomovo  阅读(846)  评论(0编辑  收藏  举报