小区门禁卡需要升级了,我不得不把卡片信息从手机里重新写到物业发的门禁卡中,正好记录关于MifareOne卡片的相关资料,之前玩Arduino时折腾过,但是现在都忘记了

卡片的芯片M1,是恩智浦公司(Phillips旗下子公司)的一种广泛应用的芯片,各种小区门禁卡、会员卡、包括学校食堂的饭卡水卡有很多都是M1卡片。(虽然M1本身也有很多安全漏洞)

工作原理

读卡器会不断发出携带有信息和一定能量的射频信号,当M1卡片靠近时,卡内的线圈会从射频信号中获取能量,给卡内的电容充电,电压达到一定阈值以后,卡内的芯片就会开始工作,给读卡器返回响应的信息,进行数据传输。当有多张卡位于读卡器射频范围内时,读卡器可以选中其中一张卡进行通信。

技术参数

  • EEPROM:1K字节
  • 工作频率:13.65 mhz
  • 读写速率:106 kbps

扇区结构

M1卡内部有一个1Kb字节的EEPROM,分成16个扇区,每个扇区再分为4个块,每个块拥有16个字节的存储空间。

可以参考我制作的结构图片:(这是我所在小区的门禁卡的Dump数据)

M1卡片

其中第0扇区的0块一般用于存放厂商代码(序列号),已经固化,无法修改(下图中黄色标识),除了第一扇区可用空间为2x16=32字节以外,其它扇区都是3x16=48字节。未被使用字节使用白色表示,可以看到只有扇区1里面存储了部分数据,其它扇区都是未使用状态。(已被使用的字节使用深绿色表示)

每个扇区内块0-3(Block)是数据块,顾名思义就是用来存储数据的地方,而最后的块3(Block)则是控制块,就是用来控制数据块的读写权限的。

控制块分3个部分:密码A读写控制位密码B

  1. 密码A永远不可读取,但可以修改
  2. 密码B则可读可写
  3. 读写控制位会对0-3块的每个块单独设置读写权限
  4. 如果两个密码都忘记了,整个扇区就相当于锁死了,无法修改(但仍然有后门操作可以找回)
  5. 每个扇区都有自己独立的密码A和密码B,一个扇区的密码丢失不会对其它扇区造成影响。

每个块的读写权限由3个控制位组成

读写控制 控制位1 控制位2 控制位3
块0 C01 C02 C03
块1 C11 C12 C13
块2 C21 C22 C23
块3 C31 C32 C33

而每个块的3个控制位分别存储在读写控制字节(上图中紫色的部分)中不同的位置。带有^标记表示需要取反存储

控制字节 位7 位6 位5 位4 位3 位2 位1 位0
字节6 ^C32 ^C22 ^C12 ^C02 ^C31 ^C21 ^C11 ^C01
字节7 C31 C21 C11 C01 ^C33 ^C23 ^C13 ^C03
字节8 C33 C23 C13 C03 C32 C22 C12 C02
字节9 - - - - - - - -

有意思的是字节9不参与任何读写控制,它的值似乎总是0x69(1101001),可能是行业惯例。

控制位由3个bit组成,不同的控制位组合在一起会有不同的权限策略,下方列出了数据块(0-2块)的读写权限表和控制块(3块)的读写权限表。

数据块的读写权限表

AB表示密码A或者密码B都可以执行这个操作,B代表只有密码B才能执行这个操作,-代表无论密码A还是B都无法执行这个操作。M1芯片除了支持直接读写以外,还支持增加操作和减少操作。

控制位1 控制位2 控制位3 读操作 写操作 加操作 减操作
0 0 0 AB AB AB AB
0 1 0 AB - - -
1 0 0 AB B - -
1 1 0 AB B B AB
0 0 1 AB - - AB
0 1 1 B B - -
1 0 1 B - - -
1 1 1 - - - -

例如:100表示:

  • 读操作:AB密码均可
  • 写操作:需要B密码
  • 加操作:AB密码均无法执行
  • 减操作:AB密码均无法执行

控制块的读写权限表

控制块有自己独立的一套权限表,并不和数据块一致

AB表示密码A或者密码B都可以执行这个操作,B代表只有密码B才能执行这个操作,-代表无论密码A还是B都无法执行这个操作。

控制位1 控制位2 控制位3 读密码A 写密码A 读"读写控制"位 写"读写控制"位 读密码B 写密码B
0 0 0 - AB AB - AB AB
0 1 0 - - AB - AB -
1 0 0 - B AB - - B
1 1 0 - - AB - - -
0 0 1 - AB AB AB AB AB
0 1 1 - B AB B - B
1 0 1 - - AB B - -
1 1 1 - - AB - - -

例如:101表示:

  • 读密码A:AB密码无法读取
  • 写密码A:AB密码无法写入
  • 读"读写控制"位:AB密码均可
  • 写"读写控制"位:需要B密码
  • 读密码B:AB密码无法读取
  • 写密码B:AB密码无法读取

关于UID/FUID/CUID卡

普通的MifareOne卡的0扇区0块在出场之前就已经被固化,无法修改,一般是存储厂商编号和卡的序列号,有些时候读卡器不仅会验证卡内的数据,也会验证卡的序列号,如果使用了克隆卡,就会认证失败。

接着UID卡就出现了,UID卡和普通IC卡最大的区别就是0扇区0块可以擦写,由此可以伪造任何一张卡的卡号,但是许多读卡器在读卡时会对卡片发出特殊指令,如果卡片响应了这个特殊指令,则代表这是一张UID卡,读卡器就会认证失败,如果没有响应,读卡器就会以为是一张普通IC卡。

再后来出现了CUID卡,和UID卡的区别在于不会响应读卡器的特殊指令,看起来就和普通IC卡一样。

FUID卡比较特殊一点,它的0扇区只能写入一次,写入之后就和普通IC卡一样了,也不会响应后门指令

还有另外一种比较高级的UFUID卡,用特殊指令封卡之后就变成了一张普通IC卡,再用特殊指令解封之后就变成了一张UID,可以灵活切换

浅谈防御攻击

因为M1卡片有安全漏洞,导致能容易被破解,即使是普通的Arc122u或者PN532都能在某些情况下轻松完成破解工作。

一般的攻击方式是获取整张卡的Dump数据以后分析数据格式,然后修改金额达到破解的目的,或者给卡片做一个Dump(可以理解为快照),刷卡扣钱以后再把快照恢复,这样就可以无限刷卡了,这就是典型的重放攻击。

防御方式有很多种,最最简单的就是使用复杂的加密算法加密卡内的数据,使用冗余位进行校验,验证是否为UID卡和卡号,最后是给所有扇区修改默认密码,无论是否存储了数据(M1卡有典型的知一密解全密的漏洞),不过这样仍然不能达到绝对的安全,因为如果使用专业的Proxmark3等设备,甚至能利用监听模式破解全加密的卡片。

最安全也是最保险的方式是让读卡器联网验证,确保数据的安全性,卡片本身只保存一个卡号,或者再激进一点,将校验数据加密后保存到卡片里,每次读卡时不仅要校验卡号,还要校验卡内的校验数据,来确保卡片本身没有修改过。

在金融领域,早已不再使用安全性欠佳的M1卡片,而是使用磁条卡等接触式安全性更高的卡片,卡片内部的芯片也不再是简单的存储芯片,而是复杂的CPU卡,可以使用更复杂的加密算法来确保交易的安全。