你真的了解taskAffinity属性么?

Posted 安静的Sunny

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的了解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
      TaskRecord2d220957 #24 A=ext.sunny.com.taskaffinitydemo U=0 sz=1
      Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
        Hist #0: ActivityRecord30a4df6d u0 ext.sunny.com.attackapp/.AttackActivity t24
          Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
          ProcessRecord277e412d 4287:ext.sunny.com.attackapp/u0a31
    Task id #23
      TaskRecord26a0ac44 #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: ActivityRecord36ccc73e 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] 
          ProcessRecord277e412d 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
          TaskRecord2d220957 #24 A=ext.sunny.com.taskaffinitydemo U=0 sz=1
          Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
            Hist #0: ActivityRecord30a4df6d u0 ext.sunny.com.attackapp/.AttackActivity t24
              Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
              ProcessRecord277e412d 4287:ext.sunny.com.attackapp/u0a31
        Task id #23
          TaskRecord26a0ac44 #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: ActivityRecord36ccc73e 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] 
              ProcessRecord277e412d 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
      TaskRecord44806dd #26 A=com.sunny.standhogg U=0 sz=2
      Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
        Hist #1: ActivityRecord13b653a8 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t26
          Intent  flg=0x10400000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity  //目标界面
          ProcessRecord3b61d923 4481:ext.sunny.com.taskaffinitydemo/u0a32
        Hist #0: ActivityRecord3f62b3a6 u0 ext.sunny.com.attackapp/.AttackActivity t26
          Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity  // 钓鱼界面
          ProcessRecord2ce44e20 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
      TaskRecordc29e68f #42 A=com.sunny.standhogg U=0 sz=1
      Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
        Hist #0: ActivityRecord21ed6e63 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t42
          Intent  flg=0x10408000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity 
          ProcessRecorda3bad25 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  //目标应用
      TaskRecord3029c50e #51 I=ext.sunny.com.taskaffinitydemo/.LoginActivity U=0 sz=1
      Intent  flg=0x10008000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity 
        Hist #0: ActivityRecordf97a149 u0 ext.sunny.com.taskaffinitydemo/.LoginActivity t51
          Intent  flg=0x10008000 cmp=ext.sunny.com.taskaffinitydemo/.LoginActivity 
          ProcessRecord1918c2c5 5583:ext.sunny.com.taskaffinitydemo/u0a32
    Task id #49 //恶意应用
      TaskRecord464553c #49 A=ext.sunny.com.taskaffinitydemo U=0 sz=1
      Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
        Hist #0: ActivityRecord95cb3af u0 ext.sunny.com.attackapp/.AttackActivity t49
          Intent  flg=0x10000000 cmp=ext.sunny.com.attackapp/.AttackActivity 
          ProcessRecord2441241a 5540:ext.sunny.com.attackapp/u0a31

以上是关于你真的了解taskAffinity属性么?的主要内容,如果未能解决你的问题,请参考以下文章

你真的了解DOM事件么?

你真的了解load方法么?(转载)

android权限机制,你真的了解么

你真的了解 “开源” 么?请查收保姆级开源百科

android权限机制,你真的了解么

你真的了解盒模型么