从一个简单的RFID安全事件说起

0x01 know it

学校新增了一个微信洗衣系统,用起来相当简单,首先,在系统的微信公众号上注册一个账户,账户是使用openid作为cookie,openid是微信生成的,只有在关注了公众号的时候才会产生。openid由几个因素决定,一个是公众号的appid,另一个是关注者的微信id。openid的作用就是让微信公众号的开发者唯一标识一个关注者。然后,将账户与任一一张卡绑定起来(我们学校有水卡和一卡通两张卡)。洗衣系统的充值使用微信支付,余额跟着微信走。

也就是说,整个结构就是线上存着你的各种信息以及余额,怎么去使用余额洗衣呢?就依靠你手上的卡,这张卡与系统进行了绑定,拿到卡,就拿到了系统的通行证。洗衣的时候拿着卡在洗衣机终端上刷一下,即可验证身份,使用余额。

0x02 key point

那么卡与系统是怎么绑定的呢?在系统中,每个账户都可以绑定一个物理卡ID,如图所示:
当然,普通人肯定不知道一张卡的物理卡ID是多少,于是,洗衣机终端就承担了这个功能。当一张未绑定的卡去刷洗衣机终端时,终端显示如下

然后只需要在系统中绑定这个物理卡号即可。绑定后正常使用的照片如下图

0x03 analysis it

我们重点分析一下这个鉴权过程,系统使用物理卡ID来唯一标识用户,而我们使用的卡都是M1卡,M1卡中存储着UID和block,block的访问是需要密码的,而洗衣系统和一卡通是不同的公司开发的,所以肯定不是使用block中存储的数据来唯一标识用户,而每张M1卡的UID都是唯一的,但是可以通过可写入的白卡写入相同的UID。关于RFID和M1卡的相关知识以及安全漏洞请自行Google。所以这个物理卡ID应该就是M1卡的UID。遂试验之,果然,连最简单的映射都没有做


我们看上面洗衣终端正常工作的照片,发现终端居然直接将卡ID赤裸裸展示出来,这不是直接把密码输出了嘛!

0x04 hack it

分析到这里,用别人的余额洗衣就非常容易了。只需要在洗衣终端上读到一卡通卡号,把它作为UID写入白卡即可。

0x05 躺枪的其它系统

到这里就结束了吗?

我曾经丢失过自己的一卡通,补办后发现刚开始的一段时间无法打开门禁。这说明什么问题呢?补办的一卡通和原来的一卡通唯一的区别就在UID上。也就是说,补办后,在中央数据库中,我的UID有更新,而门禁需要一段时间同步更新,那么,门禁也是靠UID来识别身份的。

只有门禁吗?

一个学校的系统各种各样,门禁,闸机,多媒体讲台,一个同学或者老师的权限都由统一认证系统来确定,那么,我们从程序员和系统设计者的角度来想,这个统一认证系统肯定留了API,来供其他系统调用,鉴权。这样的设计容易扩展,更容易与其他系统配合,它的市场竞争力就会强。果然,经过试验,图书馆的闸机也是用UID来验证,而且还会显示出卡对应的名字和院系。

黑客永远抵抗不了root权限的诱惑,如果我们能拿到这个API,那么。。。。嘿嘿嘿。。。。

于是就有了下面这张照片,成功伪造了一张校长的卡

0x06 p.s.

光拿到UID不能伪造出可以消费的一卡通,一卡通的消费是实时服务器校验的,而且在block中,对余额以及身份信息做了摘要,如果不知道摘要算法,无法伪造一张合法的卡

M1卡早就被曝出加密算法具有重大缺陷,具体可以Google,读卡器使用的是ACR122U。RFID安全也是安全的一个维度,国内有RadioWar团队研究比较深入。

0x07 想到的

安全永远不止那么简单,一个小小的设计缺陷–显示了卡的UID,导致了所有基于UID的鉴权全部崩溃。有的时候,一个小口子,就能瞬间将精心构建的安全防护体系毁于一旦。