预期结果:显式的制定接收组建、并且分配了合适的权限。
整改建议
1、通常采用的安全方式有设置指定action与包名
intent.setAction("allow.package.recv.action"); //设置指定的action intent.setPackage("allow.package.recv.packagename"); //设置指定的包名 sendBroadcast(intent); //发送广播
如果指定特殊的receiver接收可以指定component:
intent.setComponent(newComponentName("allow.package.recv.packagename", "allow.package.recv.classname")); sendBroadcast(intent);
2、广播如果是APP内部使用,使用LocalBroadcastManager,使广播的Intent仅在该进程内部,而不会让同一APP的其他进程或者其他APP接收到。
3、避免使用如下API:
- sendStickyBroadcast
- sendStickyBroadcastAsUser
- sendStickyOrderedBroadcast
- sendStickyOrderedBroadcastAsUser
Android SDK文档中也明确说明了存在安全问题, 如果必须使用,广播中不应包含敏感信息,另外需要设置接收权限:
//设置广播权限 sendBroadcast(intent,"broadcast.permission"); //向特定用户发送广播 this.sendBroadcastAsUser(i, null,"broadcast.permission"); this.sendOrderedBroadcastAsUser(i, null, "broadcast.permission", null, null, 0, null, null); this.sendOrderedBroadcast(i, "broadcast.permission"); this.sendOrderedBroadcast(i, "broadcast.permission", null, null, 0, null, null);
同时在AndroidManifest.xml中如下配置:
android:protectionLevel为signature,防止其他APP能够非常容易的窃取权限。
Broadcast组件越权漏洞
安全风险:攻击者可以发送恶意的消息,控制Receiver执行恶意动作或者造成信息泄露。
执行步骤
1、反编译后检索registerReceiver(),查找动态广播接收器。也可以使用命令:
run app.broadcast.info -a com.xxxx -i
2、同时留意android:exported="true"权限的组件。
3、在源代码中搜索receiver,找到应用程序定义的在接收到消息时的各项参数以及各种处理逻辑。
4、查看业务逻辑寻找是否能够直接调用Broadcast组件,是否越权进行操作。
预期结果:合理分配Broadcast组件权限。
整改建议:
- AndroidManifest.xml文件的receiver标签中设android:exported="false";
- 或者在AndroidManifest.xml中,申明一个私有权限,级别为signature;
- 私有广播接收器设置exported='false',并且不配置intent-filter,对接收来的广播进行验证;
6、Activity组件安全测试
绕过认证调用activity
安全风险:攻击者可以绕过认证阶段,直接调用后续activity组件。
执行步骤
1、反编译查看配置文件AndroidManifest.xml中activity组件(关注配置了intent-filter的及未设置export=“false”的组件)。
2、可使用工具Drozer扫描暴露的Activity:run app.activity.info -a packagename
3、执行命令run app.activity.start --component 包名 Activity名
4、查看在未经登录的情况下,登录之后的Activity能否被正常显示,如果可以则会形成越权、信息泄露等风险。
预期结果:设定正确的activity权限,避免造成越权或信息泄露。
整改建议
- app内使用的私有Activity不应配置intent-filter,如果配置了intent-filter需设置exported属性为false;
- 谨慎处理接收的intent以及其携带的信息,当Activity返回数据时候需注意目标Activity是否有泄露信息的风险;
隐式启动intent包含敏感数据
安全风险
APP创建Intent传递数据到其他Activity,如果创建Activity时通过addFlags设置了FLAG_ACTIVITY_NEW_TASK,Activity会在另一个Task中打开,这种情况很可能被其他的Activity劫持读取到Intent内容,跨Task的Activity通过Intent传递敏感信息是不安全的,会导致intent中的敏感数据泄露。
执行步骤
1、使用反编译工具打开应用,反编译出应用源码。
2、在源码中查找以下示例源码(主要是FLAG_ACTIVITY_NEW_TASK标签):
Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //设置了FLAG_ACTIVITY_NEW_TASK startActivity(intent); Intent i = new Intent("com.xiaomi.mipush.RECEIVE_MESSAGE"); startActivity(i);
3、如果FLAG_ACTIVITY_NEW_TASK标签就存在该风险,记录漏洞,停止测试。
预期结果:不包含FLAG_ACTIVITY_NEW_TASK标志的Intent启动Activity。
整改建议:避免使用包含FLAG_ACTIVITY_NEW_TASK标志的Intent启动Activity。
7、Content Provider组件测试
Provider组件导致信息泄露
安全风险:攻击者可以利用开放的Provider Content获取系统敏感资源。
执行步骤
1、查看AndroidManifest.xml文件,定位各Provider,尤其是设置了android:exported="true"的。
2、可使用工具Drozer扫描:run scanner.provider.finduris -a com.mwr.example.sieve
3、如果存在Accessible content URIs说明存在注入风险。
预期结果:系统为Content Provider组件分配合适的权限,不存在信息泄露。
整改建议
- AndroidManifest.xml文件的各provider标签中,设置android:exported="false";
- 设置minSdkVersion不低于9;
- 内部app通过content provider交换数据设置protectionLevel=“signature”验证签名,仅授予那些和本程序应用了相同密钥来签名的程序;
- 公开的content provider确保不存储敏感数据;
文件遍历漏洞
安全风险
APP的实现中定义了一个可以访问本地文件的Content Provider组件,默认的android:exported="true",该Provider实现了openFile()接口。
通过此接口可以访问内部存储app_webview目录下的数据,由于后台未能对目标文件地址进行有效判断,可以通过"../"实现目录跨越,导致对任意私有数据的访问。