利用扫描节日门票时的延迟

信息安全 开发 竞争条件
2021-09-05 17:15:08

票务系统如何运作

票务系统——你在节日看到的系统——是这样工作的:当用户支付他们的票时,数据库中会添加一行名为 的列is_scanned,其默认值设置为 false。

一旦节日的警卫用他们的设备扫描条形码(包含 ID 和唯一哈希),就会向数据库发送请求以检查是否:

  1. 匹配 ID 和哈希的用户已付款,并且
  2. 如果 column 的值is_scanned仍设置为false.

如果两个条件都满足,它会将值设置is_scannedtrue以防止其他人复制票证/条形码进入。

漏洞问题

这里的问题是从扫描设备发送请求到值is_scanned从 切换false到 之间的时间true

考虑这种情况:Alice 有一张她支付的有效票,但随后她让 Eve 复制她的条形码并将假票上的可见名称从 Alice 更改为 Eve。所以现在我们有两张票。一种有效,一种欺诈,但都具有相同的条形码,唯一的区别是名称。

如果 Alice 和 Eve 的票在他们进入节日的同时被扫描怎么办?票务系统无法及时切换is_scannedtrue确保 Eve 无法使用与 Alice 相同的条形码进入。这导致两张票(有效的和欺诈的)对警卫都显示为“有效”。

可能的解决方案

当然,这种漏洞利用真的取决于很多运气,虽然理论上是可能的……但在实际情况下,这可能会失败。

但是,我们如何才能在理论上打败这种利用呢?

鉴别

我已经使用以下方法考虑了这个漏洞:扫描条形码时,我不仅显示票证是否有效(满足前面所述的条件),显示数据库中的名称。如果名称与票证上的名称不匹配,我们就知道票证以某种方式被操纵。此外,如果扫描设备上出现的名称与 ID 上的名称不匹配(每个人都需要显示以证明年龄),也不允许进入。

绕过此解决方案的唯一方法是身份欺诈,这当然超出了票务系统检查的责任。

延迟

理论上,解决这个问题的另一种方法是在向数据库/验证 API 发出的每个请求之间添加一个随机延迟时间。这样,没有人能够同时扫描他们的票……因为验证时间每次都会延迟随机的毫秒数。

我不喜欢这个,因为它:

  1. 让入口处的一切都变慢
  2. 如果延迟不够硬,是没有效果的。因为如果数据库从 更新到 需要 50 毫秒is_scannedfalse唯一true的解决方案是每次以至少 50 毫秒的间隔延迟它。

其他解决方案?

您认为解决此漏洞的其他解决方案是什么?

4个回答

您描述的漏洞是一种竞争条件

有几种方法可以处理它,但我会使用SELECT ... FOR UPDATESQL 查询,它会锁定选定的行以防止新的写入,直到当前事务被提交。

请务必检查您的 RDBMS 文档以检查如何正确实现它:

这里的另一个解决方案是绝对正确的,并且对于不太容易的大型系统是有意义的。

使用相对简单的数据,您可以选择非阻塞选项:

UPDATE [FESTIVAL_TICKET] 
  SET IS_SCANNED = TRUE
WHERE TICKET_ID = @ScannedKey 
  AND IS_SCANNED = FALSE

现在,这是一个原子操作。没有两个数据库用户可以发出这个让它更新行。返回“受影响的 1 行”的人(显然有一种方法可以在代码中找到它,不要为此解析文本)可以进去。其他人将得到零行受语句影响。如果您想对用户友好,您现在可以检查为什么找不到它,它是错误的 ID 还是已经被扫描。

但重要的细节是该语句是原子的。只有一个人会赢,无论他们有多接近零时差。因为你不再有一个读然后写。您可以在一个原子操作中进行读取和写入。

这样做的缺点似乎是一个可能会免费进入(使用复印票)。

对于可能是正确的小事件。
但是,如果您添加太多延迟,无论出于何种原因,您所冒的风险不仅仅是一个人进入。
如果他们的设备卡住或太慢,票扫描仪只会让一些额外的人通过......因为,他们中的大多数人可能有有效的票,对吧?

