您的應用是否提供了這樣的 Service,當觸發某些操做時,做爲回調它會啓動另外一個應用的 Activity
?android
好比,一個 Intent
接受了另外一個 Intent
做爲它的 Extra 參數,並將其做爲參數經過 startActivity()
進行調用。安全
您是否知道,這種作法會讓您的應用變得容易被攻擊?app
接下來,我將會解釋使用這種方法帶來的問題,並提供一個解決方案來讓您的應用在更安全的前提下實現相同功能。ide
咱們指望這種類型的交互流程以下圖所示:google
流程圖展現了一個啓動回調 activity 的 Intent 如何做爲一個擴展數據添加到一個啓動 Service 的 Intent 中,而後使用此 Intent 啓動回調 Activity
如上圖所示,Client 應用爲 ClientCallbackActivity
建立了一個 Intent
並將其做爲 extra 添加到啓動 Provider 應用的 ApiService
組件的 Intent
中。處理完啓動 ApiService 的請求以後,Provider 應用使用 Client 應用建立的 Intent
去啓動 ClientCallbackActivity
。spa
❗️這裏須要注意的是 Provider 應用正在使用它本身的應用 Context
去調用 startActivity()
方法。這樣的調用方式會產生兩個不良的後果:code
ClientCallbackActivity
是被 Provider 應用從外部啓動的,在清單文件中必須將其標識爲 exported
,這樣不只 Provider 應用能夠啓動 ClientCallbackActivity,設備上任何其餘的應用也均可以啓動。Intent
能夠被用來啓動 Provider 應用內的任意 Activity,包括私有的,可能包含敏感信息的或者非導出的 Activity。考慮一下這種場景: 若是調用方應用提供的 Intent
並非啓動調用方應用內的 Activity (好比 ClientCallbackActivity
),而是去啓動 Provider 應用中的私有 Activity,可能會發生什麼?rem
流程圖展現了,如何經過精心構建出的 Intent 來啓動 Provider 應用中的 ApiSensitiveActivity,即便它沒有被標記爲 exported,而且也不該該被其餘應用啓動。
因爲使用了嵌套 Intent
,Provider 應用很難防範其餘應用去啓動應用內部私有的、有潛在敏感信息的 Activity。由於 Provider 應用直接使用 Intent 調用 startActivity() 方法,即便 ApiSensitiveActivity
未被標記爲 exported,仍然能夠啓動它。get
解決方案很簡單: 與其接受一個 Intent
,Provider 應用能夠變爲接受 PendingIntent
。Provider 應用接受 PendingIntent 參數,不接受 Intent 參數。it
PendingIntent
和 Intent
之間的區別在於 PendingIntent
只有在其被建立的 context 才能被處理。
流程圖展現瞭如何從建立 PendingIntent 的 context 中對其進行處理,以防止攻擊者調用 Provider 應用中未被標記爲 exported 的 Activity。
因爲回調是以 PendingIntent
的方式提供的,當 Provider 應用對其調用 send()
方法時,startActivity()
方法的調用會被看成是從 Attacker 應用發起的,因爲 Attacker 應用並無啓動 ApiSensitiveActivity
的權限,系統會阻止這次調用,防止 ApiSensitiveActivity
被啓動。
這樣的作法對於 Provider 應用來講固然是有好處的,那對於咱們本身的應用呢?因爲咱們提供的是 PendingIntent
,如今就能夠將 ClientCallbackActivity
設置爲私有的,非導出的 Activity 組件。這樣的變化使得 Client 和 Provider 應用都擁有了更好的安全性。
若是您熟悉關於 notification 處理或 alarm 管理的 API,您會注意到,它們使用了 PendingIntents
去激活某項操做或者在應用內進行 alarm 提示。PendingIntents
能夠認爲是被建立它的應用所處理的,這就是系統使用 PendingIntents
而不是普通 Intent 的緣由。
使用 Intent
做爲實現對 Activity
回調的機制,不管對 Provider 仍是 Client 應用,都會給其帶來安全風險。這是由於 Intent 老是在其被調用的應用內的 Context
中被處理的。這個 Context
有可能會啓動 Provider 應用中任意非導出 Activity,而且還會強制 Client 應用導出須要接受回調的 Activity。
相反 PendingIntents
是在其被建立的 Context
中被處理,這不只可讓 Provider 應用自由地使用它們,而不用暴露出任何非導出 Activity,還可讓 Client 應用指定任意的 Activity (包括非導出的) 來接受回調。