Shiro550

shiro550和fastjson作为攻防演练的利器,前面学习了fastjson的相关利用和回显,本篇主要来学习一下shiro550的漏洞原理。

1、漏洞原因

在 Shiro <= 1.2.4 中,AES 加密算法的key是硬编码在源码中,当我们勾选remember me 的时候 shiro 会将我们的 cookie 信息序列化并且加密存储在 Cookie 的 rememberMe字段中,这样在下次请求时会读取 Cookie 中的 rememberMe字段并且进行解密然后反序列化,且AES的key 为固定的。

2、环境搭建及复现

https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
jdk1.7
Tomcat8
idea

坑点

原有版本的jstl会报错修改为1.2

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 依赖cc链 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>

toolchains的错误

<?xml version="1.0" encoding="UTF8"?>
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>1.6</version>
<vendor>sun</vendor>
</provides>
<configuration>
<jdkHome>/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk</jdkHome>
</configuration>
</toolchain>
</toolchains>

然后启动即可

漏洞复现

3、漏洞分析

3.1、生成cookie

3.1.1、原理解析

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

cookie的处理类org.apache.shiro.web.mgt.CookieRememberMeManager类出现了漏洞,而它继承了AbstractRememberMeManager类。

处理rememberme的cookie的类为org.apache.shiro.web.mgt.CookieRememberMeManager,其中的rememberSerializedIdentity方法,主要就是设置用户的cookie的值,这个值是通过base64解密serialized获取的。

我们继续看看父类

首先定义默认的秘钥通过base64固定解码得到,这个就是我们上门工具爆破出来的秘钥

还有就是方法 onSuccessfulLogin,这方法就是登录成功的意思,判断isRememberMe,该方法就是判断token中是够含rememberMe。所以当我们成功登录时,如果勾选了rememberme选项,那么此时将进入onSuccessfulLogin方法

我们继续往下走,跟进rememberIdentity方法,这三个参数上面有解释我,我的理解是

subject:就是rememberMe字段的主体
token:成功的身份令牌
authcInfo:成功的身份验证信息

然后进入方法体,获取验证身份的主体,继续调用重载方法,再跟进去看看

进入后我看到,把accountPrincipals(身份验证信息)转成了byte字节,然后就是调用我们一开始分析的rememberSerializedIdentity方法设置cookie的值了。

这就是生成cookie的过程,但是还是有些疑惑,convertPrincipalsToBytes是怎么实现的和默认秘钥在哪里使用了,我们在org.apache.shiro.mgt.AbstractRememberMeManager的onSuccessfulLogin方法打下断点看看。

3.1.1、idea调试

首先我们idea调试启动,然后勾选Rememberme,登录。

成功捕获断点,跟进去

跟我们上面分析的一样,我们直接跟进convertPrincipalsToBytes方法

我们先跟进serialize,看他怎么序列化数据的

获取序列化对象继续调用serialize,跟进去

看到这我们就能很清晰的看到他是怎么序列化数据的了。我们继续回到convertPrincipalsToBytes方法

接着判断getCipherService是否为空,字面意思就是获取密码算法服务,我们也跟进去看看

直接返回了加密算法服务,在注解中也可以看到,为CBC模式的AES算法。那他在哪里定义的呢

我们看到在构造方法中,创建了AES加密服务,并且设置了加密服务的key,这个key就是我们上面定义的。

我们继续返回convertPrincipalsToBytes方法中。看到其使用了encrypt方法对序列化后的principals进行加密,我们也跟进去看看。

首先还是获取了加密算法服务(AES),调用该算法的加密方法encrypt,这个算法有两个参数,第一个我们知道就是序列化的字节码,我们看第二个,英文意思是获取加密算法的key,我们继续跟进去

我们看到直接返回了加密key,这个key是通过setEncryptionCipherKey设置的,而setCipherKey调用了setEncryptionCipherKey,也就是我们在encrypt方法中的getCipherService方法设置的.

我们继续回到encrypt方法,参数是 bytes和key继续跟进

判断是够创建初始化载体,我们跟进generateInitializationVector

他会调用父类的generateInitializationVector,继续跟进

我们可以看到,size为128(定义的静态字符串),然后新建长度为16的字节数组,调用了ensureSecureRandom,跟进看看

就是获取一个随机值,nextBytes方法用于生成随机字节并将其置于用户提供的字节数组

然后返回,所以ivBytes就是一个随机的16位字节数组

我们继续回到encrypt,然后调用重载方法,参数为byte数组、key,16为的随机字节数组ivBytes和布尔true。我们继续跟进

encrypt就是我们最终的加密实现算法。把ivbytes和encrypted一起放入output,然后返回

最后通过rememberSerializedIdentity设置cookie值

上面都是序列的过程,那么在那里反序列化呢

3.3、解析cookie

org.apache.shiro.mgt.AbstractRememberMeManager#getRememberedPrincipals的方法中,会从cookie中获取身份信息,我们在此打下断点,然后刷新web页面,成功捕获,会通过org.apache.shiro.web.mgt.CookieRememberMeManager类的getRememberedSerializedIdentity方法获取bytes,我们也跟进去看看

可以看到该类会获取cookie,然后解密base64加密的字段,获取字节数组返回。

