Categoria do OWASP: MASVS-PLATFORM - Interação com plataformas
Visão geral
O redirecionamento de intents ocorre quando um invasor pode controlar total ou parcialmente o conteúdo de uma intent usada para iniciar um novo componente no contexto de um app vulnerável.
A intent usada para iniciar o novo componente pode ser fornecida de várias maneiras,
geralmente em uma intent serializada em um campo extras
ou empacotada
com uma string e analisada. O controle parcial dos parâmetros também pode levar ao mesmo
resultado.
Impacto
O impacto pode variar. Um invasor pode executar recursos internos no app vulnerável ou acessar componentes particulares, como objetos ContentProvider não exportados.
Mitigações
No geral, não exponha recursos relacionados ao redirecionamento de intents aninhadas. Nos casos em que isso não puder ser evitado, aplique os seguintes métodos de mitigação:
- Limpe as informações agrupadas. Não se esqueça de verificar
ou limpar as flags (
FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and FLAG_GRANT_PREFIX_URI_PERMISSION
) e conferir para onde a intent está sendo redirecionada. OIntentSanitizer
pode ajudar nesse processo. - Use objetos
PendingIntent
. Isso evita que seu componente seja exportado e torna a intent de ação de destino imutável.
Os apps podem usar métodos como o
ResolveActivity
e verificar para onde uma intent está sendo redirecionada:
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);
}
Os apps podem usar IntentSanitizer
com uma lógica semelhante a esta:
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);
Erros comuns
- Verificar se
getCallingActivity()
retorna um valor não nulo. Apps maliciosos podem fornecer um valor nulo para essa função. - Supor que
checkCallingPermission()
funciona em todos os contextos ou que o método gera uma exceção quando, na verdade, ele está retornando um número inteiro.
Recursos de depuração
Para apps direcionados ao Android 12 (nível 31 da API) ou versões mais recentes, é possível ativar um recurso de depuração que, em alguns casos, ajuda a detectar se o app está executando uma inicialização não segura de uma intent.
Se o app realizar as duas ações a seguir, o sistema vai detectar uma
inicialização de intent não segura e ocorrerá uma violação de StrictMode
:
- O app separa as intents aninhadas das outras intents enviadas.
- O app inicia imediatamente um componente do app usando essa intent aninhada, como
transmitindo a intent para
startActivity()
,startService()
oubindService()
.