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. Prometheusbu部署使用-1

    Prometheus+grafana部署使用 主机列表: 192.168.161.130 : Prometheus 192.168.161.128 : node-1 192.168.161.129 : ...

  2. 什么是feigin?它的优点是什么?

    1.feign采用的是基于接口的注解2.feign整合了ribbon,具有负载均衡的能力3.整合了Hystrix,具有熔断的能力使用:1.添加pom依赖.2.启动类添加@EnableFeignClie ...

  3. Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?

    配置变更JDK 版本升级第三方类库升级响应式 Spring 编程支持HTTP/2 支持配置属性绑定更多改进与加强-

  4. sudo rosdep init 出现 ERROR: cannot download default sources list from:错误解决方法

    关于安装ROS时出现的rosdep init错误 sudo rosdep init ERROR: cannot download default sources list from: https:// ...

  5. 推荐一款强大的轻量级模块化WEB前端快速开发框架--UIkit

    前言 今天给大家分享一款强大的轻量级模块化WEB前端快速开发框架--UIkit 到目前(2016-06-20)为止,UIkit在github上的Forks已达到了1350个,而Stars更是达到了69 ...

  6. html和css常见的一些问题总结

    html 标签 一般在html有块级元素和行级元素,主要的块级元素有 div,p,h1-h6,ul,ol,li,dl,dt,dd,table,tr,th,td,有好记的办法,div,p,显示标题的,列 ...

  7. Vue-router实现单页面应用在没有登录情况下,自动跳转到登录页面

    这是我做前端一来的第一篇文章,都不知道该怎么开始了.那就直接奔主题吧.先讲讲这个功能的实现场景吧,我们小组使用vue全家桶实现了一个单页面应用,最初就考虑对登录状态做限制.比如登录后不能后退到登录页面 ...

  8. linux安装sbt

    1.官网下载tgz sbt - Download (scala-sbt.org) 2.解压 tar zxvf sbt-0.13.5.tgz -C /opt/scala/ 3.建立启动sbt脚本 /*选 ...

  9. 横竖屏切换android:screenOrientation属性的使用

    在开发android的应用中,有时候需要限制横竖屏切换,只需要在AndroidManifest.xml文件中加入android:screenOrientation属性限制.    android:sc ...

  10. M1芯片使用cocoapods 报错[!] Oh no, an error occurred

    [解决方式] 命令行1(编译): sudo arch -x86_64 gem install ffi 命令行2(安装): arch -x86_64 pod install 原出处:https://gi ...