MASTG-TEST-0030: Teste para Implementação Vulnerável de PendingIntent
Visão Geral¶
Ao testar Pending Intents), você deve garantir que eles sejam imutáveis e que o aplicativo especifique explicitamente o pacote exato, a ação e o componente que receberão o intent base.
Análise Estática¶
Para identificar implementações vulneráveis, a análise estática pode ser realizada procurando por chamadas de API usadas para obter um PendingIntent. Tais APIs estão listadas abaixo:
PendingIntent getActivity(Context, int, Intent, int)
PendingIntent getActivity(Context, int, Intent, int, Bundle)
PendingIntent getActivities(Context, int, Intent, int, Bundle)
PendingIntent getActivities(Context, int, Intent, int)
PendingIntent getForegroundService(Context, int, Intent, int)
PendingIntent getService(Context, int, Intent, int)
Uma vez que qualquer uma das funções acima seja identificada, verifique a implementação do intent base e do PendingIntent em busca das falhas de segurança listadas na seção Pending Intents).
Por exemplo, em A-156959408(CVE-2020-0389), o intent base é implícito e o PendingIntent também é mutável, tornando-o explorável.
private Notification createSaveNotification(Uri uri) {
Intent viewIntent = new Intent(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION)
.setDataAndType(uri, "video/mp4"); //Implicit Intent
//... skip ...
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_android)
.setContentTitle(getResources().getString(R.string.screenrecord_name))
.setContentText(getResources().getString(R.string.screenrecord_save_message))
.setContentIntent(PendingIntent.getActivity(
this,
REQUEST_CODE,
viewIntent,
Intent.FLAG_GRANT_READ_URI_PERMISSION)) // Mutable PendingIntent.
.addAction(shareAction)
.addAction(deleteAction)
.setAutoCancel(true);
Análise Dinâmica¶
O Frida pode ser usado para interceptar as APIs usadas para obter um PendingIntent. Essa informação pode ser usada para determinar a localização do código da chamada, que pode ser posteriormente usada para realizar análise estática conforme descrito acima.
Aqui está um exemplo de script em Frida que pode ser usado para interceptar a função PendingIntent.getActivity:
var pendingIntent = Java.use('android.app.PendingIntent');
var getActivity_1 = pendingIntent.getActivity.overload("android.content.Context", "int", "android.content.Intent", "int");
getActivity_1.implementation = function(context, requestCode, intent, flags){
console.log("[*] Calling PendingIntent.getActivity("+intent.getAction()+")");
console.log("\t[-] Base Intent toString: " + intent.toString());
console.log("\t[-] Base Intent getExtras: " + intent.getExtras());
console.log("\t[-] Base Intent getFlags: " + intent.getFlags());
return this.getActivity(context, requestCode, intent, flags);
}
Essa abordagem pode ser útil ao lidar com aplicativos com bases de código grandes, onde determinar o fluxo de controle pode às vezes ser complicado.