NFC 门禁卡防复制实战:升级 DESFire 加密卡

NFC 门禁卡 被手机复制,是办公区最常见的物理入侵入口:一张 MIFARE Classic 卡在电梯里被读一次,密钥就能在几分钟内被穷举出来,随后整栋楼的权限被复制进手机。本文从卡型识别、密钥强度验证、读头与控制器通信加固、后台策略四个层面给出可执行的加固路径,并说明 UID 卡、CUID 卡与 DESFire EV2 在防复制能力上的真实差距。

适用场景

  • 办公区、机房、仓库使用 IC 卡门禁,员工反馈手机一贴就能复制门禁卡
  • 门禁系统仍是十年前的韦根读头,卡号在总线上明文传输
  • 访客卡、保洁卡的权限与正式员工相同,缺少时段与区域限制
  • 需要在不动整体控制器的情况下先做风险收敛
  • 安全审计要求提供门禁卡防复制能力说明与整改记录

前置条件

  • Linux 主机与 NFC 读卡器(ACR122U、PN532),已装 libnfc、libfreefare、pcsc-tools
  • 门禁控制器具备管理后台,可配置卡号、时段、区域与反潜回
  • 书面授权:仅对自有门禁系统与自有卡片做测试,不读取第三方卡片或场所
  • 清楚现有系统用的是物理卡号还是扇区数据,避免改造后卡号对不上

原理说明

市面门禁卡大致分三类。UID 卡(MIFARE Classic S50)的 UID 出厂固化,防冲突依赖它,克隆成本极低;CUID 卡允许改写 UID,用来对付只校验物理卡号的旧系统,但本质仍是可复制的 Classic 卡;CPU 卡(DESFire EV2/EV3、国密 SM1/SM4 卡)内置安全芯片,支持双向认证与安全报文,密钥不出卡,是目前唯一能真正防复制的方案。

MIFARE Classic 使用的 Crypto1 流密码已被公开攻破,嵌套攻击可以在拿到一张合法卡后快速恢复全部扇区密钥,耗时通常以分钟计。这意味着只要门禁仍在使用 Classic 卡,卡片复制就无法通过软件层阻止,任何「防复制」宣传都只是提高门槛,而不是消除风险。

读头与控制器之间的通信同样关键。遗留系统多用 韦根协议,26 位或 34 位明文传输卡号,总线可被搭线窃听并重放;OSDP 协议支持 Secure Channel,用 SCBK 密钥做消息加密与认证码校验,能在不更换控制器的前提下把总线加密,是性价比最高的一步改造。

后台策略决定了复制卡能走多远。卡号与人员一一绑定、时段与区域限制、反潜回、访客卡自动过期,这四项不依赖硬件升级,却能把一张复制卡的可用窗口从「随时全楼」压缩到「特定时段特定门」。

操作步骤

第一步:识别手中卡片的真实类型

pcsc_scan            # 观察 ATR,确认读卡器与卡片通信正常
nfc-list             # 列出 UID 与通信参数
nfc-list -v | grep -E "ATQA|SAK|UID"

SAK 为 0x08 且 ATQA 为 0x0004 通常是 MIFARE Classic 1K;SAK 为 0x20 多为 DESFire 系列。类型判断错,后面的加固方向会全错:Classic 只能替换,DESFire 才有加密空间。

第二步:在授权范围内验证密钥强度

# 仅对自有卡片执行,用于验证是否仍在使用默认密钥
mfoc -O card_dump.mfd

# 单密钥探测,判断是否出厂默认
nfc-brute 0:A -k FFFFFFFFFFFF 2>/dev/null

# DESFire 卡可先看应用与密钥数量
mifare-desfire-info

若默认密钥 FFFFFFFFFFFF 就能读出全部扇区,说明系统从未做过密钥个性化,属于必须整改项。验证结论只需记录「默认密钥是否可用」与耗时,不要把密钥内容与卡片数据写进工单附件或群聊。

第三步:读头与控制器切换到 OSDP 安全通道

# 读头侧写入 SCBK 并开启安全通道
osdpctl --device /dev/ttyUSB0 --baud 9600 --set-secure-channel \
        --scbk 00112233445566778899AABBCCDDEEFF

# 轮询确认通信正常
osdpctl --device /dev/ttyUSB0 --poll --verbose

# 控制器侧确认日志已走加密通道
grep -i "osdp\|secure" /var/log/access-control.log | tail

