【 摘 要 】 微信公眾號(hào)系統(tǒng)在實(shí)現(xiàn)微信支付功能時(shí),如果支付流程設(shè)計(jì)或系統(tǒng)實(shí)現(xiàn)不合理,會(huì)造成篡改攻擊漏洞或短路攻擊漏洞,可以被惡意用戶(hù)用于發(fā)起中間人攻擊。論文模擬了利用兩種漏洞進(jìn)行中間人攻擊的過(guò)程,分析了兩種漏洞的形成原理,并提出了防范漏洞的解決方案。
【 關(guān)鍵詞 】 微信支付;篡改攻擊漏洞;短路攻擊漏洞
【 Abstract 】 Neither unreasonable payment process design nor failed system implementwouldlead to the Tampering Vulnerability or the Short-circuit Vulnerability, which could be used to launch the man-in-the-middle attacks by the malicious user. This paper simulates how to use 2 different vulnerabilities to launch MITM attack, describes the principle of each vulnerabilities and puts forward solution to fix them.
【 Keywords 】 wechat pay; tampering vulnerability; short-circuit vulnerability
1 引言
騰訊公司的微信(WeChat)推出公眾號(hào)、服務(wù)號(hào)以及微信支付功能后,越來(lái)越多的商家通過(guò)推出微信公眾號(hào),開(kāi)辦微商城,提供微服務(wù)等形式依托微信開(kāi)展商業(yè)活動(dòng)。但是,微信公眾號(hào)系統(tǒng)在實(shí)現(xiàn)微信支付功能時(shí),如果流程設(shè)計(jì)或系統(tǒng)實(shí)現(xiàn)不合理,容易造成支付漏洞,引來(lái)惡意用戶(hù)攻擊。
在以往有一起針對(duì)微信公眾號(hào)支付漏洞的惡意用戶(hù)攻擊事件,經(jīng)估算,這次攻擊共造成了約15萬(wàn)元人民幣的經(jīng)濟(jì)損失。值得指出的是,本文提到的支付漏洞目前在大量微信公眾號(hào)中仍然存在,需引起高度重視。
2 微信公眾號(hào)微信支付的中間人攻擊模擬
經(jīng)分析,這次攻擊是惡意用戶(hù)采用中間人攻擊的方法,通過(guò)網(wǎng)絡(luò)抓包的手段,利用某微信公眾號(hào)的微信支付流程中存在的篡改攻擊漏洞和短路攻擊漏洞,偽造網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),最終實(shí)現(xiàn)了惡意消費(fèi)。下面將對(duì)比該微信公眾號(hào)的正常支付流程,模擬惡意用戶(hù)利用漏洞發(fā)起中間人攻擊的過(guò)程。
2.1 微信公眾號(hào)正常支付流程
該微信公眾號(hào)設(shè)計(jì)的正常支付流程共分七步,如圖1所示。第一步,通過(guò)微信客戶(hù)端關(guān)注微信公眾號(hào);第二步,點(diǎn)擊微信公眾號(hào)底部菜單欄中的“購(gòu)買(mǎi)會(huì)員”菜單項(xiàng);第三步,跳轉(zhuǎn)到“永久VIP會(huì)員”購(gòu)買(mǎi)頁(yè)面,輸入手機(jī)號(hào);第四步,點(diǎn)擊【立即購(gòu)買(mǎi)】按鈕后,跳轉(zhuǎn)到確認(rèn)購(gòu)買(mǎi)頁(yè)面;第五步,在確認(rèn)購(gòu)買(mǎi)頁(yè)面點(diǎn)擊【微信支付】按鈕,彈出微信支付對(duì)話框;第六步,在微信支付對(duì)話框中輸入支付密碼,進(jìn)行支付操作;第七步,如果支付成功,會(huì)收到消息通知,告知用戶(hù)購(gòu)買(mǎi)VIP會(huì)員已成功,可以開(kāi)始使用VIP客戶(hù)的功能;如果支付失敗,將返回第二步。
2.2 惡意用戶(hù)進(jìn)行中間人攻擊過(guò)程模擬
2.2.1 利用篡改攻擊漏洞實(shí)施中間人攻擊
篡改攻擊漏洞,是由于系統(tǒng)的接口設(shè)計(jì)或?qū)崿F(xiàn)存在缺陷造成的漏洞,導(dǎo)致惡意用戶(hù)可以通過(guò)篡改網(wǎng)絡(luò)交互數(shù)據(jù)等方法,達(dá)到攻擊系統(tǒng)的目的。上述微信公眾號(hào)支付流程的第四步的設(shè)計(jì)存在篡改攻擊漏洞。
當(dāng)用戶(hù)點(diǎn)擊【立即購(gòu)買(mǎi)】按鈕,跳轉(zhuǎn)到確認(rèn)購(gòu)買(mǎi)頁(yè)面時(shí),如果使用網(wǎng)絡(luò)抓包工具Fiddle Web Debugger抓取此時(shí)微信公眾號(hào)提交到后端系統(tǒng)的URL請(qǐng)求,可以在抓取的URL請(qǐng)求中,發(fā)現(xiàn)有“totalprice”字段,該字段的值為“12”。這個(gè)值與支付流程第五步中顯示的價(jià)格一致。這意味著如果修改此字段的值,則微信支付系統(tǒng)生成的支付憑證中的金額值也可能會(huì)相應(yīng)修改。嘗試在Fiddle中將此值修改為0.01,果然在隨后的第五步中,微信支付頁(yè)面顯示為0.01元。隨即通過(guò)微信實(shí)際支付1分錢(qián),該微信公眾號(hào)即反回支付成功消息,并告知用戶(hù)已取得了VIP用戶(hù)的所有特權(quán)。
經(jīng)驗(yàn)證,篡改攻擊漏洞也存在于某些電商平臺(tái)和團(tuán)購(gòu)網(wǎng)站的微信公眾號(hào)中。
2.2.2 利用短路攻擊漏洞實(shí)施中間人攻擊
短路攻擊漏洞是由于系統(tǒng)的流程設(shè)計(jì)或?qū)崿F(xiàn)存在缺陷造成的漏洞,利用該漏洞,惡意用戶(hù)可以更改腳本代碼,造成代碼中的條件判斷語(yǔ)句“短路”,只執(zhí)行條件分支中的某部分語(yǔ)句,達(dá)到攻擊系統(tǒng)的目的。上述微信公眾號(hào)支付流程的第五步的設(shè)計(jì)和實(shí)現(xiàn)中存在短路攻擊漏洞。
當(dāng)用戶(hù)點(diǎn)擊【微信支付】按鈕,發(fā)起微信支付請(qǐng)求時(shí),可以使用Fiddle截獲后臺(tái)服務(wù)器返回的頁(yè)面代碼,如代碼 1所示。有三種方法可以導(dǎo)致這段代碼“短路”:一是將if表達(dá)式中的邏輯判斷符號(hào)“==”修改為賦值符號(hào)“=”,使if判斷語(yǔ)句變?yōu)橐粋€(gè)恒真式,達(dá)到“短路”的目的;二是直接刪除if語(yǔ)句和后面的else語(yǔ)句塊,使得無(wú)論用戶(hù)微信支付是否成功,或者是否實(shí)際支付,都會(huì)提交用戶(hù)支付成功的信息,并修改用戶(hù)狀態(tài);三是在if判斷語(yǔ)句前增加一行代碼,直接將res的err_msg屬性值賦值為“get_brand_wcpay_request:ok”。
經(jīng)驗(yàn)證,上面三種方法都可以對(duì)該微信公眾號(hào)實(shí)施短路漏洞攻擊。值得注意的是,有的微信公眾號(hào)系統(tǒng)考慮到了第一、二種攻擊方法,因此采取將微信支付接口返回的res對(duì)象直接提交到后臺(tái)系統(tǒng),在后臺(tái)系統(tǒng)中再根據(jù)res.err_msg的值來(lái)判斷用戶(hù)是否支付成功。但是由于存在第三種攻擊方法,仍然可能造成短路攻擊漏洞。
3 微信公眾號(hào)微信支付漏洞成因剖析
為了保證支付過(guò)程安全可靠,騰訊公司給出了微信公眾號(hào)微信支付的參考業(yè)務(wù)流程,如圖 2所示。對(duì)照該業(yè)務(wù)流程可以看出,造成該微信公眾號(hào)出現(xiàn)篡改攻擊漏洞和短路攻擊漏洞的主要原因是,沒(méi)有按照正確的業(yè)務(wù)流程設(shè)計(jì)和實(shí)現(xiàn)微信支付功能。
3.1 篡改攻擊漏洞分析
按照微信支付業(yè)務(wù)流程,當(dāng)用戶(hù)通過(guò)點(diǎn)擊微信支付消息或掃描二維碼,準(zhǔn)備在微信客戶(hù)端瀏覽器中打開(kāi)用于支付的頁(yè)面時(shí)(圖 2第二步),將向微信公眾號(hào)后臺(tái)系統(tǒng)提交生成支付訂單的請(qǐng)求;微信公眾號(hào)后臺(tái)系統(tǒng)收到請(qǐng)求后,生成客戶(hù)訂單(圖 2第四步);再調(diào)用微信支付統(tǒng)一下單API,向微信支付系統(tǒng)提交生成預(yù)付單請(qǐng)求,微信支付系統(tǒng)在生成預(yù)付單后,返回預(yù)付單信息(prepay_id)給微信公眾號(hào)后臺(tái)系統(tǒng)(圖 2第五步);微信公眾號(hào)后臺(tái)系統(tǒng)根據(jù)返回的預(yù)付單信息(prepay_id)生成JSAPI頁(yè)面調(diào)用的參數(shù)并簽名(paySign)(圖 2第六步)后生成HTML5頁(yè)面返回用戶(hù),等待用戶(hù)點(diǎn)擊進(jìn)行支付。
導(dǎo)致產(chǎn)生篡改攻擊漏洞的主要原因是在上述流程中,“請(qǐng)求生成支付賬單”和“生成用戶(hù)訂單”兩步間的信息交互設(shè)計(jì)存在問(wèn)題。
微信公眾號(hào)后臺(tái)系統(tǒng)在生成用于支付的消息或二維碼時(shí),通常會(huì)使用一個(gè)標(biāo)識(shí)號(hào)作為前后端交互的依據(jù),這個(gè)標(biāo)識(shí)號(hào)可以是用戶(hù)的訂單號(hào)或產(chǎn)品的產(chǎn)品號(hào)。當(dāng)用戶(hù)點(diǎn)擊消息或掃描二維碼請(qǐng)求生成支付訂單時(shí),后臺(tái)系統(tǒng)應(yīng)根據(jù)這個(gè)標(biāo)識(shí)號(hào)生成對(duì)應(yīng)的訂單,包括計(jì)算訂單的應(yīng)付金額。
但是部分以提供會(huì)員、充值、點(diǎn)卡、外賣(mài)等產(chǎn)品的微信公眾號(hào)系統(tǒng),由于產(chǎn)品形態(tài)單一,而且通常一個(gè)產(chǎn)品就是一個(gè)訂單,因此沒(méi)有設(shè)計(jì)獨(dú)立的標(biāo)識(shí)號(hào),而是將應(yīng)付金額等敏感數(shù)據(jù)包含在了前后端交互的信息中;后臺(tái)系統(tǒng)在收到前端系統(tǒng)的支付請(qǐng)求后,也沒(méi)有進(jìn)行必要的驗(yàn)證,就直接將請(qǐng)求數(shù)據(jù)生成了預(yù)付單,這樣就會(huì)留下篡改攻擊漏洞。
3.2 短路攻擊漏洞分析
從微信支付業(yè)務(wù)流程看,從用戶(hù)確認(rèn)支付(圖 2第九步)到微信客戶(hù)端展示支付結(jié)果(圖 2第十五步),共有六個(gè)步驟。這其中包含了兩個(gè)并行任務(wù),用于返回用戶(hù)支付結(jié)果:一是通過(guò)異步的方式通知微信公眾號(hào)后臺(tái)系統(tǒng)支付結(jié)果(圖 2第十步),微信公眾號(hào)后臺(tái)系統(tǒng)在處理完支付結(jié)果后再將處理結(jié)果通知微信支付服務(wù)(圖 2中第十一步);二是通過(guò)JS API直接返回支付結(jié)果給微信客戶(hù)端(圖 2第十二步)。在公眾號(hào)支付開(kāi)發(fā)者文檔中明確說(shuō)明,這兩個(gè)并行處理的任務(wù)并“不保證遵循嚴(yán)格的時(shí)序,JS API返回值作為觸發(fā)商戶(hù)網(wǎng)頁(yè)跳轉(zhuǎn)的標(biāo)志,但商戶(hù)后臺(tái)應(yīng)該只在收到微信后臺(tái)的支付成功回調(diào)通知后,才做真正的支付成功的處理”。
因此,當(dāng)微信支付的JS API返回支付結(jié)果后,要驗(yàn)證用戶(hù)是否實(shí)際支付成功,還應(yīng)向微信公眾號(hào)的后臺(tái)系統(tǒng)提交查詢(xún)用戶(hù)實(shí)際支付結(jié)果的請(qǐng)求(圖 2第十三步),微信公眾號(hào)的后臺(tái)系統(tǒng)通過(guò)調(diào)用微信支付查詢(xún)API,查詢(xún)實(shí)際支付結(jié)果(圖 2第十四步),再根據(jù)查詢(xún)結(jié)果執(zhí)行支付后個(gè)性化頁(yè)面展示。
短路攻擊漏洞造成損失的直接原因是惡意用戶(hù)繞過(guò)用戶(hù)支付結(jié)果驗(yàn)證流程,將用戶(hù)狀態(tài)修改為已正常支付的狀態(tài)。系統(tǒng)實(shí)現(xiàn)中的兩個(gè)錯(cuò)誤共同導(dǎo)致了短路攻擊漏洞:一是錯(cuò)誤地使用微信客戶(hù)端收到的JS API返回結(jié)果作為驗(yàn)證用戶(hù)是否支付的依據(jù);二是在前端的Javascript中調(diào)用修改用戶(hù)支付狀態(tài)的代碼。
分析微信公眾號(hào)的微信支付頁(yè)面代碼,發(fā)現(xiàn)在調(diào)用微信支付接口時(shí),都參照了公眾號(hào)支付開(kāi)發(fā)者文檔中提供的示例,如代碼 2所示。
從代碼 2中可以看出,微信公眾號(hào)是通過(guò)使用微信內(nèi)置瀏覽器提供的內(nèi)置對(duì)象WeixinJSBridge調(diào)用getBrandWCPayRequest方法來(lái)調(diào)用微信支付接口。在該方法的回調(diào)函數(shù)中,可以根據(jù)微信支付接口返回的結(jié)果res.err_msg進(jìn)行下一步處理。但是在公眾號(hào)支付開(kāi)發(fā)者文檔中,明確說(shuō)明:“res.err_msg將在用戶(hù)支付成功后返回ok,但并不保證它絕對(duì)可靠”。不能保證其絕對(duì)可靠的原因是因?yàn)镴avascript的對(duì)象屬性是可以在運(yùn)行時(shí)修改。因此,導(dǎo)致短路攻擊漏洞的第一個(gè)錯(cuò)誤是直接將微信客戶(hù)端收到的JS API返回結(jié)果作為驗(yàn)證用戶(hù)是否支付成功的依據(jù),沒(méi)有嚴(yán)格按照微信支付業(yè)務(wù)流程要求,在后臺(tái)進(jìn)行支付結(jié)果驗(yàn)證,致使驗(yàn)證流程可能被繞過(guò)。
導(dǎo)致短路攻擊漏洞的第二個(gè)錯(cuò)誤是將修改用戶(hù)支付狀態(tài)的代碼放在了前端Javascript代碼中(如前文代碼 1所示)。由于存在可以繞過(guò)支付結(jié)果驗(yàn)證環(huán)節(jié)的可能性,因此這樣做既不能保證業(yè)務(wù)流程的完整性,也不能保證用戶(hù)狀態(tài)修改合法。實(shí)際上,按照微信支付流程,應(yīng)該是在微信公眾號(hào)的后臺(tái)系統(tǒng)收到微信支付系統(tǒng)的異步通知后才能修改用戶(hù)支付狀態(tài)。
4 微信公眾號(hào)微信支付漏洞的解決方案
要避免微信公眾號(hào)的微信支付模塊中留下篡改攻擊漏洞或短路攻擊漏洞,需要從系統(tǒng)的設(shè)計(jì)、實(shí)現(xiàn)、運(yùn)維等多個(gè)方面著手。
4.1 前后端模塊之間的交互應(yīng)是系統(tǒng)設(shè)計(jì)時(shí)關(guān)注的重點(diǎn)
要保證微信支付的安全,系統(tǒng)設(shè)計(jì)是關(guān)鍵。在系統(tǒng)設(shè)計(jì)時(shí),應(yīng)嚴(yán)格按照公眾號(hào)支付開(kāi)發(fā)者文檔中提供的業(yè)務(wù)流程,對(duì)前后端模塊的職責(zé)、交互接口、傳輸協(xié)議等進(jìn)行正確設(shè)計(jì)。
(1)前后端模塊職責(zé)分明。前端模塊只負(fù)責(zé)頁(yè)面的展示和部分的輸入校驗(yàn)功能,而訂單處理、預(yù)付單生成、支付結(jié)果處理、賬單狀態(tài)查詢(xún)等關(guān)鍵功能應(yīng)放在后端模塊。
(2)交互接口最小化。在接口設(shè)計(jì)時(shí),可遵循RESTful風(fēng)格,按照HTTP協(xié)議規(guī)則設(shè)計(jì)API接口;在傳輸內(nèi)容上,只傳遞訂單號(hào)或產(chǎn)品號(hào)等必要信息,特別是在前端模塊向后端模塊發(fā)起PUT、POST請(qǐng)求時(shí),應(yīng)避免將價(jià)格、數(shù)量、總價(jià)等可能影響到支付結(jié)果的敏感信息包含在內(nèi)。
(3)選擇HTTPS協(xié)議作為傳輸協(xié)議。與HTTP協(xié)議相比,HTTPS協(xié)議具有更好的保密特性,可以防止在傳輸過(guò)程中被獲取或篡改信息。
4.2 在系統(tǒng)開(kāi)發(fā)過(guò)程中應(yīng)層層設(shè)防,避免留下漏洞
由于程序員個(gè)體經(jīng)驗(yàn)的不足,或者是團(tuán)隊(duì)沒(méi)有采用恰當(dāng)?shù)能浖_(kāi)發(fā)方法,在系統(tǒng)實(shí)現(xiàn)階段往往容易造成微信支付功能出現(xiàn)漏洞。通過(guò)層層設(shè)防的方式,有助于減少系統(tǒng)開(kāi)發(fā)過(guò)程中造成的漏洞。
(1)對(duì)前端代碼進(jìn)行必要的分離、混淆和壓縮。在實(shí)現(xiàn)前端模塊時(shí),要充分掌握J(rèn)avascript語(yǔ)言規(guī)范和正確的使用方式,避免因誤用留下漏洞;將HTML5代碼和Javascript代碼分離,有利于對(duì)Javascript代碼進(jìn)行獨(dú)立的管理;借助諸如YUI Compressor、Closure Compiler、uglifyjs等工具軟件對(duì)Javascript腳本文件進(jìn)行混淆和壓縮,可以增加惡意用戶(hù)逆向分析和篡改程序的難度。
(2)后端模塊必須對(duì)請(qǐng)求參數(shù)進(jìn)行校驗(yàn)。對(duì)于前端模塊傳遞來(lái)的任何請(qǐng)求,后端模塊都必須對(duì)請(qǐng)求所攜帶的參數(shù)進(jìn)行校驗(yàn),包括有效性校驗(yàn)、合規(guī)性校驗(yàn)、業(yè)務(wù)規(guī)則校驗(yàn)等,保證請(qǐng)求的合法性。校驗(yàn)通過(guò)后才能進(jìn)行后續(xù)處理,以杜絕惡意用戶(hù)在參數(shù)傳遞過(guò)程中實(shí)施篡改攻擊。
(3)采用驗(yàn)收測(cè)試、代碼審查等軟件工程方法,減少人為因素造成漏洞。驗(yàn)收測(cè)試可以模擬軟件系統(tǒng)在實(shí)際使用場(chǎng)景中的不同運(yùn)行流程,驗(yàn)證軟件的功能質(zhì)量特性;代碼審查通過(guò)團(tuán)隊(duì)成員間交叉審查源代碼,達(dá)到彌補(bǔ)個(gè)體經(jīng)驗(yàn)不足,減少系統(tǒng)漏洞,提高代碼質(zhì)量的目的。
4.3 在運(yùn)維中應(yīng)通過(guò)定期核查保障資金安全
除了在系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)時(shí)需要考慮周全,小心謹(jǐn)慎外,在運(yùn)維過(guò)程中加強(qiáng)定期核查也是保障資金安全的重要手段。定期核查可以通過(guò)對(duì)賬檢查和日志審計(jì)等方式進(jìn)行。
(1)在系統(tǒng)中應(yīng)提供“對(duì)賬檢查”功能,通過(guò)微信支付系統(tǒng)提供的“下載對(duì)賬單”接口,定期或手動(dòng)下載對(duì)賬單。運(yùn)維人員通過(guò)自動(dòng)或人工比對(duì)提交到微信支付系統(tǒng)的訂單及金額與微信公眾號(hào)系統(tǒng)中記錄的訂單和金額,發(fā)現(xiàn)是否存在異常訂單支付記錄。
(2)系統(tǒng)應(yīng)提供完備的運(yùn)行日志,可以對(duì)支付過(guò)程中的運(yùn)行情況進(jìn)行跟蹤記錄。當(dāng)發(fā)現(xiàn)遭受惡意用戶(hù)攻擊或者資金異常情況時(shí),運(yùn)維人員可以通過(guò)分析系統(tǒng)運(yùn)行日志,查找問(wèn)題出現(xiàn)的時(shí)間和位置,分析惡意用戶(hù)的攻擊方式,及時(shí)修補(bǔ)漏洞。
參考文獻(xiàn)
[1] 【微信支付】公眾號(hào)支付開(kāi)發(fā)者文檔[EB/OL]. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1#.2016.05.18.
[2] 【微信支付】公眾號(hào)支付開(kāi)發(fā)者文檔[EB/OL]. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4# . 2016.05.18.
[3] 【微信支付】公眾號(hào)支付開(kāi)發(fā)者文檔[EB/OL]. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 . 2016.05.18.
[4] 【微信支付】公眾號(hào)支付開(kāi)發(fā)者文檔[EB/OL]. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6.2016.05.20.
[5] 【微信支付】公眾號(hào)支付開(kāi)發(fā)者文檔[EB/OL]. https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7.2016.05.20.
作者簡(jiǎn)介:
敖毅(1976-),男,四川樂(lè)山人,管理學(xué)博士,解放軍南京政治學(xué)院軍事信息管理系軍事信息安全防護(hù)實(shí)驗(yàn)室副主任,講師;主要研究方向和關(guān)注領(lǐng)域:指揮信息系統(tǒng)、政治工作信息化、軍事信息安全。