Edge 漏洞研究團隊對 iOS Chromium 漏洞的研究
本文我將快速介紹iOS Chromium瀏覽器以及WKWebView提供的JavaScript進程間通信(IPC)的潛在攻擊面。另外,我還講討論在探索此代碼區(qū)域時發(fā)現的一個UXSS漏洞。WKWebView 是蘋果在 WWDC 2014 上推出的新一代 webView 組件,用以替代 UIKit 中笨重難用、內存泄漏的 UIWebView。WKWebView 擁有60fps滾動刷新率、和 safari 相同的 JavaScript 引擎等優(yōu)勢。
iOS Chromium瀏覽器以及WKWebView提供的JavaScript進程間通信(IPC)的潛在攻擊面
與Chromium瀏覽器的桌面版(使用V8作為JavaScript引擎,使用Blink進行渲染和WebAPI支持)不同,iOS版的Chromium沒有。實際上,iOS上所有第三方瀏覽器很可能都使用內置的WKWebView API向其應用程序添加Web支持,Chromium也不例外。原因是iOS平臺上的代碼簽名限制以及Apple不愿意允許開發(fā)人員提交啟用了動態(tài)協(xié)同設計權限的應用程序。特別是,此權限允許應用程序映射RWX內存。這個功能將允許實現一個高效的JavaScript引擎,與其讓Chromium在平臺上遭受性能不佳的困擾,不如像其他瀏覽器一樣使用WKWebView。
IPC
使用WKWebView而不是自己的渲染和JavaScript引擎的一個不幸的副作用是,你不能再對底層代碼進行直接修改。這意味著你不能直接向網站公開新的本機功能。 WKWebView API通過WKUserContentController對象對此進行了補救。在創(chuàng)建WKWebView對象期間,可以通過WKWebViewConfiguration對象傳遞該對象。
該對象不僅可以用于將JavaScript直接注入網頁中,還可以通過JavaScript公開本機或目標c代碼。這些JavaScript接口通過window.webkit.messageHandlers對象公開,并通過postMessage接口支持調用。在撰寫本文時,每個網頁都有四個消息處理程序可用,找到這些代碼的最簡單方法是grep“setScriptMessageHandler”的代碼
- window.webkit.messageHandlers.FrameBecameAvailable.postMessage(...)
- window.webkit.messageHandlers.FrameBecameUnavailable.postMessage(...)
- window.webkit.messageHandlers.crwebinvoke.postMessage(...)
- window.webkit.messageHandlers.FindElementResultHandler.postMessage(...)
先讓我們一起討論前兩個消息處理程序,這些是控制WebFrameImpl對象的創(chuàng)建和銷毀的處理程序。該對象的唯一責任是管理瀏覽器進程與頁面內框架之間的IPC通信。在內部,這些對象由WebStateImpl擁有的WebFramesManagerImpl管理。 WebStateImpl對象是代表選項卡的主要對象,在桌面上與之等效的是WebContents對象。
與桌面版的Chromium不同,在Chromium的桌面版本中,諸如RenderFrameHost之類的對象與框架的生命周期完全同步,而WebFrameImpl對象的生命周期則完全由JavaScript控制。如果網頁隨機調用FrameBecomeAvailable或FrameBecomeUnavailable,則框架可能沒有相應的WebFrameImpl對象,或者可能有10個,不過此時我還沒有注意到由該API公開并以這種方式使用而引起的任何內存安全問題。
這些處理程序通常通過//ios/web/js_message/resources目錄中的代碼調用,要創(chuàng)建WebFrameImpl對象,需要以下代碼段。

要銷毀一個WebFrameImpl對象,下面的代碼片段就足夠了。

在上面的代碼段中,銷毀框架的WebFrameImpl對象唯一需要的就是其標識符,除主框架的標識符外,這些標識符都是公開的。
這是因為,如果瀏覽器的本機端要在子框架中執(zhí)行JavaScript,它將首先通過主框架路由消息。這是通過調用WebFrameImpl :: CallJavaScriptFunction方法來完成的,此方法使用目標框架的加密密鑰對函數名稱和參數進行加密,然后將對__gCrWeb.message.routeMessage的調用注入到頁面的主框架中。然后,接收框架將消息中的目標框架字段與其自身的框架ID相對照。如果不匹配,它將遍歷所有子框架并重新發(fā)布消息。最終,消息將進入正確的子框架,并且將解密消息并調用所需的函數。之所以子框架的框架ID是公開的,是因為任何子框架都可以安裝消息偵聽器,并檢查通過它傳遞的消息的目標框架ID字段。
這些routeMessage調用的構建方式與FrameBecameAvailable處理程序中的監(jiān)督相結合,實際上導致了一個相當嚴重的漏洞。在將routeMessage調用注入主框架時,使用了以下代碼。