我在本日历年的一个重大活动中看到了这种情况,成千上万的音乐家粉丝参加了许多人都听说过的活动。
票务公司是一家主要的公司(也许是你工作的那个?),它位于一个专为购票而建的网站。
我的派对是未经扫描就通过的派对之一(是的......我有一张有效/合法的票)。
我不得不站在那里看着售票员几分钟,然后我才能弄清楚为什么会发生这种情况。

TL;博士; 当人们参与其中时
,不要为每一种可能的情况编写代码 拍摄两个或三个九 (99%-99.9%) 并收工。 当只涉及机器时保存昵称......那时你可以获得一堆9。

这个答案已经是一个又好又便宜的答案,但是,我会从软件工程和安全的角度添加我自己的答案。这可能有助于未来有关不太可能的漏洞利用的类似问题。

虽然理论上是可能的......在实际情况下,这可能会失败。

那么,与成本相比,潜在的损失是多少?我将证明在额外的安全性上花费精力和头痛是不值得的。

现在,已经提出并接受的解决方案是正确处理 SQL 事务的竞争条件,将责任/成本转移到数据库,是最好的、行业标准的和更便宜的解决方案。这可能是案件的结束,因为答案确实被接受了

正如已经指出的那样,在非常精确的时刻扫描两个服务员并触发竞争条件漏洞的事件可以估计为数百万甚至数十亿的可能性。为了让您对亿万富翁几率有一个定性的了解,请阅读这篇关于彩票的文章,并发现与扫描两张彩票相比,为第二名的 SuperEnalotto 玩可能是一个简单的游戏,而且奖励绝对是一致的。几率代表漏洞的可利用性,通常限定为谨慎的级别([非常]不太可能,[非常]可能)。我总是将不确定的安全相关事件与彩票进行比较,以提供更熟悉的比较。

为了进一步澄清,赔率受以下因素影响:

  • 两人能够同步他们在队列中的移动并同时将票交给警卫。这意味着两人经常交流并训练自己,更不用说他们的线路以可预测的速度移动的运气(几率!)
  • 守卫的肢体动作。并非所有警卫都以毫秒为单位扫描票证的确切时间,他们以不同的速度移动手臂。其中一张票可能会从警卫手中掉下来,一名警卫可能会反手拿着票。一名警卫可能会转身检查他们身后的线路是否被卡住。换句话说,有过多的熵来计划攻击
    • 无人检票机可能不受此因素影响
  • 计算机系统扫描票证所需的时间,以便两次扫描落在同一时间段并利用漏洞。

所以这里是软件工程的考虑。

门票有价格,所以值 X 美元。我估计 X 的大小可以在 50-100 的数量级。对于每个利用漏洞并以欺诈方式进入设施的人,将损失 X 美元。

实现更复杂的检查(如护照名字控制)是昂贵的在软件开发阶段所需的代码的条款和所花费的时间的人进入该设施。保安人员按小时计酬。实施Ben-Gurion 式的安全审查* 对诚实的人来说更加昂贵和痛苦。

现在,您想睡得更好,确保没有人可以利用您的系统。它要多少钱?在您支付巨额资金来保护您的系统后,您可能会发现运行“未受保护”系统的竞争对手正在承受 80 美元的损失,赔率高达数百万倍。很难量化这种概率。既然你有更多的机会赢得世界上最难的彩票,你最好赌一把,永远离开你的工作!

结论:在我们的职业中,获胜几率是我们最好的睡眠伴侣!

结论 2:竞争条件攻击很可能在自动化网络系统上被利用,攻击者显然可以将自己同步到微秒!!!这也可能使损害成倍增加,因此欢迎采取最好的安全措施!

结论 3:如果系统已经在运行,那么用公认的答案(设计、开发、测试、UAT、推出、PMO ......)对其进行修补的工作潜在的损害更昂贵。请在下方评论

*我举了一个例子,因为以色列的机场安检线传奇般的漫长而彻底