2019 SDC 議題回顧 | 是誰推開我的“窗”:iOS App介面安全分析
對於廣大的開發者而言,WebView和URL Scheme並不陌生。WebView一直以來都是iOS的核心元件,而URL Scheme是iOS APP重要的介面之一。
由於目前介面安全性研究較少,已有的研究也主要集中在Android系統,忽略了iOS 應用的安全性。下面就讓我們來回顧看雪2019安全開發者峰會上《是誰推開我的“窗”:iOS App介面安全分析》的精彩內容。
編輯按
crownless:在廣闊的網路世界,或許你在瀏覽器上的一次點選都會觸發你手機上已安裝的應用的漏洞,進而導致賬號被盜、財產丟失、資料洩漏……
導致這個問題的原因是開發者沒有在外部可呼叫介面上部署許可權檢查或過濾有害呼叫。所以,開發者應當時刻將安全放在首要的位置上!
嘉賓介紹
張一峰,北京長亭科技移動安全負責人,負責移動APP安全審計、原始碼審計等漏洞挖掘工作。全球網際網路技術大會網路安全專場演講嘉賓,2018華為終端安全獎勵計劃大會圓桌會議嘉賓,2018 DEFCON Demo Labs speaker。
大會上講師首次披露了由於iOS APP URL Scheme和JSBridge介面導致的安全漏洞,完美的體現了“不知攻焉知防”。透過把過程介面呼叫可以利用的方式,在iOS平臺上實現可攻擊的效果和cookie注入等方式,最後還幫我們做了防範和總結,希望大家注意iOS開發裡的那幾點。
演講具體內容
以下為速記全文:
大家好!我是來自長亭科技的張一峰,我分享的題目是APP介面安全分析。
議題主要內容有這麼五方面:第一,業務開發模式變遷,第二,混合開發模式,第三,漏洞成因和漏洞基礎,第四,例項展示,因為介面設計的缺陷導致的安全問題,第五,總結以及開發建議。
一、移動開發模式變遷
在開發模式變遷的時間軸,上面是一些時間節點,下面是相對應時間段在移動開發中Android和iOS使用的主流開發語言。
2007年Android和iOS問世,最初主要以java和oc作為程式語言,隨後谷歌增加了c和c++的支援。後面由於html5技術的發展,逐漸出現了純WEB的應用,不只是移動端,其它也會有,蘋果在這期間推出了它的新開發語言swift,同時,谷歌也官方支援了kotlin語言進行開發。
但是由於WEBAPP存在缺陷,後面人們更多使用混合開發模式,也就是當前比較多的開發模式。截止到現在,從最初的java、oc,到現在官方主流推薦使用kotlin和swift開發,所以經過10多年變遷,有很大變化。同時,因為有混合開發模式,還有著js和HTML。
二、混合開發模式
從時間線來說,從原生到WEB再到混合開發模式,但是從邏輯角度來說,混合開發模式放在中間是更合適的。原生開發模式很好理解,我們用官方提供的語言,呼叫Framework的介面實現我們APP的功能。在webAPP裡完全依賴於webview這個元件使用純前端技術,我們APP的功能和邏輯主要由js實現。
而混合開發模式是原生和web的混合,它相當於二者間的一個結合點。主流APP的呼叫還是依靠原生程式碼進行呼叫,對於一些業務應用,比如更新比較頻繁的,或者可能每天都會變化的業務,我們會使用純web進行展示和渲染。
為了引出混合開發模式,就不得不提webAPP裡面的優缺點,優點是跨平臺、開發成本比較低,但缺點也很多,其中比如主要的就是它對複雜演算法、多程式設計等等支援不是很好。
同時,因為js能做的最多是壓縮和混淆,它對以前的程式碼而言,與編譯之後的二進位制相比,對原始碼保護還是有很多不足的。同時,有個最重要的缺點是與原生API互動是非常不方便的。
基於這個原因,人們開始逐漸使用混合開發模式,混合開發模式繼承了webAPP裡的很多優點,透過JSBridge手段避免了很多API呼叫的問題。JSBridge是什麼?它是js程式碼到原生程式碼的介面,大家把它形容為像一個橋一樣。
透過這個橋,我們的API還是由原生的程式碼進行呼叫。其實JSBridge的功能並不是在混合開發模式中從零做出來的,它類似的功能在系統API本來就已經提供了,只不過在混合開發模式中程式設計師對API進行了一定的封裝和擴充套件。
下面舉個能實現這樣功能的API,上面是UIWebView,下面是WKWebView,可以實現JSBridge的功能,後面還有相應API的例子,這裡面就不再詳細說了。
基於這個API有一個使用很多的框架,就是這個WebViewJavascriptBridage框架,它就是對API進行封裝,跟著框架所做的主要貢獻是增加了回撥函式,也就是說它能獲取JSBridge的返回值。
正常來說,我們透過這個API只能進行傳參、呼叫,但是如果獲取的JSBridge返回值,所以在複雜業務裡是有缺陷的,這個框架主要是增加callback,能透過callback獲取它的返回值。
另外一個是UIWebView的JavaScriptCore和WKScriptMessageHandler,它也都分別有對應的API可以實現這樣的功能。後面有例子,這裡就再不繼續展開。
說到這樣的功能的API就不得不提安卓平臺下這個介面,這個介面也是為了實現同樣的介面,但是在2012年被人們發現它可以實現一個遠端任意程式碼執行,這個漏洞影響特別深遠,很多做開發的哪怕不懂安全,但在寫程式碼時都會用一個API判斷是否大於17來避開這個漏洞,其實這個地方是容易發生安全問題的。
三、漏洞成因和漏洞接觸
首先介紹一下iOS deeplinks裡的一種,就是URLScheme,它是提供了應用間IPC的方式,也就是說透過URLScheme可以調取另外一個應用再進行返回。怎麼使用URLScheme這個技術?其實非常簡單,只需要在xcode中進行註冊,然後實現回撥就可以了。
這個URLScheme大概長這個樣子,它是遵從這三個規範,透過API可以傳回URLScheme裡哪個欄位的值,一個應用如果自定義了URLScheme,其他第三方應用就可以對它進行呼叫,同時網頁也可以進行呼叫。這個也是我們後面例子中遠端進行攻擊的一個非常依賴的點。
其實URLScheme也不是大家隨便可以調的,它是有一個許可權限制的,就是需要使用者互動的,類似於讓使用者授權一樣,如果透過網頁進行調取的話,需要使用者點選開啟,如果是應用的話,在第一次是需要使用者進行授權的。
但那個授權其實相對來說是一個很寬泛的,它並不像強制訪問控制,它只是一個需要使用者點選和確認就可以了,使用者很難去分辨。
說到URLScheme,我們下相對應的程式碼怎麼去用它,前兩行程式碼是URLScheme裡面,已知URLScheme,去調取的話很簡單的兩行程式碼就可以用這個open函式進行呼叫了,如果是js的話也非常簡單,一個連結就可以了,我們可以透過js裡面這種自動點選的方式進行自動呼叫也可以。
被動應用會進行回撥函式,也就是最下面的函式,這個函式里它會獲取傳輸URLScheme的引數,然後根據這個引數再執行相應的邏輯。
剛剛說有幾個API可以實現JSBridge的功能,這裡選了兩個API,選了兩個例子,讓大家對JSBridge實現有個瞭解。上面是我們的前端連結,這裡面Scheme是自定義的一種,並不是常見的。
當這個連結被請求的時候,系統的這個函式就會被毀掉,相當於對我們請求的連結進行攔截。如果我們這裡面自定義了一個Scheme,這裡就可以判斷這是不是我們自定義的Scheme,也就是說前後端對應好就可以實現通訊,這裡可以把傳輸引數取到,實現類似於偽協議的這樣一個通訊。
透過這個可以實現從前端到後端的呼叫。另外一個是JScafffun裡的函式,它和上一個區別是你可以自定義這個函式的名字,前端你可以認為它是JS函式進行呼叫,但是它其實也會進入這個程式碼,在這個程式碼可以進行獲取引數。
有了上面那些基礎知識,就引出了介面漏洞的成因:首先,因為自定義的第三方URLScheme,實際應用中你可以去市場中看,基本都有,基本是可以滿足的。
定義URLScheme以後,其他的應用或者網頁可以對它進行呼叫,呼叫完程式可以執行URLScheme和對應回撥函式,這個回撥本身可能就存在一些缺陷。
如果URLScheme回撥函式本身沒有什麼特別的,我們需要關注它是不是有可能載入任意的URL,如果能載入任意的URL,也就是說我們可以執行我們任意的JS程式碼,執行任意的JS程式碼,如果恰好實現很多JSBridge,我們就可以對JSBridge介面進行呼叫,這種介面可能存在缺陷。兩種情況都不符合的話,有其他方式允許應用載入這一段。
為了更好理解下一部分例項裡的程式碼,這裡簡單講一下OC執行時。OC是面嚮物件語言,它是一個大家接觸比較多的訊息轉發機制,它在彙編層面發生函式對話時,它並不是直接把PC指標跳轉到目標函式的地址,它是有個OBJC_MSGSEND的函式,把這個函式呼叫封裝,但這個函式呼叫其實還是透過這個跳轉過去,但是它相當於把這個訊息進行轉發,其實是oc裡多型的一種實現。
所以oc裡面的多型相當於是在這執行池進行確定的。除此以外,執行池還提供performSelector的方式,Selector可以理解為函式名字,但其實不是。如果把這個函式名傳裡面去也可以實現函式呼叫,你不需要在程式裡用形式把它包起來。
四、案例分析
案例1:遠端竊取cookie的漏洞。
我們首先看它的info.pilist的檔案,因為最根本是在這個檔案裡。這裡面我們發現它有一個自定義的URLScheme,有了這個URLScheme以後我們就要去看它的回撥函式,它的回撥函式邏輯很長,這裡只是把相關的函式摘出來了,我們會發現它會進入APPSchemeManager這裡,這裡是做什麼呢?它首先把我們傳輸的URLScheme以字元段的形式取出,然後拿到問號之後的字元,然後以dictionary的形式進行解析。
因為URLScheme是我們傳入的,所以這是一個可控變數。這段所要需要查詢的dictionary,就是在標準URLScheme裡query這個欄位,它是dictionary格式的。進而判斷dictionary是否有Key為type的欄位,這跟我們沒關係,就跳過了。
我們主要看它的eLse值,Else值裡會判斷是不是有Key的URL,如果有的話它繼續判斷是不是這個開頭,如果兩個check都符合的話,它會把這個value傳給baseWebViewCONTRoller。
下面是前端的程式碼,相當於是把這個View壓到棧的最上面,把它渲染和展示。有了這個程式碼我們就知道最終需要傳輸的URLScheme就是這個樣子,我們的K是URL,然後對應的value,前面是字串URL,後面是連結。這個程式把我們傳輸的連結會進行渲染出來,然後同時也沒有進行任何的校驗。
我們讓它開啟我們的連結並不是真正的目的,所以我們還需要繼續往下分析,如果它開啟我們的連結,因為這個伺服器是我們自己的,我們可以在這裡寫任意的js,任如果它定義了JSBridge介面的話,我們就可以呼叫它的JSBridge介面。
我們看一下這個URLSchemeJSBridge,為了實現這個遠端攻擊,你可以把這個URLScheme寫到一個網頁裡。分析時發現它在初始階段進行初始化了,初始化最重要的是這個registerLoginWithHanler這個地方,它是前面說到那個框架裡面的用法,在這裡面相當於前面也註冊了名字就是函式的名字,然後第二個是函式名字所對應的操作。
所以最終發現在我們載入頁面裡實現的效果,我們可以呼叫Module這個類下面的任意函式。
既然可以實現函式呼叫,我們就看看這個類下面有什麼函式值得我們調,發現了有這個Bridge這個函式,根據函式名字感覺像獲取使用者資訊,我們就需要去驗證一下是不是我們想要的樣子。所以嘗試一下,然後斷下來,發現它傳輸的有電話號碼、UID、comparyID和token。
最後payload就呼之欲出了,我們呼叫getuserinfo介面,達到最終的陣列,這個陣列不是最終目的,我們把它發給遠端伺服器。這個頁面裡透過這個方式,把拿到的token和number傳送給我們的伺服器。
因為這個頁面本身就是www,所以它是符合策略的。這是我們實際在服務端收到一個請求,發現token和手機號都可以傳送給我們。拿到token以後相當於對這個帳號實現了控制,而且在移動端裡有個特點,就是token的有效期比較長。
案例2:任意檔案上傳漏洞。
我們還是看info.plist,它有自定義的URLscheme,這個案例本身可以完全不依賴於載入自己頁面本身,這可以完全挑過,因為這相當於實現問題比較多,從很多方面都可以去打。
同時為了實現遠端攻擊,你也可以把URLscheme嵌到網頁裡。說到URLscheme嵌到網頁裡剛剛忽略了一個點,它需要有授權,這裡最方便的方式是可以以領紅包等等之類的方式,因為使用手機的都知道,基本所有都在用URLscheme的應用,比如第三方支付、朋友圈分享等等底層都會用到這個機制,所以對普通使用者來說,很難分辨一個跳轉是惡意的還是真正的業務功能。
這個裡面它使用的shouldStartLoadWithRequest。這個處理,傳輸的最終會進入hander的URL裡面,在這個裡面它會首先判斷這個URLscheme是不是等於空,如果等於的話它進一步查詢URL引數進入handlemessage,進入下面的這個函式。
在這個函式里它獲取裡面的action和args,這時我們還不知道它是幹什麼用的,但是我們知道URL是我們傳入的,這個是個可控變數,也就是說它所查詢到的引數也是我們可控的。這裡面它有一個許可權驗證,就是它判斷你是不是有許可權呼叫這個API,但是這個驗證是存在缺陷的。
然後就進入下一步,也就是說這兩個引數我們知道是可控的。這裡面首先會呼叫許可權呼叫這個函式,這個函式里面會把action前面加一個jsapi_completion,把構造好的action傳給performSelector,這個我們在剛剛講oc執行池時提過這個函式,這個函式傳入的相當於是對這個的呼叫。
分析到這,我們就分析它其實可以實現的效果是對component下面的以“jsapi-”為開頭,以completion為結尾的任意函式呼叫,我們就可以利用這個任意函式呼叫去做些有意思的事情。
所以我們要分析這類裡面到底有什麼函式值得我們呼叫。我們發現它有一個UPloadImages的函式,因為它符合這個命名,我們分析這個函式,發現它首先會拿到這個函式的URL欄位,還有一個path欄位,其實這個URL是它上傳圖片目標的伺服器地址,path是你要上傳檔案的路徑。有了上面一些已知資訊,我們最終的就出來了。
開頭是jsapi,也就是我們過它第一個check,action是你所要呼叫的函式名,我們這裡面傳入剛剛看到的uploadimages,在這裡面要傳送兩個關鍵字,一個是URL,一個是path,URL是我們自己的伺服器,也就是說把沙箱裡的檔案上傳到我們自己的服務輕易鬆手,path是沙箱裡的一個檔案。
所以在POC裡上傳沙箱裡的SQLline資料庫。這個例子裡面為什麼剛剛我說其實不需要載入任意URL那個地方?因為你完全可以把上面的load寫在最初的網頁裡,只要跳轉這個目標應用,攻擊在一瞬間就完成了。
分析了很多ios平臺發現,發現回撥函式里利用OC執行時進行函式動態呼叫的非常多,佔比最大。這個例子可以看出你傳輸的字元是不是以某個數字開始,如果以某個數字開始就會呼叫某個函式,所以相當於傳輸一串數字就可以呼叫裡面很多函式。實際分析下來,確實有很多這樣的案例存在,是一個非常危險的東西。
案例3:業務邏輯漏洞。
因為之前我們已經對怎麼去確定URLscheme是什麼樣子的,所以在這裡我們就把這兩個都跳過了,因為可是於這幾個例項是內容依次變少了,因為有很多東西思路是重複的,但程式碼不一樣。
這個應用裡,它為了實現增強網頁裡面的功能,它不單是加入了很多記憶體這樣的函式,而且加入很多外掛。可以透過外掛ID呼叫這裡面很多外掛,我們從它可以呼叫的外掛裡發現了很引起我們興趣的東西就是這個,就是它本身自己帶了一個支付功能的應用。
所以我們把這個ID傳入,作為walletPaySDK傳進去,它的引數裡有一個很重要的OrderID,也就是說我們可以生成訂單,但是我們先不支付,然後我們作為payload發過去,可能導致支付風險,就是可能支付別人那去了。
當然,這個最終使用還需要依賴其他條件。但是這個例子充分說明了,對於支付類的SDK詳細顯示購買商品和金額是一個特別必要的事。之前交大他們做第三方支付研究時,也介紹過這一點。這個例子也是本地和遠端都可以打的。
這裡我們做個階段性小結:之前我們演示的例子裡主要是以檔案讀作為我們利用的一個點,我們自然而然想到檔案寫是不是也可以。同時,除了我們利用透過API這樣的方式、這樣的JSBridge,還有沒有其他JS介面可以供我們呼叫?在攻擊方式上,我們剛才講了透過URLScheme和DeepLink的形式進行遠端攻擊,那還有沒有其他方式?
下面看下JS程式碼執行情況,就是在ios9還是ios8,引入了一個更為安全、效能更高的WKWeView。WKWeView有一個新特性是支援JS注入。在下面的程式碼裡,可以把沙箱的這個JS插入到頁面中,以這個載入到前端頁面都會自動引入我們一個JS進去。
被插入的JS長什麼樣子?大概這樣子,它也會定義很多函式。對JS程式而言,它可以當作自己實現的函式一樣進行呼叫。JS會駐留在所有網頁中,它會定義很多函式,效果類似於JSBridge,如果存在剛才案例中的情況,我們依然可以透過呼叫這樣的函式進行滲透。
如果剛剛我們備註的JS存在沙箱或者遠端的話,結合檔案寫等等,我們把本身給重寫了,就可以實現XSS。如果熱更新,當然,熱更新現在已經被蘋果禁止了,如果有熱更新的話也可以實現效果。
下面看一個程式碼執行的例子,這個程式碼執行的例子裡,它首先是判斷這個scheme是不是等於這個字串,如果等於的話它會post這個,這個到底是什麼?
它是ios裡一個應用內部通訊的機制。在之前都會呼叫這個server的API,類似於把這個先註冊,註冊時會傳輸這個action東西叫什麼名字,它對應的是什麼,也就是說它要執行的函式是什麼。
所以在這個例子裡,我們只要傳輸URLScheme,它這個字串進去,就會導致這個函式被執行。但這裡其實並沒有實現任意程式碼執行,但是如果被執行是一個非常敏感的函式或者結合其他漏洞的話,還是可以進行利用的。
剛剛我們說了遠端觸發,除此之外還有一個經常被別人忽略的二維碼掃描,這是普遍大家都在使用的一個方式,APP裡面定義一個名以後,它可能在很多地都用同一個名進行載入,只不過這個URL傳輸的方式不一樣。
所以利用二維碼掃描也是可以做到的,在之前我們團隊有同事做過類似的活動,掃描二維碼就可以把你的照片傳送給遠端伺服器。
再一個是後臺觸發,但是這個利用難度就比較大了,因為後臺許可權是很難拿到的。但是這個比較有意思的一點是什麼?如果把攻擊向量放在後臺,它是可以打所有前端,也就是說你的伺服器可以打這個業務裡所有的客戶端,這是觸發方式裡比較有意思的一點。
五、總結以及開發建議
說一下怎樣發現漏洞以及發現漏洞的思路是什麼。首先,看看URLScheme定義情況,如果有的話我們就看它的回撥函式以及重點關注它有沒有載入URL這樣的操作。
另外,看看它有沒有透過二維碼或者其他方式載入任意URL。最後,對它我們可以呼叫的介面進行分析,看有沒有可利用的點。
在開發定義裡面說幾點:iOS生態比安卓做得好多,也一定程度上保證了安全性,但是應用安全並不能完全依賴於系統安全。第二,對於URLScheme使用建議保證最少原則,因為增加一個URLScheme就相當於增加一個介面,增加一個介面就增加一個風險。
在混合開發模式中,這種核心敏感的操作建議使用原生程式碼進行開發。外部可呼叫介面一定要嚴格過濾呼叫者,確保可信。比如剛剛的例子,如果我們在那個位置的check過不了的話,後面也就無從談起了。
最後,對WebView本身是一個非常容易出現漏洞的元件之一,實際開發中又很難避開它去不用,所以在開發中要注意已知和未知的安全漏洞。
公眾號ID:ikanxue
官方微博:看雪安全
商務合作:wsc@kanxue.com
相關文章
- 峰會預告 |是誰推開我的“窗”:iOS App介面安全分析2019-07-18iOSAPP
- 2019 SDC 議題回顧 | 工業集散控制系統的脆弱性分析2019-07-29
- 2019 SDC 議題回顧 | 安全研究視角看macOS平臺EDR安全能力建設2019-07-23Mac
- 2019 SDC 議題回顧 | 基於雲資料的司法取證技術2019-07-24
- 2023 SDC 議題回顧 | 探索軟體定義汽車的安全攻擊面2023-12-07
- 2023 SDC 議題回顧 | 晶片安全和無線電安全底層滲透技術2023-11-22晶片
- 2020 看雪SDC議題回顧 | 麒麟框架:現代化的逆向分析體驗2020-11-03框架
- 2020 看雪SDC議題回顧 | Android WebView安全攻防指南20202020-10-29AndroidWebView
- 2023 SDC 議題回顧 | 從探索到利用:揭示安卓模擬器漏洞2023-11-14安卓
- 2021看雪SDC議題回顧 | 基於模擬模擬的藍芽協議棧漏洞挖掘2021-11-01藍芽協議
- 2021看雪SDC議題回顧 | APT針對恐怖主義的間諜活動剖析2021-11-04APT
- 2023 SDC 議題回顧 | JDoop:下一代針對Java Web應用的靜態分析框架2023-11-06OOPJavaWeb框架
- 2020 看雪SDC議題回顧 | 生物探針技術研究與應用2020-10-30
- 2020 看雪SDC議題回顧 | 敲開晶片記憶體保護的最後一扇“門”2020-11-02晶片記憶體
- 2020 看雪SDC議題回顧 | 高通移動基帶系統內部揭密2020-11-04
- 2019 SDC 圓桌會談回顧 | 5G時代車聯網安全的未來與展望2019-08-02
- 2023 SDC 議題回顧 | 輕舟“難”過萬重山——工控漏洞挖掘的探索實踐2023-11-10
- 故障分析 | 是誰偷走了我的 IO2022-05-03
- 2020 看雪SDC議題回顧 | 世界知名工控廠商密碼保護機制突破之旅2020-11-02密碼
- 2020 看雪SDC議題回顧 | 基於量子邏輯閘的程式碼虛擬(vmp)保護方案2020-11-02
- 2021看雪SDC議題回顧 | SaTC:一種全新的物聯網裝置漏洞自動化挖掘方法2021-11-09
- Tita的OKR:如何開好 OKR 季度回顧會議?2024-06-05OKR
- 回顧 crash log 分析2019-03-18
- 活動精彩回顧|GopherChina 2019乾貨回顧!2019-05-07Go
- 2022 SDC 議題 | 從後門到漏洞——智慧裝置私有協議中的安全問題2022-10-12協議
- 2023 SDC 議題回顧 | 從邏輯計算到神經計算:針對LLM角色扮演攻擊的威脅分析以及防禦實踐2023-11-07
- 我的樹莓派專案回顧2020-01-11樹莓派
- 回顧我學過的程式語言2017-11-16
- 回顧:我的linux歷程薦2011-09-27Linux
- 什麼是元回顧?2024-06-16
- OAuth 2.0安全案例回顧2020-08-19OAuth
- 網路安全:2018回顧&2019預測2019-01-31
- JUC之Lock介面以及Synchronized回顧2021-12-17synchronized
- HashMap?面試?我是誰?我在哪?2019-01-14HashMap面試
- 安卓 VS iOS,誰更安全?2018-11-09安卓iOS
- CRI TechSummit LIVE回顧:哪個課題是你的最愛?2022-08-31MIT
- iOS開發小貼士—APP介面跳轉卡死問題2017-08-09iOSAPP
- 2022 SDC 議題 | 面向業務守護的移動安全對抗實踐2022-10-17