我们继续返回其父类org.apache.shiro.mgt.AbstractRememberMeManager#getRememberedPrincipals的方法中,会调用convertBytesToPrincipals方法,跟生成cookie相反,我们也跟进去看看。

重复代码不再一一解释,直接进入decrypt方法

发现跟加密一样,通过decrypt解密AES。然后返回

然后反序列化解密的字符串

最后调用readObject方法,造成反序列化。

值得注意的是该readObejct方法,是shiro重写过的,重写了resolveClass函数,调用了ClassUtils.forName(),而原生的则是Class.forName().所以导致很多链用不了 ,也是为什么要导入cc4的组件了。我们来看看ClassUtils.forName()

看到org.apache.shiro.util.ClassUtils的forName()方法,他是调用了而ClassLoader.loadClass,该方法不支持装载数组类型的class,也就是cc1、cc3等用的Transform数组类都不行了,但是cc2和cc4是可以的 ,其利用的是javassist的TemplateImpl类实现的,所以不影响。

还有就是通过改造利用链实现shiro原生的命令执行,具体查看https://www.anquanke.com/post/id/192619#h2-3。

参考

https://y4er.com/post/shiro-rememberme-rce/

https://www.cnblogs.com/nice0e3/p/14183173.html

https://xz.aliyun.com/t/6493

https://www.anquanke.com/post/id/192619#h2-3

shiro550反序列学习的更多相关文章

  1. JDK7u21反序列链学习

    JDK7u21 1.前置知识 jdk7u21是一条不依赖CommonsCollections库依赖的,看利用链所有知识其实跟CommonsCollections也有重复,我们来学习一下以前没学过的类或 ...

  2. Fastjsonfan反序列链学习前置知识

    Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...

  3. CommonsCollection2反序列链学习

    CommonsCollection2 1.前置知识 CmonnosCollection2需要用到Javassist和PriorityQueue 1.1.Javassist Javassist是一个开源 ...

  4. PHP反序列漏洞学习

    0x00 序列化和反序列化 在PHP中,序列化和反序列化对应的函数分别为serialize()和unserialize(). 序列化:serialize()将对象转换为字符串以便存储传输的一种方式. ...

  5. 通过WebGoat学习java反序列化漏洞

    首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...

  6. web渗透学习目录

    一,基础学习 01.基础学习 [[编码总结]] [[JSON三种数据解析方法]] [[js加密,解密]] [[Internet保留地址和非保留地址.内网和公网.VNC和UltraVN]] 代理 [[S ...

  7. WCF学习之旅—WCF第二个示例(五)

    二.WCF服务端应用程序 第一步,创建WCF服务应用程序项目 打开Visual Studio 2015,在菜单上点击文件—>新建—>项目—>WCF服务应用程序.在弹出界面的“名称”对 ...

  8. Redis学习笔记二

    学习Redis添加Object时,由于Redis只能存取字符串String,对于其它数据类型形容:Int,long,double,Date等不提供支持,因而需要设计到对象的序列化和反序列化.java序 ...

  9. Node.JS 学习路线图

    转载自:http://www.admin10000.com/document/4624.html 从零开始nodejs系列文章, 将介绍如何利Javascript做为服务端脚本,通过Nodejs框架w ...

随机推荐

  1. [源码解析] TensorFlow 分布式环境(5) --- Session

    [源码解析] TensorFlow 分布式环境(5) --- Session 目录 [源码解析] TensorFlow 分布式环境(5) --- Session 1. 概述 1.1 Session 分 ...

  2. Bean实例化方式

    https://blog.csdn.net/diaosinixiheixiu/article/details/78919395 https://www.cnblogs.com/deng-cc/p/89 ...

  3. 生命周期内create和mounted的区别?

    created: 在模板渲染成html前调用,即通常初始化某些数据,然后再渲染成视图. mounted: 在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作 ...

  4. SpringBoot与SpringCloud的关系与区别?

    一.SpringBoot和SpringCloud简介 1.SpringBoot:是一个快速开发框架,通过用MAVEN依赖的继承方式,帮助我们快速整合第三方常用框架,完全采用注解化(使用注解方式启动Sp ...

  5. Java中hashCode、equals、==的区别

    ref:http://www.cnblogs.com/skywang12345/p/3324958.html 1.==作用: java中的==用来判断两个对象的地址是否相等:当对象是基本数据类型时,可 ...

  6. CEPH-3:cephfs功能详解

    ceph集群cephfs使用详解 一个完整的ceph集群,可以提供块存储.文件系统和对象存储. 本节主要介绍文件系统cephfs功能如何灵活的使用,集群背景: [cephadmin@yq01-aip- ...

  7. apollo规划控制视频-13 motion planning with autonomous driving

  8. ROS机器人操作系统相关书籍、资料和学习路径

    作者:Top Liu链接:https://zhuanlan.zhihu.com/p/30391098来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 本文是易科机器人实验 ...

  9. 让弹幕给 PPD 生个孩子

    怎样才能跑起来我写的弹幕程序 资源下载 申请野狗后端云账号注册 创建应用: 复制appId到index.html的 var ref = new Wilddog("https://<ap ...

  10. Java/C++实现命令模式---多次撤销和撤回

    某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对象,并通过该命令集合实现多次undo()和redo()操作,可以使用加法运算来模拟实现.\ 类图: Java代码: ...