6
【編者按】本文來自烏云,作者FengGou。
0x01 前言
因為自己曾DIY過所謂的“智能硬件”,學(xué)習(xí)過程中除了接觸各種芯片、傳感器、電路知識外,也拆了不少設(shè)備分析其設(shè)計思想學(xué)以致用。再后來又接觸了如:Wi-Fi、ZigBee、Bluetooth、NFC、IR、普通射頻甚至音頻等通信技術(shù),才發(fā)現(xiàn)空氣中那些形形色色的邊界,才是整個物聯(lián)安全的關(guān)鍵。
今天的內(nèi)容是我在烏云內(nèi)部做的技術(shù)分享,也是我以前對低功耗藍(lán)牙技術(shù)的一些接觸,整理后決定對社區(qū)公布。一來可以讓社區(qū)對神秘的藍(lán)牙技術(shù)破冰;二來也是拋磚引玉,希望能看到更多有趣的案例;三來比起那些華麗麗的show,我更喜歡分享一些實際的內(nèi)容。
0x02 BLE 協(xié)議??傆[,GAP、GATT講解
0x03 BLE嗅探
0x04 偽造BLE通信
(理論細(xì)節(jié)過于繁復(fù),暫且略去,感興趣的童鞋可進烏云平臺原文查看)
0x05 分析BLE私有數(shù)據(jù)協(xié)議,以燈泡、跳蛋、小米手環(huán)為例
有了上面的理論基礎(chǔ),要開始實戰(zhàn)了。我手頭上只有藍(lán)牙燈泡和小米手環(huán),后來一個猥瑣的朋友借我個跳蛋希望幫忙分析…
YeeLight 2 代藍(lán)牙燈泡
首先這個燈泡我在分析前就敢肯定它是存在問題的,因為燈泡的操作邏輯不會過于復(fù)雜,無非是一開一關(guān)、變色等等,所以我就拿它來做個“Hello world”。
抓包燈泡的開關(guān)燈動作的value
2c2c2c3130302c2c2c2c2c2c2c2c2c2c2c2c(開)
2c2c2c302c2c2c2c2c2c2c2c2c2c2c2c2c2c(關(guān))
看到差異了么?
0x313030 = 100 0x30 = 0 從 4bytes 開始,就是該燈泡的亮度部分,100最亮,0沒有亮度,也就是關(guān)。
2. 抓包燈泡的換顏色動作
3235352c302c302c3130302c2c2c2c2c2c2c(紅色)
302c302c3235352c3130302c2c2c2c2c2c2c(藍(lán)色)
同上道理
0x3235352c302c30 = 255,0,0
0x302c302c323535 = 0,0,255
這就是RGB的顏色格式,很簡單直接告破:)
最后看下 Handle 0x0012,來源如圖
最后,簡單的看下Bluez協(xié)議棧自帶的gatttool工具的使用方法
通過抓包分析得知操控?zé)襞蓊伾膆andle是0x0012,我讀了下他的uuid為fff1,私有的。用char-write-cmd命令直接寫入我們分析好的協(xié)議,燈泡變色,然后再讀取之,數(shù)據(jù)確實成功寫入。
Demo(視頻進入烏云平臺可看)
小愛愛智能跳蛋
(這個真不是我的,某個小伙伴借給我研究的)
這個產(chǎn)品感覺邏輯也簡單,就是網(wǎng)絡(luò)遠(yuǎn)程發(fā)送震動指令到手機,手機在通過BLE鏈接設(shè)備進行你懂、我懂、他也懂的事情,羞~
這個跳蛋有三種模式:預(yù)定義節(jié)奏的震動、隨著音樂翩翩起舞的震動以及體位交互震動。
前兩個沒啥難度,基本抓到操作重放出來就OK了,最后這個模式比較卡哇伊,玩玩它咯。
與燈泡不同的是,進入體位模式后,Master會給Slave發(fā)送一個狀態(tài)開啟這個模式。所以你盲目的發(fā)送抓到的震動操作這個蛋是不震的,因為你要先讓她進入狀態(tài)。
給 Handle 0x0013 發(fā)送 0x0811060f01010232 后,它就進入狀態(tài)了。
然后 0x3e = 震動,0x7f = 生理暴擊(你狂按手機的時候就瘋狂的震動)
這個分析很簡單,因為都是些開關(guān)類的操作沒有太多實際的含義,所以無需解開數(shù)據(jù),直接重放就可以,我做了個發(fā)送SOS急救信號的demo。
Demo (視頻見烏云漏洞平臺)
小米手環(huán)
小米手環(huán)是明星產(chǎn)品,對它的分析也充滿了趣味與困難。因為從一開始我就遇到了一個認(rèn)證機制,如果藍(lán)牙鏈接后不寫入一段特殊格式的數(shù)據(jù),那你只能讀少量信息不能對手環(huán)進行操作。
我通過抓包分析GATT中的write操作,過程省略2萬字,最終定位了一個向 Handle 0x0019 進行的write操作,該Characteristic返回了個Notify,然后手環(huán)就可以隨意寫指令了(如私有協(xié)議中的震動、LED顏色變化、開啟實時步數(shù)監(jiān)控等)。
不過認(rèn)證怎么能叫PWN?
不過認(rèn)證怎么能叫PWN?
不過認(rèn)證怎么能叫PWN?
重要的事情說三遍。小米手環(huán)的認(rèn)證數(shù)據(jù)分析好了,結(jié)構(gòu)如下
這個簽名是最重要的部分,前面的數(shù)據(jù)都可以偽造,只要簽名過了,手環(huán)就會允許你后續(xù)的寫指令,才能做到真正的PWN。那這個簽名是咋算出來的?請看番外篇。
番外篇:小米手環(huán)認(rèn)證機制分析
劍走偏鋒,通過BlueZ得到了小米手環(huán)一個完整的私有協(xié)議UUID,然后去Github搜索,希望找到官方的代碼(其實這部分通過逆向Android app相信就能得到,不過說好的劍走偏鋒么)
然后呢?duang~
似乎是個第三方SDK,目前至少不用去逆向Android APP了開心,說實話這個我還真不擅長。通過這個SDK我找到了具體認(rèn)證流程的代碼:GitHub - miband-sdk-android。
從這段代碼中分析,最終寫入Characteristic的內(nèi)容,來自 userInfo.getBytes(device.getAddress()
public void setUserInfo(UserInfo userInfo)
{
BluetoothDevice device = this.io.getDevice();
this.io.writeCharacteristic(Profile.UUID_CHAR_USER_INFO, userInfo.getBytes(device.getAddress()), null);
}
userInfo.getBytes 的設(shè)計在這里,做了簡單注釋
public byte[] getBytes(String mBTAddress)
{
...
ByteBuffer bf = ByteBuffer.allocate(20);
bf.put((byte) (uid & 0xff)); //uid
bf.put((byte) (uid >> 8 & 0xff));
bf.put((byte) (uid >> 16 & 0xff));
bf.put((byte) (uid >> 24 & 0xff));
bf.put(this.gender); //性別
bf.put(this.age); //年齡
bf.put(this.height); //身高
bf.put(this.weight); //體重
bf.put(this.type); //類型
if(aliasBytes.length<=10)
{
bf.put(aliasBytes);
bf.put(new byte[10-aliasBytes.length]);
}else{
bf.put(aliasBytes,0,10);
}
byte[] crcSequence = new byte[19]; //取出用戶信息的前19個字節(jié)
for (int u = 0; u < crcSequence.length; u++)
crcSequence[u] = bf.array()[u];
byte crcb = (byte) ((getCRC8(crcSequence) ^ Integer.parseInt(mBTAddress.substring(mBTAddress.length()-2), 16)) & 0xff);
bf.put(crcb); //將簽名跟前面的用戶信息拼接
return bf.array(); //最終寫入Characteristic的內(nèi)容
}
這個數(shù)據(jù)與MAC地址最后兩位FC進行異或為16byte數(shù)據(jù),在轉(zhuǎn)為2byte的hex簽名結(jié)果。用戶信息與手機端無需一致,只要簽名正確即可。這里感謝 @瘦蛟舞 的幫忙,用java程序幫我做了個接口,這樣我就能根據(jù)MAC地址任意生成有效的認(rèn)證數(shù)據(jù)了。
完整代碼也不放出了,畢竟可以秒殺手環(huán)認(rèn)證:)
解決了認(rèn)證的難題,接下來就是壓軸大戲,如何對用戶以及產(chǎn)品口碑造成真正的影響。震動?改步數(shù)?LED跑馬燈?都不是,我選擇在茫茫人群中,給你寫入惡意的鬧鈴,名曰 午夜兇“鈴”。試想下,背著我那臺無線Hack設(shè)備,天天在早高峰蹭北京城鐵13號線,自動搜索身邊小米手環(huán),然后鏈接過認(rèn)證寫入鬧鈴,你們猜一個月后我能“感染”多少手環(huán)?我相信不用多久,小米手環(huán)論壇就會有用戶鬧翻天了…光說不練耍流氓,實現(xiàn)它。選擇設(shè)備后抓包,客戶端設(shè)置幾次鬧鈴,只要一次我就解開私有協(xié)議格式了:
一樣簡單,數(shù)據(jù)格式我畫出來。第一位說明當(dāng)前的操作是鬧鈴,第二位是鬧鈴的序號,第三位鬧鈴的開關(guān),第四位開始就是鬧鈴時間,倒數(shù)第二位是智能喚醒(就是在你淺睡眠的時候把你叫起,但是我偏不,就是要在你深度睡眠時喚醒你,木哈哈),最后一位就是鬧鈴的循環(huán)日期,0x7F就是每天。
寫好測試程序,搜索并鏈接手環(huán)通過那個“認(rèn)證”獲取操作權(quán)限,再用手環(huán)LED玩?zhèn)€跑馬燈,最后華麗麗的寫入鬧鈴釋放鏈接。結(jié)果手機客戶端連上去發(fā)現(xiàn)鬧!鈴!沒!開!啟!還是默認(rèn)的關(guān)閉狀態(tài),不放棄繼續(xù)分析,我是越挫越勇的……
通過后面的分析發(fā)現(xiàn),這個地方是小米手環(huán)客戶端(至少iOS客戶端)的BUG,手環(huán)開發(fā)組GG認(rèn)為手環(huán)的數(shù)據(jù)只有通過客戶端進行開啟修改,所以非客戶端寫入的數(shù)據(jù)不會自動同步!也就造成了惡意鬧鈴雖然寫入成功,但客戶端看不到,認(rèn)為鬧鈴沒有變化不去同步最新的狀態(tài),但這反讓攻擊變的更加隱蔽了,嘖嘖。
看演示吧,POC代碼不放,因為細(xì)心動手的人可以通過我的分析解決一切問題,也避免真的有人直接利用代碼對小米用戶進行攻擊(因測試成功后忘記取消之前設(shè)置的午夜兇“鈴”,所以我成了第一個受害者,大半夜太酸爽了)。
Demo:(視頻略大,沒法直接上傳,感興趣的童鞋進入烏云平臺看吧)
0x06 結(jié)語
內(nèi)容沒有涉及任何經(jīng)典/低功耗藍(lán)牙的協(xié)議加解密、簽名、配對兒認(rèn)證等安全機制,畢竟是初探,不搞那么復(fù)雜高大上變成學(xué)術(shù)文章。所以我先分享一些接地氣兒的產(chǎn)品和攻擊場景,希望能夠建立伙伴們對物聯(lián)網(wǎng)安全的興趣。
BLE在藍(lán)牙中都是很小的一部分,在物聯(lián)網(wǎng)汪洋大海中更是一葉扁舟,學(xué)海無涯希望路上有你。
PS:以上的內(nèi)容我個人認(rèn)為并不是漏洞,畢竟還得10米的攻擊范圍內(nèi),所以直接當(dāng)做技術(shù)分享吧。
為照顧用戶體驗,部分內(nèi)容已做精簡。欲了解更多技術(shù)細(xì)節(jié),可進入烏云平臺查看。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。