Reindirizzamento intent

Categoria OWASP: MASVS-PLATFORM: Interazione con la piattaforma

Panoramica

Un reindirizzamento intent si verifica quando un malintenzionato può controllare parzialmente o completamente i contenuti di un intent utilizzato per avviare un nuovo componente nel contesto di un'app vulnerabile.

L'intenzione utilizzata per avviare il nuovo componente può essere fornita in diversi modi, solitamente come intenzione serializzata in un campo extras o in una stringa marshallata e analizzata. Anche il controllo parziale dei parametri può portare allo stesso risultato.

Impatto

L'impatto può variare. Un malintenzionato potrebbe eseguire funzionalità interne nell'app vulnerabile o accedere a componenti privati come oggetti ContentProvider non esportati.

Mitigazioni

In generale, non esporre funzionalità relative al reindirizzamento degli intent nidificati. Nei casi in cui non sia possibile evitarlo, applica i seguenti metodi di mitigazione:

  • Sottoponi a sanificazione corretta le informazioni in bundle. È importante ricordare di controllare o cancellare i flag (FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and FLAG_GRANT_PREFIX_URI_PERMISSION) e di verificare dove viene reindirizzato l'intent. IntentSanitizer può aiutarti a completare questa procedura.
  • Utilizza gli oggetti PendingIntent. In questo modo, il componente non viene estratto e l'intent dell'azione target diventa immutabile.

Le app possono controllare dove viene reindirizzato un intent utilizzando metodi come ResolveActivity:

Kotlin

val intent = getIntent()
// Get the component name of the nested intent.
val forward = intent.getParcelableExtra<Parcelable>("key") as Intent
val name: ComponentName = forward.resolveActivity(packageManager)
// Check that the package name and class name contain the expected values.
if (name.packagename == "safe_package" && name.className == "safe_class") {
    // Redirect the nested intent.
    startActivity(forward)
}

Java

Intent intent = getIntent()
// Get the component name of the nested intent.
Intent forward = (Intent) intent.getParcelableExtra("key");
ComponentName name = forward.resolveActivity(getPackageManager());
// Check that the package name and class name contain the expected values.
if (name.getPackageName().equals("safe_package") &&
        name.getClassName().equals("safe_class")) {
    // Redirect the nested intent.
    startActivity(forward);
}

Le app possono utilizzare IntentSanitizer con una logica simile alla seguente:

Kotlin

val intent = IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent)

Java

Intent intent = new  IntentSanitizer.Builder()
     .allowComponent("com.example.ActivityA")
     .allowData("com.example")
     .allowType("text/plain")
     .build()
     .sanitizeByThrowing(intent);

Errori comuni

  • Controlla se getCallingActivity() restituisce un valore diverso da null. Anche le app dannose possono fornire un valore null per questa funzione.
  • Supponendo che checkCallingPermission() funzioni in tutti i contesti o che il metodo generi un'eccezione quando restituisce effettivamente un numero intero.

Funzionalità di debug

Per le app destinate ad Android 12 (livello API 31) o versioni successive, puoi attivare una funzionalità di debug che, in alcuni casi, ti aiuta a rilevare se la tua app sta eseguendo un lancio non sicuro di un intent.

Se la tua app esegue entrambe le seguenti azioni, il sistema rileva un lancio di intent non sicuro e si verifica una violazione di StrictMode:

  • La tua app estrae un intent nidificato dagli extra di un intent inviato.
  • L'app avvia immediatamente un componente dell'app utilizzando quell'intent nidificato, ad esempio passandolo a startActivity(), startService() o bindService().

Risorse