2007年的時候,我在印度最大的國有銀行中的一家注冊了一個賬號,這個國家的銀行(政府或者民營)普遍所使用的技術(shù)與當(dāng)前水平相比至少落后了10年。
2015年末,我賬號所在的銀行與外包公司合作,開發(fā)了一款手機(jī)銀行應(yīng)用,分為安卓版和IOS版。這是一個典型的瑞典冬天的周末,沒有陽光的跡象,所以我決定留在室內(nèi),并研究一下這個應(yīng)用。
0×00
我一開始是打算用安卓來進(jìn)行測試的,但是一想起上次在安卓上安裝一個自簽名證書(用于Burp監(jiān)聽)所遇到的挫折,我果斷選擇了iPhone6作為測試平臺。當(dāng)你在安卓上安裝自簽名證書時,安卓會一直提醒你“第三方證書已被添加到您的設(shè)備的信任庫”,但是因?yàn)槌杀镜年P(guān)系你有時候不得不這么做(在企業(yè)環(huán)境或者測試環(huán)境中),再加上測試的過程中會一直看到討厭的提醒信息“您的通信可能被監(jiān)控”,所以IOS是最好的選擇,我在MacBook Pro上運(yùn)行Burp用來作為代理服務(wù)器。
0×01
Burp攔截到的初始請求顯示了與app進(jìn)行通信的主機(jī)名和端口,這是一個中間件應(yīng)用程序,之所以會這樣,那是因?yàn)殂y行通常會從大型廠商購買軟件,比如說TCS 的Bancs、Infosys 的Finacle,、Oracle Finance 的Flexcube。因?yàn)檫@個手機(jī)銀行app是由多個不同的外包公司合作開發(fā)的,所以能夠有效的阻止核心API的曝光。在對OpenSSL進(jìn)行研究之后,我發(fā)現(xiàn)這個中間件使用的是SSL3.0,并且可以被迫降到SSL2.0。
我嘗試通過Burp添加一個自簽名證書用來抓取請求/響應(yīng)中的明文數(shù)據(jù),結(jié)果發(fā)現(xiàn)很成功的就抓到數(shù)據(jù)了,這說明app沒有使用“證書鎖定”??紤]到這是一個銀行的手機(jī)應(yīng)用,沒有使用“證書鎖定”就是一個史詩級的錯誤!
0×02
這顯然是一個不符合規(guī)范的架構(gòu)或者說是不夠到位的代碼審查的案例。這個app的初始請求是向服務(wù)器確認(rèn)是否有可用的更新,而這個請求是發(fā)生在你登錄前的。
這個更新請求會產(chǎn)生一個session ID,這個session ID可被重復(fù)使用來發(fā)起真正的請求(比如說查詢賬戶余額,存款名單),而這樣的行為是只有用戶登錄后才能發(fā)起的,這等于說是繞過了密碼驗(yàn)證。下圖是我在未驗(yàn)證登錄的情況下通過構(gòu)造數(shù)據(jù)包來進(jìn)行賬戶查詢的圖像。而且我說了這個session ID是不會失效的,請繼續(xù)往下閱讀。
0×03
當(dāng)我在把玩這個app時,前端彈出了一個窗口(操作時間即將到期?),詢問我是否要重新登錄或者退出當(dāng)前窗口。這樣的處理行為是正確的,我想知道這個計時是不是只在前端進(jìn)行的,而后端卻沒有處理。
我的直覺是對的,后端并沒有設(shè)置會話失效控制,所以除非客戶端調(diào)用API銷毀session,否則你的會話IDs永不失效。
0×04
我測試了一下該app中接收賬戶的驗(yàn)證控制的有效性。我發(fā)現(xiàn)接收賬戶必須存在于收款人列表中,如果這個賬戶不在收款人列表中,轉(zhuǎn)賬時屏幕就會彈出錯誤,要求你將接收賬戶添加至收款列表中。而添加一個新的接收賬號到收款列表中會要求輸入PIN(MPTIN會在0×05提到)。
事實(shí)上我一點(diǎn)都不會對“這個驗(yàn)證是在前端進(jìn)行”的這件事感到驚奇,
所以直接通過CURL調(diào)用轉(zhuǎn)賬的API就能繞過接收人/受益人賬戶驗(yàn)證,我就能夠?qū)㈠X轉(zhuǎn)賬到不在我的受益人列表中的賬戶。原本我還想測試其他的關(guān)鍵的流程(轉(zhuǎn)賬中的余額驗(yàn)證,轉(zhuǎn)賬限制),但是這可能是違法的,所以我只能跳過了。
(從收到的來自銀行的響應(yīng)數(shù)據(jù),似乎能看出我上面提到的關(guān)鍵流程的驗(yàn)證都是在前端驗(yàn)證的)。
0×05
從上面提到的這些漏洞就可以寫一個嚴(yán)重程度為中高的POC了。在0×02和0×03中,只需要5行代碼就能枚舉所有用戶的記錄(當(dāng)前賬戶余額和存款)。
我決定挖掘的更深一點(diǎn)。
在我挖掘的更深之前,我要先解釋一下此應(yīng)用程序的身份驗(yàn)證機(jī)制。
這里有兩個PINs(身份認(rèn)證PIN[MPIN],交易授權(quán)PIN[MTPIN])。從名字來看就知道你可以用MPIN來進(jìn)行登錄,用MTPIN來對重要的操作進(jìn)行驗(yàn)證,比如添加一個接收賬號到受益人名單中,轉(zhuǎn)義資金,創(chuàng)建一個新的定期存款,關(guān)閉現(xiàn)有的定期存款。這個應(yīng)用中的用戶名為你的用戶ID[CID]。
一個有效的轉(zhuǎn)賬請求如下:
"mobileAppVersion=x.x.x&MTPIN==XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&channel=rc&entityId=XXX&beneficiaryAccount=123456789&serviceID=fundTransfer&appID=XXXXXXXX&txn_amount=100000&customerId=1337&transferType=XXXX&appVer=x.x.x&platform=iPhone&mobPlatform=iPhone&remarks=tt&accountNo=987654321"
在上面的請求中,發(fā)送者(ccountNo:987654321)正嘗試將100,000轉(zhuǎn)賬給受益人(beneficiaryAccount:123456789)。
當(dāng)請求被反序列化后,會傳遞給如下的函數(shù)處理:
你發(fā)現(xiàn)錯誤了嗎?
問題出現(xiàn)在,這個validateAuthenticator方法會驗(yàn)證MTPIN與用戶ID對應(yīng)的MTPIN是否匹配,這兩者的值都是由用戶提交的,但是卻沒有驗(yàn)證提交的用戶ID或者M(jìn)TPIN是否屬于當(dāng)前發(fā)送者。所以通過使用我的用戶ID和我對應(yīng)的MTPIN,我能夠?qū)崿F(xiàn)在任意賬戶間進(jìn)行金額互轉(zhuǎn)。我用我們家庭中的賬戶進(jìn)行了測試,發(fā)現(xiàn)甚至一些沒有開通網(wǎng)上銀行或者手機(jī)銀行的用戶也能通過這種手段進(jìn)行轉(zhuǎn)賬。
如下面的圖片,1303是我的用戶ID的后4位,列表中是我賬戶關(guān)聯(lián)的其他用戶的ID。(SB-存款賬號,RIP-定期存款)。
如下是我做的一個成功的交易。你可以看到我構(gòu)造了一個請求,請求中用到的是我的用戶ID和我的MTPIN,但是發(fā)送者賬戶(6254)卻不是我的。(= = 作者的圖掛了,各位腦補(bǔ)下吧!)
我快速的用bash寫了一個13行的代碼,供給銀行或者外包進(jìn)行測試。
0×06
用手機(jī)銀行進(jìn)行轉(zhuǎn)賬時,銀行會給當(dāng)前賬號綁定的手機(jī)號發(fā)送短信即時通知,問題是在這里他們又處理錯了。
發(fā)送提醒短信的代碼和上面的代碼是類似的:
和0×05相似,要發(fā)送提醒短信的手機(jī)號碼是從客戶ID中獲取的,而不是賬戶號碼。因此,當(dāng)攻擊者竊取了受害者的資金后,提醒短信會發(fā)送到攻擊者那,而不是受害者。(作者的圖掛了,各位就再腦補(bǔ)一次吧!)
0×07
我很快速的寫了一個poc,然后在2015.11.3號將此poc發(fā)給了該銀行的一堆總經(jīng)理、副總經(jīng)理、IT經(jīng)理、部門經(jīng)理,一個禮拜過去了都沒有收到任何回復(fù)。8天后,我收到了該銀行的一個非官方的確認(rèn)信息(該銀行的一個中層經(jīng)理)說他們正在調(diào)查這個問題。大概第9/10天左右,開發(fā)該app的外包公司的副總裁訪問了我的linkedIn主頁。最后在第12天的時候,我收到了來自該銀行的副總經(jīng)理的官方回復(fù),他們基本上采用了我提交的漏洞修復(fù)建議。這讓我有點(diǎn)驚喜的同時也讓我感到害怕,他們居然用了12天的時間來回應(yīng)我,并且就像在說“嘿,你的數(shù)十億身價存款有風(fēng)險”,真是太令人吃驚了。
我回信詢問漏洞何時會被修復(fù)以及是否會為此漏洞提供賞金,鑒于這家銀行有將近250億美元的存款(2015年的數(shù)據(jù)),為什么不嘗試著要點(diǎn)賞金呢,但是就如預(yù)期的一樣,他們沒有再回復(fù)任何信息了。
所以這就是印度,這么大的漏洞0賞金!