票务系统如何运作
票务系统——你在节日看到的系统——是这样工作的:当用户支付他们的票时,数据库中会添加一行名为 的列is_scanned
,其默认值设置为 false。
一旦节日的警卫用他们的设备扫描条形码(包含 ID 和唯一哈希),就会向数据库发送请求以检查是否:
- 匹配 ID 和哈希的用户已付款,并且
- 如果 column 的值
is_scanned
仍设置为false
.
如果两个条件都满足,它会将值设置is_scanned
为true
,以防止其他人复制票证/条形码进入。
漏洞问题
这里的问题是从扫描设备发送请求到值is_scanned
从 切换false
到 之间的时间true
。
考虑这种情况:Alice 有一张她支付的有效票,但随后她让 Eve 复制她的条形码并将假票上的可见名称从 Alice 更改为 Eve。所以现在我们有两张票。一种有效,一种欺诈,但都具有相同的条形码,唯一的区别是名称。
如果 Alice 和 Eve 的票在他们进入节日的同时被扫描怎么办?票务系统无法及时切换is_scanned
以true
确保 Eve 无法使用与 Alice 相同的条形码进入。这导致两张票(有效的和欺诈的)对警卫都显示为“有效”。
可能的解决方案
当然,这种漏洞利用真的取决于很多运气,虽然理论上是可能的……但在实际情况下,这可能会失败。
但是,我们如何才能在理论上打败这种利用呢?
鉴别
我已经使用以下方法考虑了这个漏洞:扫描条形码时,我不仅显示票证是否有效(满足前面所述的条件),还显示数据库中的名称。如果名称与票证上的名称不匹配,我们就知道票证以某种方式被操纵。此外,如果扫描设备上出现的名称与 ID 上的名称不匹配(每个人都需要显示以证明年龄),也不允许进入。
绕过此解决方案的唯一方法是身份欺诈,这当然超出了票务系统检查的责任。
延迟
理论上,解决这个问题的另一种方法是在向数据库/验证 API 发出的每个请求之间添加一个随机延迟时间。这样,没有人能够同时扫描他们的票……因为验证时间每次都会延迟随机的毫秒数。
我不喜欢这个,因为它:
- 让入口处的一切都变慢
- 如果延迟不够硬,是没有效果的。因为如果数据库从 更新到 需要 50 毫秒
is_scanned
,false
唯一true
的解决方案是每次以至少 50 毫秒的间隔延迟它。
其他解决方案?
您认为解决此漏洞的其他解决方案是什么?