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()
obindService()
.