修復 Intent Redirection 安全漏洞

開發人員請注意,如果您的應用程式含有 Intent Redirection 安全漏洞,請詳閱本文資訊。

問題說明

您的一或多個應用程式含有 Intent Redirection 問題,可能會有惡意應用程式趁機存取非公開的應用程式元件或檔案。請按照下列詳細步驟修正應用程式的問題。在 Play 管理中心 顯示的修正期限過後,Google Play 會將尚未修復安全漏洞的應用程式下架。

敬請配合

  1. 登入 Play 管理中心,然後前往「快訊」專區查看受影響的應用程式以及解決這些問題的期限。
  2. 按照下方標明的步驟更新受影響的應用程式。
  3. 提交受影響應用程式的更新版本。

我們將再次審查您重新提交的應用程式,過程可能需要數小時。如果應用程式可以通過審查並成功發布,您就不必採取進一步行動。如果應用程式未能通過審查,就無法發布新的版本,而且您將收到電子郵件通知。

其他詳細資訊

使用不受信任的 Intent 啟動元件 (如呼叫 startActivity) 或傳回資料 (如呼叫 setResult) 具有危險,並可能導致惡意應用程式造成以下問題:

  1. 從您的應用程式中竊取敏感的檔案或系統資料 (例如簡訊)
  2. 使用中毒的引數啟動應用程式的私人元件

對於不受信任的 Intent,請務必防止您的應用程式在 Intent 未經過驗證或安全處理的情況下呼叫 startActivitystartServicesendBroadcastsetResult

建議您採用下列其中一種做法來防堵這個安全漏洞:

做法 1:將受影響的應用程式元件 (擷取的 Intent 會從中重新導向) 設為不公開。

如果受影響的應用程式元件不需要接收來自其他應用程式的 Intent,您可以在資訊清單中設定 android:exported="false",將該應用程式元件設為不公開。

做法 2:確定擷取的 Intent 來自可信的來源。

您可以使用類似 getCallingActivity 的方法來驗證來源 Activity 是否可信。範例如下:

 // 檢查來源 Activity 是否來自可信任的套件
 if (getCallingActivity().getPackageName().equals(“known”)) {
   Intent intent = getIntent();
   // 擷取巢狀 Intent
   Intent forward = (Intent) intent.getParcelableExtra(“key”);
   // 將巢狀 Intent 重新導向
   startActivity(forward);
 }

注意:

  • 只檢查 getCallingActivity() 是否傳回非空值並不能完全防堵這項安全漏洞,因為惡意應用程式可以為這個函式提供空值。
  • 如果您使用的是 Google Play 服務的 SMS Retriever Auth,透過 SEND_PERMISSION 來保護廣播接收器就能確保 Intent 來自 Play 服務。

做法 3:確定要被重新導向的 Intent 是無害的。

請務必驗證被重新導向的 Intent

  1. 不會傳送至您應用程式的任何非公開元件。
  2. 不會傳送至外部應用程式的元件。如果重新導向的目標為外部應用程式,請確保 Intent 不會授予應用程式的非公開內容供應者或系統資料的 URI 權限

應用程式可以查詢用來處理 Intent 的元件為何,再使用類似 resolveActivity 的方法進行重新導向。範例如下:

 Intent intent = getIntent();
 // 擷取巢狀 Intent
 Intent forward = (Intent) intent.getParcelableExtra(“key”);
 // 取得元件名稱
 ComponentName name = forward.resolveActivity(getPackageManager());
 // 確認套件名稱和類別名稱正確無誤
 if (name.getPackageName().equals(“safe_package”) &&
     name.getClassName().equals(“safe_class”)) {
   // 將巢狀 Intent 重新導向
   startActivity(forward);
 }

應用程式可以查詢 Intent 是否使用類似 getFlags 的方法授予 URI 權限。範例如下:

 // 擷取巢狀 Intent
 Intent forward = (Intent) intent.getParcelableExtra(“key”);
 // 取得標記
 int flags = forward.getFlags();
 // 確認巢狀 Intent 並未授予 URI 權限
 if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0) &&
     (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0)) {
   // 將巢狀 Intent 重新導向
   startActivity(forward);
 }

應用程式也可以使用 removeFlags 移除已授予的 URI 權限。範例如下:

 // 不受信任的 Intent
 Intent intent = getIntent();
 // 移除在不受信任的 Intent 中授予的 URI 權限
 intent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 intent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 // 傳遞不受信任的 Intent
 setResult(intent);

瞭解快訊的作用及選擇防範選項

Play 管理中心快訊會回報您的應用程式在何處使用不受信任的 Intent 呼叫 startActivity、startActivityForResult、startService、sendBroadcast 或 setResult。如果想進一步瞭解最適當的預防做法,請追溯並檢查方法呼叫端,找出不受信任 Intent 的來源。舉例來說,如果採用做法 1,請往回追溯記錄,確定要設為不公開的元件為何。

我們很樂意提供協助

如有關於安全漏洞的技術問題,請前往 Stack Overflow 提問並加上「android-security」標記。如需進一步瞭解這個問題的解決步驟,歡迎與開發人員支援團隊聯絡。

這對您有幫助嗎?

我們應如何改進呢?
false
主選單
7874720746906224091
true
搜尋說明中心
true
true
true
true
true
5016068
false
false