一、漏洞背景
- 研究人员在Android操作系统中发现一个最新漏洞,并命名为StrandHogg,攻击者可利用该漏洞伪装成合法的应用程序,目前已被BankBot等多个恶意木马积极利用。
二、漏洞细节
- 在Android系统中,Activity作为向用户展示可视内容的组件,它是以任务的方式进行组织的。Android提供了允许开发者干预Activity任务的一些方式,当这种机制被恶意程序利用后,就会产生意想不到的效果。
- 在默认情况下,每个应用程序的所有Activity都位于同一个任务栈中,这个任务栈的名称和该应用程序的包名相同。在AndroidManifest.xml中定义Activity,或者使用Intent来启动一个Activity时,开发者可以对这个Activity的任务和返回栈行为进行修改。例如在AndroidManifest.xml中可以为Activity指定
launchMode
属性,含义如下:
standard
,该值为默认值,这种情况下该Activity可以被多次实例化,每个Activity实例可以属于不同的任务,并且一个任务也可以具有多个该Activity实例。(多次创建,不同分属,相同归属)
singleTop
,这种情况下,如果Activity的实例已经存在于当前任务的栈顶,则Android会通过调用其onNewIntent()
方法将Intent传递到该实例,而不是创建该Activity的新实例。该Activity可以被实例化多次,每个Activity实例可以属于不同的任务,一个任务也可以具有多个该Activity的实例,当然由于上述的特性,在一个任务栈中不会存在两个相邻的该Activity的实例。(栈顶复用,不同分属,相同归属,栈中不邻)
singleTask
,这种情况下,在创建Activity时候,Android将创建一个新任务,并在新任务的底部实例化该Activity。但是,如果Activity的实例已经存在于单独的任务中,则Android同样会调用其onNewIntent()
方法将Intent传递到现有实例 ,而不是创建新实例。所以一次只能存在一个该Activity的实例。(任务复用,独立任务,全局唯一)
singleInstance
,这种情况下,和singleTask
类似,但系统不会将任何其他Activity添加到该Activity所在的任务中。该Activity始终是其任务的唯一的成员。由该任务开始的任何该Activity都在单独的新任务中打开。(独占任务,全局唯一)
- 如前所述,使用Intent来启动Activity时,也可以携带标志来修改Activity任务的行为,可以修改行为的标志有:
FLAG_ACTIVITY_NEW_TASK
:相当于使用了launchMode=singleTop
FLAG_ACTIVITY_SINGLE_TOP
:相当于使用了launchMode=singleTop
FLAG_ACTIVITY_CLEAR_TOP
:如果正在启动的Activity已经在当前任务中运行,那么Android将清除任务栈中该Activity以上的所有其他Activity,并调用其onNewIntent()
方法将Intent传递到现有实例。没有和该标志对应的launchMode
值。
- 然后,在AndroidManifest.xml中定义Activity时,还可以指定
taskAffinity
属性,用于指定该Activity对于特定任务的亲和性,默认情况下该参数不进行指定,即Activity对其他任务不具备亲和性。因为任务的名称是形如包名的形式,所以指定的taskAffinity
属性看起来也是一个包名的形式。
- 此外,在AndroidManifest.xml中定义Activity时,还有
allowTaskReparenting
属性,该值为布尔类型,默认为false,为true表示当该Activity所亲和的任务进入前台时,该Activity可以从它原来的任务转移到它所亲和的任务。由于具有singleTask
或singleInstance
启动模式的Activity只能在任务栈底,因此该属性仅对于standard
和singleTop
模式有效。
- 由于有了这些属性,当一个Activity设置了
taskAffinity
为另一个应用的包名,并且launchMode
为singleTop
且allowTaskReparenting
为true的时候,或出现这样的现象:首先启动这个Activity,并将其放入后台运行返回桌面,再点击另一个应用,你会发现这个Activity又出现在屏幕上。正是因为Android对任务栈的重排机制,导致了这样的结果。
- 详细可参考Android官方的文档:任务和返回栈 – Android Developers
三、漏洞验证
- 编写一个应用程序,对其MainActivity设置
taskAffinity
为被攻击应用的包名,并且allowTaskReparenting
为true,启动该Activity并放入后台运行。当打开被攻击应用时,该Activity将会被显示出来,而不是被攻击的应用。
四、漏洞影响
- 该漏洞允许攻击者编写应用程序仿冒合法的应用程序,通过编写极其相似的界面,可以诱骗用户输入密码,或通过向用户申请相关权限,进行隐私窃取。所有Android版本都受影响。
五、漏洞补丁
- 根据研究者的文章,Google认为这是一个正常的功能特性,所以Google仅仅是下架了Google Play上相关的恶意应用,并不会修复这个问题。在这种情况下,建议用户特别警惕无故要求重新登录账号以及重新授权权限的请求,并且保证仅从官方的应用市场下载应用。
- 更新:在Android 11版本安全公告中,Google已公开披露此漏洞,级别为Critical,分配了CVE-2020-0267编号跟踪,同时漏洞也在Android 11中被修补:现在
taskAffinity
字段只对相同UID的应用有效,也就是说,只有共享UID的应用才可以使用该方法进行界面的替代。