Activity-exported安全
Activity(exported安全)
安卓应用Activity的安全风险
android:exported(导出安全)* | Implicit Intent(隐式) | android:lauuchMode(Activity启动设置) | Flag_ACTIVITY_NEW_TASK(Activity启动设置) | android:taskAffinity(Activity启动设置) |
---|---|---|---|---|
安全绕过 | Activity劫持 | 返回劫持 | 信息泄露 | 信息泄露 |
拒绝服务 | 信息泄露 | 返回劫持 | 返回劫持 | |
信息泄露 | ||||
.... |
android:exported
Activity是否可由其他应用的组件启动"true"
表示可以,"false"
表示不可以。若为"false"
,则 Activity只能由同一应用的组件或使用同一用户ID的不同应用启动。
默认值取决于Activity是否包含Intent过滤器。没有任何过滤器意味着Activity只能通过指定其确切的类名称进行调用。这意味着Activity专供应用内部使用(因为其他应用不知晓其类名称)。因此,在这种情况下,默认值为" false"。另一方面,至少存在一个过滤器意味着Activity专供外部使用,因此默认值为"true"。
该属性并非限制Activity对其他应用开放度的唯一手段。您还可以利用权限来限制哪些外部实体可以调用 Activity(请参阅 permission属性)。
漏洞点和原理
假设场景
一个安卓设备中安装应用A和应用B,应用A有两个Activity
,Login Acitvity
是Main Activity
,也就是应用A启动后的第一个页面, X Acitvity
可导出属性为true
,并且定义了intent filter
设置action
的值为budi
,在应用B里面通过intent的方式并将值设置成budi
,这就意味着应用B的代码可以调用应用A的X Activity
。
- 如果应用B参数值设置成恶意的,可能会导致
X Acitvity
报错抛出异常崩溃退出,进而影响应用A的正常使用这样调用方式可能会存在本地拒绝服务
- 如果应用A必须要求用户必须先访问一个密码锁,才能访问
X Activity
,而应用B通过代码直接访问X Activity
,这就会导致绕过安全限制
- 在
Activity
调用之后可以访问一个结果给调用者,如果调用结果包含敏感信息就可能会出现泄露风险,如:应用B调用应用AX acitvity
返回一个敏感信息给应用B时可能会导致信息泄露
- 加入
X Activity
接受一个URL参数,并通过该URL下载一个文件到本地,应用B
传给X Acitvity
是一个恶意的URL,导致X Activity
下载一个后门App到本地有可能会应用A或整个安卓设备的安全性出现安全威胁,业务漏洞
。当然还有一种情况X Activity
包含Webview组件(Webview有一个远程命令执行漏洞),如果应用B传递给X Acitvity
是一个恶意的URL,可能会导致命令执行漏洞
在我们进行黑盒测试或者代码审计时,首先是查看安卓应用的主配置文件AndroidManifest.xml
检查所有Activity的可导出属性,这里分为两种情况
AndroidManifest.xml(No Intent filter)
没有定义Intent filter
过滤器,他的可导出属性指定为true
时,可以被外部组件调用
AndroidManifest.xml(Intent filter)
定义Intent filter
过滤器,此时可导出属性的默认值为true
,也可以被外部组件调用
测试方法
黑盒:
先逆向获取AndroidManifest.xml
查看
可以通过原始adb shell
进行调用测试
am start -a android.intent.action.MAIN -n package/component
am start -n com.android.mypackage/com.android.mypackageLaunchMeActivity
示例
(假装是个正常的App)
在我们代码审计时,拿到源码首先需要检查他的主配置文件(AndroidManifest.xml)
查看有的Activity的可导出属性,这里是给出两个示例的Activity
分别是SecurityActivity
和DoSActivity
,这两个都定义了intent-filter
,可导出默认属性都为True
,接下来看下实际的使用过程.
首先查看MainActivity
,查看第一段代码有个button注册了一个点击事件调用了SecurityActivity
,并且传递了1
个参数值
跟入SecurityActivity
查看定义,也很简单意思是取出参数值source,并将参数值设置到textView里面
返回MainAcitvity
查看第二个Button
注册了点击事件调用DoSActivity
传递了"number, "3"
给DoSActivity
跟入DoSActivity
查看定义,这里可以看到这段代码用于取出参数值number,接下来对number值进行了强制转换成整数(这里就有可能抛出异常,因为有可能number传递过来的字符串不能转换成整数因此可能会影响应用正常使用)
将App安装完成后,查看第一个button
会访问SecurityActivity
并且传递一个参数值source
为Normal
参考效果,SecurityActivity
调用源为Normal
在查看第二个button
,会传递一个数字3
给DoSActivity
接下来就是如何编写一个恶意的App,对这个NormalApp
进行攻击
攻击SecurityActivity
是SecurityActivity
里面的intent-filter里面的action值,new一个Intent,设置成SecurityActivity
的action
值,传递一个source
参数值为Evil App
,然后启动这个Activity
就可以了
攻击DoSActivity
是DoSActivity
里面的intent-filter里面的action值,然后传递的是一个number
参数,值为Evil App
,然后在启动Acitvity
运行一下查看效果(攻击app)
第一个button
,这样就可以看到NormalApp
里面的securityActivity
,相当于绕过了他的MainActivity
(或者说LoginAcitvity
需要一些认证的地方)
第二个button
,访问的是DosActivity
,传递的是一个number
值的Evil App
在转换为整型的时候会出现报错导致Normal
App的退出
效果App退出,如果这个时候打开Android studio,可以看到报数字格式的Exception错误了
安全建议
- 若不需外部应用调用
Activity
,明确指出该exported
属性为false
;
<activity
android:name=".activity.FirstAcitvity"
android:label="this is FirstActivity"
android:exported="false">
</activity>
- 若需外部应用调用,使用
signature
或signatureOrSystem
权限;(都是通过校验App的证书来验证是否是授权的调用源)
<activity
android:name=".activity.FirstAcitvity"
android:label="this is FirstActivity"
android:exported="false"
android:prottectionLevel="signature">
</activity>