公司小兄弟发给我一个py样本,是今日捕获的某weblogic 0day,咱们来分析一下。
使用我的javaSerializationTools工具,来分析这个样本。结果如图

jdk7u21调试一下 
当然,weblogic 12已经不支持在jdk版本低于1.8的jdk下运行。 
我们可以很明显的看到,这个是反序列化gadgets中7u21的变种。唯一不同的是com.sun.org.apache.xalan.internal.xsltc.trax被用java.rmi.MarshalledObject代替。要了解这个为什么可以绕过weblogic黑名单,我们要了解一下weblogic 反序列化的黑名单究竟是什么
在java反序列化的过程中,会层层解析所需要的类,而weblogic就是控制解析反序列化的类,如果碰到可能触发恶意操作的类的名称,则直接打断反序列化流程。
而weblogic在处理jdk 7u21这条反序列化gadgets中,为了平衡拦截的效果与不影响业务,选择拦截com.sun.org.apache.xalan.internal.xsltc.trax这个类。而这个类恰恰也是绝大多数java反序列化中最为关键的一环。
所以,如果我们想要绕过weblogic针对7u21的反序列化拦截的黑名单,则需要找到com.sun.org.apache.xalan.internal.xsltc.trax的替代。
我在这里简单分析一下7u21中AnnotationInvocationHandler到com.sun.org.apache.xalan.internal.xsltc.trax的过程。因为在poc中只有这里改变了。
Templates类的newTransformer方法,会将属性_bytecodes,通过调用java的defineClass去生成一个类,并将其实例化,也就是调用静态代码块的代码。
而AnnotationInvocationHandler,创建一个Templates的jdk动态代理,在hashmap出现哈希碰撞的时候,在hashmap中会调用AnnotationInvocationHandler的equal方法,equal方法会调用自身的equalImpl方法。最终会调用被代理对象的每个方法,去生成结果,相关代码如下
private Boolean equalsImpl(Object var1) {
// 判断var1是否为AnnotationInvocationHandle,var1是templates,pass
if(var1 == this) {
returntrue;
// 构造限制点,type属性限制了var1必须为this.type的类实例
} elseif(!this.type.isInstance(var1)) {
returnfalse;
} else{
//这里获取了当前成员的方法
Method[] var2 = this.getMemberMethods();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
Method var5 = var2[var4]; //遍历获取方法
String var6 = var5.getName(); //获取方法名字
Object var7 = this.memberValues.get(var6);//获取memberValues中的值
Object var8 = null;
// Proxy.isProxyClass(var1.getClass()
// 判断varl是不是代理类,显然不是,pass
AnnotationInvocationHandler var9 = this.asOneOfUs(var1);
if(var9 != null) {
var8 = var9.memberValues.get(var6);
} else{
try {
// 这里直接进行了方法的调用核心。
// var5是方法名,var1是可控的类
// var1.var5()
var8 = var5.invoke(var1);
private Method[] getMemberMethods() {
if(this.memberMethods == null) {
this.memberMethods = (Method[])AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
public Method[] run() {
Method[] var1 = AnnotationInvocationHandler.this.type.getDeclaredMethods();
AccessibleObject.setAccessible(var1, true);
returnvar1;
}
});
}
returnthis.memberMethods;
}
因为newTransformer方法恰好为Templates的第一个方法,如果是第二个方法的话,会导致执行第一个方法的时候出错而中断整个反序列化链。
而poc中,使用了java.rmi.MarshalledObject这个类,我们来分析一下。
在java.rmi.MarshalledObject中,getMemberMethods方法返回的一个方法是get。get代码如下
public T get() throws IOException, ClassNotFoundException {
if(objBytes == null) // must have been a null object
returnnull;
ByteArrayInputStream bin = new ByteArrayInputStream(objBytes);
// locBytes is null ifno annotations
ByteArrayInputStream lin =
(locBytes == null ? null : new ByteArrayInputStream(locBytes));
MarshalledObjectInputStream in=
new MarshalledObjectInputStream(bin, lin);
@SuppressWarnings("unchecked")
T obj = (T) in.readObject();
in.close();
returnobj;
一看就懂了,将objBytes属性作为反序列化的流,从中解析对象。我们知道,weblogic中,必须要调用FilteredObjectInputStream,才可以在反序列化过程中使用反序列化的黑名单。如果类中私自调用ObjectInputStream,则不会应用weblogic反序列化的黑名单。从而绕过
剩下的流程就与7u21的触发流程就一样了,只需要把objBytes随心所欲的替换为你喜欢的反序列化就可以,在这里无视weblogic黑名单。
当然,我拿到的样本,只是一个简单的回显代码,并没有太复杂的操作。
解决方案
- 这个反序列化漏洞并不只是影响jdk7u21,因为我们知道8u21是7u21的变种,理论上将jdk 8u21以下的jdk都受到此反序列化gadget的影响。
- 直接关闭iiop/t3这两个协议

浙江省丽水市 1F
这波操作属实秀了,rmi还能这么玩👏
香港 B1
@ 偏锋 这招确实骚,rmi还能这么绕,学到了。
中国 2F
weblogic的黑名单一直就这样,治标不治本
北京市 3F
7u21变种现在还这么活跃?我以为早被围剿了
重庆市 4F
objBytes那块直接反序列化,确实绕得挺溜
上海市 5F
这个poc是不是只能打老版本?8u200试试能行不?
四川省攀枝花市 B1
@ 蓝莓冰沙 8u200估计悬,新版本加了校验,得看payload咋构造
湖南省长沙市 6F
前几天分析了个类似的,也是用MarshalledObject绕的
日本 7F
说白了还是黑名单太窄,光拦xalan不够看
广东省汕头市 B1
@ SinisterVortex 黑名单不更新等于摆设,治标不治本。
北京市 8F
t3关了业务受不了吧,有没有更细粒度的方案?
广东省江门市蓬江区 9F
冰蝎这工具更新真快,beta8都开始玩内存马了
安徽省 10F
回显都搞不定还想干啥,别整这些花里胡哨的
四川省南充市顺庆区 11F
感觉现在绕黑名单都成常规操作了,hhhh
广东省深圳市 12F
老哥分析得挺细啊,这思路有点意思
宁夏银川市 B1
@ 白骨灯 哈哈,这思路确实绕得挺巧妙的。
澳大利亚 13F
冰蝎这更新速度,怕不是开发比安全圈还关注补丁
河南省郑州市 14F
weblogic这黑名单,修了十年还在修,无语
上海市 15F
这绕过手法有点秀
陕西省西安市 16F
黑名单绕来绕去,还是协议关了省心。