你真的了解taskAffinity属性么?

在2019年,有安全研究员向Google官方提交了一个利用taskAffinity的漏洞,后面被命名为StandHogg。最近在2020年5月份又公布了StandHogg 2.0漏洞。StandHogg 2.0 隐藏的更深,一般很难发现,甚至都不用设置taskAffinity就可以实现。目前官方已经发布了Android 10.0系统补丁包,有条件的可以对系统进行升级。有兴趣的同学可以看下这篇文章:https://www.xda-developers.com/strandhogg-2-0-android-vulnerability-explained-developer-mitigation/

一、taskAffinity

这个属性在AndroidManifest.xml中进行设置,有2个地方,一个在application标签里面,一个在activity标签里面。当App启动时,对AndroidManifest.xml进行解析后,会放在ApplicationInfo与ActivityInfo类中。对其的定义与描述如下:

$1.1、ApplicationInfo
 /**
     * Default task affinity of all activities in this application. See 
     * {@link ActivityInfo#taskAffinity} for more information.  This comes 
     * from the "taskAffinity" attribute. 
     */
    public String taskAffinity;
$1.2、ActivityInfo

在这里插入图片描述
上面的注释我有以下几点理解:

  1. taskAffinity属性,如果设置在<application>则对所有Activity生效,默认为应用包名;
  2. taskAffinity属性,作用于Activity,针对多任务而言,表示对另外一个任务的亲和度
  3. taskAffinity的值一般用应用包名表示;
  4. 如果手动设置taskAffinity为空,则当前Activity只属于当前task,对其他task无亲和度

二、allowTaskReparenting

官方对此属性的注释如下:

   /**
     * Bit in {@link #flags} that indicates that the activity can be moved
     * between tasks based on its task affinity.  Set from the
     * {@link android.R.attr#allowTaskReparenting} attribute.
     */
    public static final int FLAG_ALLOW_TASK_REPARENTING = 0x0040;

同样,基于注释,我有以下几点理解:

  1. 此属性作用于activity,且基于activity设置的task affinity属性。如果没有设置,则默认为应用包名
  2. 如果allowTaskReparenting为true。且taskAffinity有设值,则表示允许当前activity从“当前包名task"移动至”taskAffinity指定的task"。

三、StandHogg漏洞

此漏洞的原理就是恶意APP利用taskAffinity属性,来实现task任务栈的劫持。
成功劫持的条件如下:

  1. 目标应用<application>中taskAffinity没有手动设置空字符串。
  2. 恶意应用 的钓鱼界面的taskAffinity 设置为目标应用的包名。且allowTaskReparenting = true或者不设置allowTaskReparenting但在启动钓鱼界面的intent中setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

POC成功后,采用adb shell dumpsys activity查看任务栈信息如下:

第一种情况:设置allowTaskReparenting = true

// 恶意应用设置allowTaskReparenting=true
Display #0 (activities from top to bottom):
  Stack #1:
    Task id #24
      TaskRecord{2d220957 #24 A=ext.sunny.com.taskaffinitydemo U=0 sz=1}
      Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
        Hist #0: ActivityRecord{30a4df6d u0 ext.sunny.com.attackapp/.AttackActivity t24}
          Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
          ProcessRecord{277e412d 4287:ext.sunny.com.attackapp/u0a31}
    Task id #23
      TaskRecord{26a0ac44 #23 A=ext.sunny.com.attackapp U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=ext.sunny.com.attackapp/.MainActivity }
        Hist #0: ActivityRecord{36ccc73e u0 ext.sunny.com.attackapp/.MainActivity t23}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=ext.sunny.com.attackapp/.MainActivity bnds=[222,930][434,1290] }
          ProcessRecord{277e412d 4287:ext.sunny.com.attackapp/u0a31}

第二种情况:采用setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)来启动钓鱼界面。启动如下:

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("sunny","恶意APP:MainActivity $ task:"+getTaskId());
        Intent intent = new Intent(this, AttackActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        finish();
    }

dump 信息如下:

 //恶意应用用setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    Display #0 (activities from top to bottom):
      Stack #1:
        Task id #24
          TaskRecord{2d220957 #24 A=ext.sunny.com.taskaffinitydemo U=0 sz=1}
          Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
            Hist #0: ActivityRecord{30a4df6d u0 ext.sunny.com.attackapp/.AttackActivity t24}
              Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
              ProcessRecord{277e412d 4287:ext.sunny.com.attackapp/u0a31}
        Task id #23
          TaskRecord{26a0ac44 #23 A=ext.sunny.com.attackapp U=0 sz=1}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=ext.sunny.com.attackapp/.MainActivity }
            Hist #0: ActivityRecord{36ccc73e u0 ext.sunny.com.attackapp/.MainActivity t23}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=ext.sunny.com.attackapp/.MainActivity bnds=[222,930][434,1290] }
              ProcessRecord{277e412d 4287:ext.sunny.com.attackapp/u0a31}

而对于其他在Activity中设置taskAffinity,然后再设置launchMode=“singleTask” 或者启动的时候采用setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),如果先启动恶意应用,然后Home键退至后台,再打开目标 应用 。则钓鱼界面与目标界面在会同一个task里面,但是目标界面在栈顶。dump信息如下:

Display #0 (activities from top to bottom):
  Stack #1:
    Task id #26
      TaskRecord{44806dd #26 A=com.sunny.standhogg U=0 sz=2}
      Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
        Hist #1: ActivityRecord{13b653a8 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t26}
          Intent { flg=0x10400000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity } //目标界面
          ProcessRecord{3b61d923 4481:ext.sunny.com.taskaffinitydemo/u0a32}
        Hist #0: ActivityRecord{3f62b3a6 u0 ext.sunny.com.attackapp/.AttackActivity t26}
          Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity } // 钓鱼界面
          ProcessRecord{2ce44e20 4443:ext.sunny.com.attackapp/u0a31}

四、对StandHogg的防护措施

从上面可以看出,当在taskAffinity与allowTaskReparenting、taskAffinity与setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)时,可以成功

第一种,在启用Activity的时,添加如下标记:

       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 

添加后,dump信息如下:

 Stack #1:
    Task id #42
      TaskRecord{c29e68f #42 A=com.sunny.standhogg U=0 sz=1}
      Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
        Hist #0: ActivityRecord{21ed6e63 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t42}
          Intent { flg=0x10408000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity }
          ProcessRecord{a3bad25 5186:ext.sunny.com.taskaffinitydemo/u0a32}

第二种:针对利用taskAffinity = 目标应用包名,进行整个task劫持

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:taskAffinity=""  //手动将taskAffinity置为空
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

dump信息如下:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #1:
    Task id #51  //目标应用
      TaskRecord{3029c50e #51 I=ext.sunny.com.taskaffinitydemo/.LoginActivity U=0 sz=1}
      Intent { flg=0x10008000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity }
        Hist #0: ActivityRecord{f97a149 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t51}
          Intent { flg=0x10008000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity }
          ProcessRecord{1918c2c5 5583:ext.sunny.com.taskaffinitydemo/u0a32}
    Task id #49 //恶意应用
      TaskRecord{464553c #49 A=ext.sunny.com.taskaffinitydemo U=0 sz=1}
      Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
        Hist #0: ActivityRecord{95cb3af u0 ext.sunny.com.attackapp/.AttackActivity t49}
          Intent { flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity }
          ProcessRecord{2441241a 5540:ext.sunny.com.attackapp/u0a31}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值