背景
藍芽技術是一種無線資料和語音通訊開放的全球規範,它是基於低成本的近距離無線連線,為固定和移動裝置建立通訊環境的一種特殊的近距離無線技術連線。藍芽具有無線、短程等特點,主要能夠提供裝置到裝置之間的通訊。藍芽協議目前從最初的 1.0 版本更新到了 5.3 版本,並在 4.0 版本之後分為了經典藍芽(BC)和低功耗藍芽(BLE),BLE 在保證了 BC 的大部分效能的情況下最大程度上降低了功耗,因此在如今的更多智慧裝置中被採用。
本篇部落格將介紹一種新型的低功耗藍芽攻擊方式,攻擊發生在藍芽的配對過程中。論文來自於《Method Confusion Attack on Bluetooth Pairing》,程式碼放在了 github。
原理
低功耗藍芽配對過程
低功耗藍芽配對共分為四個步驟:配對資訊交換、公鑰交換、認證階段、長期金鑰的生成與驗證。
配對資訊交換
在配對資訊交換階段,將要進行配對的裝置會交換配對過程中一些所必須的資訊,比如:
- OOB-bit:表明帶外資訊是否準備就緒
- MitM-bit:表明是否需要驗證
- IOCaps:表明待配對裝置的輸入輸出能力
IOCaps一般會表明待配對裝置的輸入輸出能力,具體分為以下六種:
- DisplayOnly:裝置只能顯示一個6位數的數字值。
- DisplayYesNo:裝置可以顯示一個6位數的數值,使用者可以輸入確認(是或否)。
- KeyboardOnly:使用者可以輸入一個6位數的數字值和一個確認。
- KeyboardDisplay:裝置可以顯示一個6位數的數字值,使用者可以輸入一個6位數的數字值並確認。
- NoInputNoOutput。裝置沒有能力與使用者通訊
根據不同的輸入輸出能力,認證階段會採取不同的認證方式。
公鑰交換
在完成配對資訊交換後,會進入公鑰交換階段,如圖1所示。首先發起者I與響應者R會分別選取一個私鑰 \(SK_I\) 與 \(SK_R\) ,之後採用 Elliptic Curve Diffie-Hellman (ECDH) 演算法加密生成公鑰 \(PK_I\) 與 \(PK_R\)。在交換公鑰之後,在交換公鑰之後,再分別根據自己的私鑰計算出相同的 \(DHK\),從而生成相同的金鑰。
認證階段
為了驗證交換的公鑰是否正確,保證交換過程中沒有遭到中間人攻擊,目前常用的認證方法共有四種:
-
Just Works(直接工作):金鑰未經驗證(即未經驗證的安全要求)。
-
Out of Band(帶外認證):公鑰透過獨立於藍芽的反向通道(例如,NFC、二維碼)進行驗證。
-
Numeric Comparison(數字比較):使用者在兩臺裝置上顯示一個 6 位數字,必須確認它們是否相等。
-
Passkey Entry(密碼輸入):使用者在一臺裝置上顯示一個 6 位密碼,並被要求將其輸入另一臺裝置。
在認證階段,會根據交換得到的 IOCaps 位,即兩個待配對裝置的輸入輸出能力,來採取不同的認證方式,如下圖所示。
方法混淆攻擊的主要物件是數字比較與密碼輸入兩種方法,下面將詳細說明兩種認證方法的異同。
數字比較(Numeric Comparison)
首先發起者 \(I\) 與響應者 \(R\) 會分別生成一個設定值 \(ra\) 和 \(rb\)(為0),一個隨機值 \(N_I\) 和 \(N_R\)。之後響應者 \(R\) 會用由協議規定的 \(f4\) 演算法根據公鑰 \(PK_I\) 與 \(PK_R\)、隨機值 \(N_R\) 與設定值 \(rb\) 生成一個校驗值 \(C_R\),傳遞給發起者 \(I\),並在交換 \(N_I\) 和 \(N_R\) 後,由發起者進行校驗。隨後發起者 \(I\) 與響應者 \(R\) 會由公鑰 \(PK_I\) 與 \(PK_R\),隨機值 \(N_I\) 和 \(N_R\) 雜湊出一個六位數字,並在兩邊的裝置上顯示,由使用者對兩個數字進行比較並確認。若確認結果相同,則完成認證,否則認證失敗。
下面這個影片演示了數字比較的過程:
密碼輸入(Passkey Entry)
首先在發起者 \(I\) 與響應者 \(R\) 會有一方生成一個 20 位密碼,並由使用者輸入到另外一方,雙方便獲得了相同的設定值 \(ra\) 和 \(rb\)。隨後雙方會對 \(ra\) 與 \(rb\) 進行逐位檢驗。具體過程是,對於 \(ra\) 和 \(rb\) 的每一位,發起者 \(I\) 與響應者 \(R\) 會首先生成一個隨機值 \(N_I\) 和 \(N_R\)。之後雙方會用由協議規定的 \(f4\) 演算法根據公鑰 \(PK_I\) 與 \(PK_R\)、隨機值 \(N_I\) 和 \(N_R\) 生與設定值當前位 \(rai\) 與 \(rbi\) 生成校驗值 \(C_I\) 與 \(C_R\),並在交換 \(N_I\) 和 \(N_R\)、\(C_I\) 與 \(C_R\) 後,由雙方進行校驗。在這個過程迴圈 20 次,\(ra\) 與 \(rb\) 的每一位都得到校驗後,若所有位相同,即完成了密碼輸入的認證過程,否則認證失敗。
下面這個影片演示了密碼輸入的過程:
長期金鑰的生成與驗證
在完成驗證之後,雙方會由協議規定的 \(f5\) 演算法根據 \(DHK\),隨機值 \(N_I\) 和 \(N_R\),地址 \(addr_I\) 和 \(addr_R\) 生成長期金鑰 \(LTK\),\(LTK\) 會作為長期通訊中的加密金鑰,有了 \(LTK\) 之後下次兩個藍芽裝置之間就無需配對過程:
此外,在生成長期金鑰後,還會進行最終階段的驗證,如下圖所示
方法混淆攻擊
根據 Initiator 和 Responder 與中間人驗證方式的不同,方法混淆攻擊分為 PoN 攻擊與 NoP 攻擊兩種,其中 PoN 方法混淆攻擊的原理如下圖所示。
首先在配對資訊交換階段,在接收到發起者 \(I\) 的資訊後,觸發中間人發起者 \(M_I\) 與響應者 \(R\) 進行配對資訊交換。注意此時中間人響應者 \(M_R\) 返回給發起者 \(I\) 的 IOCaps 為 DisplayOnly,而中間人發起者 \(M_I\) 發給響應者 \(R\) 的 IOCaps 為 DisplayYesNo,這樣便保證了之後在認證階段中間人響應者 \(M_R\) 與發起者 \(I\) 進行密碼輸入認證,而中間人發起者 \(M_I\) 與響應者 \(R\) 進行數字比較認證。
之後中間人者 \(M_R\) 與 \(M_I\) 分別與發起者 \(I\) 與響應者 \(R\) 進行公鑰交換。完成後首先中間人發起者 \(M_I\) 和響應者 \(R\) 會進行數字比較認證,並在此過程中將比較值傳給中間人響應者 \(M_R\), 中間人響應者便會利用這個值與真正的發起者進行密碼輸入認證。由於所有值都是由中間人傳輸的,所以雙方最終都會認證透過並進入長期金鑰的生成與驗證階段,同理,最終驗證也會透過。至此,便完成了中間人 \(M_R\) 與 \(M_I\) 與真正的發起者 \(I\) 與響應者 \(R\) 之間的藍芽配對。NoP 攻擊原理和 PoN 類似,唯一的差別就是交換了 Initiator 和 Responder 與中間人的驗證方式。
BTstack
BTstack 開源庫實現了藍芽協議棧,它的架構如圖7所示。可以看到,BTstack 使用單個 Run Loop 處理應用程式或者藍芽模組發來的資料包。藍芽協議棧有 GAP、ATT 和 L2CAP 等多個層級,BTstack 在每個層級處都提供了回撥函式,應用程式可以在這些回撥函式中處理收到的資料。
實驗過程
實驗配置
為了實現 NoP 攻擊,我們準備了 4 個不具備獨立 MAC 地址的 CSR 藍芽加密狗,接著使用 Bluetooth Mac Address Changer 工具修改加密狗的 MAC 地址,使得他們的 MAC 地址各不相同。NoP 攻擊框圖如下圖所示,兩個加密狗作為 Initiator\((I)\) 和 Responder\((R)\),另外兩個作為 Mitm Responder\((M_R)\) 和 Mitm Initiator\((M_I)\),其中 \(I\) 與 \(M_R\)、\(R\) 與 \(M_I\) 之間透過藍芽進行通訊,\(M_R\) 與 \(M_I\) 之間使用管道進行程式間通訊。
實驗一開始,啟動 Responder 程式,向外界廣播 ADV_IND 幀,表明自己處於可連線的狀態。接著啟動 \(M_R\) 與 \(M_I\) 父子程式,其中 \(M_R\) 的藍芽名和 \(R\) 保持一致,這樣 Initiator 就可能錯誤地將 \(M_R\) 當做 \(R\) 而與中間人進行連線。如下圖所示,手機藍芽的可用裝置中有兩個名為 CARDREADER 的藍芽裝置,Initiator 無法辨別出哪個是 \(R\) 那個是 \(M_R\)。
配對過程
- \(I\) 與 \(M_R\) 建立連線,觸發
HCI_EVENT
,BTstack 建立型別為HCI_EVENT_LE_META
型別的 packet 並呼叫 \(M_R\) 的responder_sm_packet_handler
回撥函式,這個回撥函式用來處理與加密連線配對相關的資料包; - 在
responder_sm_packet_handler
回撥函式中將啟動 \(M_I\) 與 \(R\) 的連線的訊息寫入管道; - \(M_I\) 監聽到管道中有讓自己與 \(R\) 進行連線的訊息,就立即與 \(R\) 建立連線,並接著等待 \(M_R\) 給自己發過來 \(V_a\);
- \(M_R\) 將計算出的 \(V_a\) 寫入管道;
- \(M_I\) 收到管道中傳來的 \(V_a\),完成與 \(R\) 之間的 Passkey Entry 驗證過程
通訊過程
- \(I\) 透過藍芽模組傳送訊息給 \(M_R\);
- \(M_R\) 收到訊息,觸發
l2cap_mitm_responder_packet_handler
回撥函式,這個回撥函式用來處理 L2CAP 層的資料包; l2cap_mitm_responder_packet_handler
中識別到 packet 型別為L2CAP_DATA_PACKET
,將 packet 的資料複製到緩衝區中,此時也可以直接修改緩衝區的資料為中間人想要的訊息;- BTStack 的 Run Loop 的每次迴圈都會呼叫
forward_packet
函式,在這個函式中 \(M_R\) 將緩衝區的資料寫入管道; - \(M_I\) 在
forward_packet
函式中將管道的資料複製到緩衝區,接著轉發給 \(R\)
實驗結果
NoP攻擊結果如下述影片,Initiator 傳送的原始訊息“硝子真可愛”被中間人截獲,並被修改為“我家硝子真可愛”後轉發給 Responder,此時 Responder 收到的就是修改後的訊息。
總結
在本文中,我們復現了藍芽配對方法混淆攻擊,該攻擊方式利用藍芽配對過程中裝置不會確認雙方實際使用的認證方式是否相同的漏洞,成功實現了發起者和響應者的雙向欺騙。該攻擊方式被提出之後,部分手機廠商(如華為)在藍芽配對的確認環節會彈出提示框,要求裝置使用者仔細核對認證方式是否相同,這在一定程度上可以減少方法混淆攻擊的危害性,但治標不治本,要想徹底杜絕方法混淆攻擊的危害,需要對藍芽協議打上補丁。