可以看到,腳本是使用格式字符串構建的,該格式字符串使用了WebFrameImpl的encryption_message_json,encrypted_function_json和frame_id_成員。最初,frame_id_成員對你可以提供的名稱沒有任何限制。因此,子框架可以執(zhí)行以下代碼:

這將導致創(chuàng)建一個新的WebFrameImpl,其框架ID為foobar'); alert(window ['origin'] +'。創(chuàng)建框架后,瀏覽器將嘗試向其路由消息。會嘗試從框架中獲取表單信息以進行自動填充,因為將JavaScript注入到主框架中,這將以在主框架中運行的以下代碼結尾:

此漏洞的影響是,它啟用了從子框架(例如托管廣告的框架)中的UXSS,并允許該框架在托管框架的網頁中運行任意JavaScript。不過該漏洞已經進行了修復,該修補程序本身很簡單,可以確??蚣躀D僅包含十六進制數字(0-9和A-F)。
crwebinvoke
crwebinvoke處理程序用于處理綁定到標簽的WebState對象的消息,通過調用WebStateImpl :: AddScriptCommandCallBack添加這些處理程序,并且回調本身具有以下簽名。

ScriptCommandCallback senderFrame的第四個參數有趣的是,它完全取決于在消息的crwFrameId字段中傳遞的ID。再加上子框架的框架ID可能會泄漏的事實,可能會在將來導致漏洞。目前,我還沒有注意到此行為引起任何漏洞。值得注意的是,許多回調在執(zhí)行某些操作之前會執(zhí)行類似于if(sender_frame->IsMainFrame()的操作。這意味著,如果你可以泄漏表示主機框架ID的128位值,則可以模擬主機框架。幸運的是,我沒有注意到執(zhí)行此操作的任何方法。
就像該接口的一個示例一樣,它與任何安全問題都不相關,它是處理window.print調用的代碼。

如果你在網頁中執(zhí)行上述代碼,則將打開打印對話框。
crwebinvoke界面提供的另一個功能是從注入的JavaScript調用發(fā)送結果的通道,每當通過routeMessage調用方法時,瀏覽器都會在內部向列表添加回調處理程序。通過發(fā)送frameMessaging_
此實現細節(jié)的一個潛在問題是,偽造回應所需要的只是發(fā)送請求的框架ID和請求的消息ID的知識。事實證明,消息ID最終只是一個32位的遞增整數,它來自創(chuàng)建框架時的crwFrameLastReceivedMessageId參數。對于新的框架,這個消息ID從0開始。這意味著任何子框架理論上都可以偽造任何其他子框架的回調。然而,我還沒有注意到任何利用子框架消息的問題。
FindElementResultHandler
最后,FindElementResultHandler處理程序負責將被修改的HTML元素通知瀏覽器。每當修改網頁時,瀏覽器就會在主框架中調用__gCrWeb.findElementAtPoint。當findElementAtPoint檢測到所修改的元素位于不同來源的子框架中時,會在子框架上發(fā)布一條消息,以便它可以處理通知瀏覽器的操作。這用于生成長按上下文菜單,并在CRWContextMenuController類中實現。
總結
盡管本文討論的大多數概念都專門針對基于Chromium的iOS瀏覽器,但所有WKWebView使用者都可以訪問messageHandler功能。在審核基于WKWebView的瀏覽器時,它是一個很好的第一手資料。MessageHandler是一個抽象類,開發(fā)者可以在自己的項目中創(chuàng)建自己的類,繼承并實現(重寫)MessageHandler中提供的方法。
本文翻譯自:https://microsoftedge.github.io/edgevr/posts/Hacking-Chrome-iOS/如若轉載,請注明原文地址。