SCBK 必须是 16 字节随机密钥,按门禁分区独立设置,不要全网共用一把。改造期间读头与控制器需同时支持 OSDP;若控制器只支持韦根,优先更换为「韦根+OSDP 双模」读头,先跑通 OSDP 再关闭韦根口,避免一次性改造导致门禁全瘫。

第四步:DESFire 卡初始化与三层密钥体系

# 查看卡信息与已有应用
mifare-desfire-info
mifare-desfire-list-apps

# 新建应用并设置 AES 主密钥(示例密钥必须替换)
mifare-desfire-create-aid --aid 0x000001
mifare-desfire-format --aid 0x000001 --key-no 0 \
  --key 000102030405060708090A0B0C0D0E0F

# 认证测试
mifare-desfire-auth --aid 0x000001 --key-no 0 \
  --key 000102030405060708090A0B0C0D0E0F

密钥体系建议分三层:主密钥用于发卡,应用密钥控制读写权限,卡片唯一密钥按卡号派生。三层分离后,单张卡丢失只需吊销该卡,不必全站换钥。密钥应集中存放在具备审计的密钥管理系统或加密文件中,禁止随读头配置备份一起流转。

第五步:后台策略与刷卡异常监控

# 同一卡号短时间多次被拒:疑似复制卡试探
awk '$4=="DENY"{c[$1]++} END{for(k in c) if(c[k]>10) print k, c[k]}' \
  /var/log/access/2026-10.log

# 深夜时段刷卡记录排查
grep -E " (0[0-5]|23):[0-9]{2}:" /var/log/access/2026-10.log | awk '{print $1}' \
  | sort | uniq -c | sort -rn | head

策略层至少开启四项:卡号与人员一一绑定,禁止共用卡;时段与区域限制;反潜回,未刷出不能再次刷入;访客卡自动过期。日志侧关注「同卡异地同时刷」「深夜高频失败」「单卡短时多次尝试」,这三类特征分别对应复制卡、试探与权限摸索。

配置验证

# 1. 卡片是否仍可被无密钥读取
mfoc -O verify.mfd 2>&1 | tail -3

# 2. DESFire 认证是否必须正确密钥
mifare-desfire-auth --aid 0x000001 --key-no 0 \
  --key 00000000000000000000000000000000

# 3. 总线上是否还能看到明文卡号
osdpctl --device /dev/ttyUSB0 --poll --verbose | grep -i "card"

# 4. 反潜回策略是否已产生记录
grep -c "ANTI_PASSBACK" /var/log/access/2026-10.log

验收标准是三条负面用例:复制出的 UID 卡在 DESFire 读头上无法通过认证;OSDP 抓包看不到明文卡号;错误密钥认证返回失败而非静默通过。三条都成立,才算完成加固。

常见问题

Q1:把 UID 卡换成 CUID 卡就算加固了吗?

不算。CUID 只是把 UID 改成可写,用来欺骗那些仅校验物理卡号的旧系统,本质仍是可复制的 Classic 卡,扇区密钥依旧能被穷举。真正的分界线是卡内是否有安全芯片、是否支持双向认证,也就是从 Classic 迁移到 DESFire EV2 及以上。

Q2:门禁卡换成 DESFire 后,手机 NFC 还能模拟吗?

手机厂商的 NFC 模拟主要支持固定 UID 类卡片,DESFire 需要按应用做密钥认证,模拟后无法完成认证流程,刷卡会失败。这也是判断升级是否成功的直观依据:升级后员工再用手机贴卡录入,应提示不支持该卡类型。

Q3:预算有限,能不能只做一部分改造?

可以按「先总线、后策略、再换卡」的顺序分步走。第一步把读头换成双模并启用 OSDP 加密,成本最低、立刻消除总线窃听;第二步补齐时段、区域、反潜回与日志告警,不花钱就能削弱复制卡可用性;第三步按区域分批迁移到 DESFire,优先覆盖机房与财务室等高价值门禁。

总结

NFC 门禁卡 的防复制本质是密钥强度问题,不是配置技巧问题。Classic 卡无论怎么设置都不能真正防克隆,能做的只有提高门槛、缩短暴露窗口。可执行顺序是:识别卡型 → 验证是否仍用默认密钥 → 总线切 OSDP 加密 → 卡片迁移 DESFire 并建立三层密钥 → 后台补齐时段、反潜回与异常刷卡告警。门禁是物理边界的第一道门,这道门的强度取决于最弱的那张卡,而不是最新采购的那台读头。