How a Race Condition Vulnerability Could Cast Multiple Votes

How a Race Condition Vulnerability Could Cast Multiple Votes

This blog was originally posted on Medium by Dane Sherrets.
这篇博客最初由Dane Sherrets发表在Medium上。

Race condition vulnerabilities make up less than 0.3% of reports on the HackerOne platform. However, researchers have recently been particularly interested in experimenting with race condition vulnerabilities as a result of James Kettle’s “State Machine” research that he presented at BlackHat in 2023. 
在HackerOne平台上,竞争条件漏洞占报告的比例不到0.3%。然而,由于 James Kettle 于 2023 年在 BlackHat 上发表的“状态机”研究,研究人员最近对竞争条件漏洞的实验特别感兴趣。

This blog tells the story of how I applied this research to the World ID Software Development Kit (SDK) and identified a race condition that would have enabled an attacker to bypass the preset verification limit on a cloud-based implementation. The exploitation of this vulnerability would impact a project that relied on World ID for restricting the number of actions a user could take (for example, if a project was using the SDK to ensure a user should only be able to cast one vote, an attacker could exploit the vulnerability to cast 20 votes). 
这篇博客讲述了我如何将这项研究应用于 World ID 软件开发工具包 (SDK) 并确定一种竞争条件,该条件使攻击者能够绕过基于云的实现上的预设验证限制。利用此漏洞将影响依赖 World ID 来限制用户可以执行的操作数量的项目(例如,如果项目使用 SDK 来确保用户只能投一票,则攻击者可以利用此漏洞投 20 票)。

What Is A Race Condition?
什么是争用条件?

A race condition occurs when the behavior of software is contingent upon the sequence or timing of uncontrollable events. This flaw arises in environments where multiple processes or threads access and modify shared resources concurrently without appropriate synchronization, leading to unpredictable outcomes.
当软件的行为取决于不可控事件的顺序或时间时,就会发生争用条件。在多个进程或线程同时访问和修改共享资源而没有适当同步的情况下,会出现此缺陷,从而导致不可预知的结果。

The introduction of race conditions is often attributed to insufficient design consideration regarding concurrency (e.g. – lack of adequate safeguards when processing requests concurrently) and flawed implementation of access controls to shared data. A common scenario involves two threads that both read and write to a shared variable without ensuring the operations are atomic. Without proper locking mechanisms or atomic operations, the final state of the shared resource becomes dependent on the order of execution, leading to inconsistencies and potentially compromising the integrity and security of the system. 
引入争用条件通常归因于对并发性的设计考虑不足(例如,在并发处理请求时缺乏足够的保护措施)和对共享数据的访问控制实现存在缺陷。一个常见的方案涉及两个线程,它们同时读取和写入共享变量,而不确保操作是原子的。如果没有适当的锁定机制或原子操作,共享资源的最终状态将取决于执行顺序,从而导致不一致,并可能损害系统的完整性和安全性。

These vulnerabilities can be exploited to cause unauthorized actions, data corruption, and even system crashes. In worst-case scenarios, attackers could leverage race conditions to bypass security mechanisms, gain unauthorized access to sensitive data, or execute arbitrary code, posing significant risks to organizational security and data integrity. Addressing race conditions requires a meticulous approach to design and testing, emphasizing concurrency control and ensuring that critical operations on shared resources are performed atomically.
这些漏洞可被利用来导致未经授权的操作、数据损坏,甚至系统崩溃。在最坏的情况下,攻击者可能会利用竞争条件绕过安全机制,未经授权访问敏感数据或执行任意代码,从而对组织安全和数据完整性构成重大风险。解决竞争条件需要采用细致的设计和测试方法,强调并发控制,并确保以原子方式执行共享资源上的关键操作。

Background on Worldcoin 世通元 的背景

I have been interested in Worldcoin ever since it hit the Blockchain scene back in 2019. Worldcoin is a cryptocurrency project that aims to build a foundation for a) biometrically verifying unique humans and b) a distribution mechanism for Universal Basic Income (UBI). Most people probably just know about it as the company that builds an orb that will give you cryptocurrency if you stare into it. 
自从 Worldcoin 在 2019 年进入区块链领域以来,我一直对它感兴趣。Worldcoin是一个加密货币项目,旨在为a)生物识别验证独特的人类和b)全民基本收入(UBI)的分配机制奠定基础。大多数人可能只知道它是一家制造球体的公司,如果你盯着它看,它会给你加密货币。

The idea of humans scanning their eyeballs and giving biometric data to a centralized entity is certainly controversial, however, Worldcoin’s approach delivers Sybil resistance, one of the most difficult problems the internet faces today (A Sybil attack is a security threat where an attacker creates multiple fake identities to gain a disproportionately large influence on a network.)  As we approach a world where anyone can create hundreds of AI-powered bots, Sybil resistance will become a critical problem to solve (it is worth noting that Sam Altman is one of the founders of Worldcoin) and Worldcoin is one of the only projects that is working on this issue in a meaningful way.
人类扫描他们的眼球并将生物识别数据提供给中心化实体的想法当然是有争议的,然而,Worldcoin的方法提供了女巫抵抗力,这是当今互联网面临的最困难的问题之一(女巫攻击是一种安全威胁,攻击者创建多个虚假身份以对网络产生不成比例的巨大影响。随着我们接近一个任何人都可以创建数百个人工智能机器人的世界,女巫抵抗将成为一个需要解决的关键问题(值得注意的是,山姆·奥特曼是Worldcoin的创始人之一),而Worldcoin是唯一以有意义的方式解决这个问题的项目之一。

Before I started looking into Worldcoin, I had assumed that it was purely a cryptocurrency distribution mechanism but, as I dug deeper, I found that they were building a Software Development Kit (SDK) around biometric authentication. This means that other apps could use the Worldcoin SDK to confirm that one user = one human being. That might not sound like a big deal, but it is a game changer for apps with use cases including voting, airdropping, and bot protection. For example, if I wanted to make an app that made it so a unique human could only vote once on a given issue, then I could make all of my users authenticate via the Worldcoin SDK, which would essentially act as an Identity Provider (IDP) and enforcer for the limitation I preconfigured (i.e vote once).
在我开始研究Worldcoin之前,我以为它纯粹是一种加密货币分发机制,但随着我深入挖掘,我发现他们正在围绕生物识别身份验证构建软件开发工具包(SDK)。这意味着其他应用程序可以使用Worldcoin SDK来确认一个用户=一个人。这听起来可能没什么大不了的,但对于具有投票、空投和机器人保护等用例的应用程序来说,它改变了游戏规则。例如,如果我想制作一个应用程序,让一个独特的人只能对给定的问题进行一次投票,那么我可以让我的所有用户通过Worldcoin SDK进行身份验证,它基本上将充当身份提供者(IDP)和我预先配置的限制的执行者(即投票一次)。

As a cryptocurrency, Worldcoin has an SDK implementation that works for (EVM-compatible) blockchains and a cloud-based version that does not require touching any blockchain. Both versions use some really cool Merkle-tree-based cryptography to create a tamper-proof log of transactions that is worth reading up on if you are not familiar
作为一种加密货币,Worldcoin有一个SDK实现,适用于(EVM兼容)区块链,以及一个不需要接触任何区块链的基于云的版本。这两个版本都使用一些非常酷的基于默克尔树的加密技术来创建防篡改的交易日志,如果您不熟悉,值得一读。

Testing on Worldcoin 在Worldcoin上进行测试

To help developers test the Worldcoin workflow, Worldcoin offers a simulator to test transactions and verifications (link here). If I create a dev account, I can create “actions” (e.g. “vote on this proposal”)  and set a maximum number of “verifications” (e.g. “number of times a human can vote on a proposal).  To look under the hood of how this all works, I did most of my testing on this simulator and ran the requests through Burp Suite. 
为了帮助开发者测试世通元 工作流程,世通元 提供了一个模拟器来测试交易和验证(链接在这里)。如果我创建一个开发帐户,我可以创建“操作”(例如“对此提案进行投票”)并设置最大数量的“验证”(例如“一个人可以对提案进行投票的次数”)。 为了了解这一切是如何工作的,我在这个模拟器上进行了大部分测试,并通过 Burp Suite 运行了请求。

How a Race Condition Vulnerability Could Cast Multiple Votes

While I could change things like the “credential type” (either “orb” or “device”) or “chain”, the requests were all very similar. I spent many hours trying to break the flow and signatures but was unsuccessful in achieving anything interesting, so I gave up for a few weeks. 
虽然我可以更改“凭据类型”(“orb”或“device”)或“链”之类的内容,但请求都非常相似。我花了很多时间试图打破流程和签名,但没有成功实现任何有趣的东西,所以我放弃了几个星期。

Flash forward to DEF CON 31, and James Kettle presented his research on Smashing The State Machine. As soon as I read his blog, I realized it was something I could try on Worldcoin. I opened up the Burp Repeater tab, made sure I downloaded the Burp update that had the “send in parallel” feature, and gave it a shot on the Worldcoin flow I described earlier. 
快进到 DEF CON 31,James Kettle 介绍了他对 Smashing The State Machine 的研究。当我读到他的博客时,我意识到这是我可以在Worldcoin上尝试的东西。我打开了“打嗝中继器”选项卡,确保我下载了具有“并行发送”功能的打嗝更新,并在我之前描述的 Worldcoin 流程上试了一下。


Specifically, the steps were:
具体来说,这些步骤是:

  1. Capture the request and send it to the repeater
    捕获请求并将其发送到中继器
  2. Make a new “tab” for the request
    为请求创建一个新的“选项卡”
  3. Duplicate the original request ~20 times in the new “tab”
    在新的“选项卡”中复制原始请求 ~20 次
  4. Send them all “in parallel” 
    将它们全部“并行”发送
How a Race Condition Vulnerability Could Cast Multiple Votes

When I looked at the requests it worked! Where I should have only seen two verifications of “unique humans,” I saw 20! 
当我查看请求时,它起作用了!我应该只看到两个“独特人类”的验证,我看到了 20 个!

How a Race Condition Vulnerability Could Cast Multiple Votes

I only tested this on the “cloud” version of the implementation as I was pretty sure it wouldn’t work on the “blockchain” version since that would require a transaction to be finalized. 
我只在实现的“云”版本上测试了这一点,因为我非常确定它不适用于“区块链”版本,因为这需要完成交易。

Since the Worldcoin project is open source, I reviewed the code and saw a red flag in the  `canVerifyForAction` util:
由于Worldcoin项目是开源的,我查看了代码,并在“canVerifyForAction”实用程序中看到了一个危险信号:

export const canVerifyForAction = (
export const canVerifyForAction = (

 nullifiers: 无效:
   | Array<{ |数组<{
       nullifier_hash: string; nullifier_hash:字符串;
     }>
   | undefined, |定义
 max_verifications_per_person: number
max_verifications_per_person:数字

): boolean => { ): 布尔值 => {
 if (!nullifiers?.length) {
如果 (!nullifiers?.长度) {

   // Person has not verified before, can always verify for the first time
以前没有验证过的人,可以随时第一次验证

   return true; 返回 true;
 } else if (max_verifications_per_person <= 0) {
} else if (max_verifications_per_person <= 0) {

   // `0` or `-1` means unlimited verifications
“0”或“-1”表示无限制的验证

   return true; 返回 true;
 }

 // Else, can only verify if the max number of verifications has not been met
否则,只有在未满足最大验证次数时才能进行验证

 return (nullifiers?.length ?? 0) < max_verifications_per_person;
返回(nullifiers?.长度??0) < max_verifications_per_person;

}

Specifically, the way `nullifier` is referenced in other parts of the codebase here allowed for a race condition as it just added to an array without a “lock,” which means parallel requests would all be treated equally. 
具体来说,此处代码库其他部分引用“nullifier”的方式允许竞争条件,因为它只是添加到没有“锁”的数组中,这意味着所有并行请求都将被平等对待。

The Mitigation 缓解措施

The Worldcoin team addressed this by using the database to create an artificial lock so that even if two requests come in at the same time, they will be treated properly. In this pull request, you can see they now have new database tables for `nullifiers`, and they have updated the `canVerifyForAction` code to reference the `nullifier` number of uses instead of just the length:
世通元 团队通过使用数据库创建人工锁来解决这个问题,这样即使同时收到两个请求,它们也会得到妥善处理。在此拉取请求中,您可以看到他们现在为“nullifiers”提供了新的数据库表,并且他们更新了“canVerifyForAction”代码以引用“nullifier”的使用次数,而不仅仅是长度:

export const canVerifyForAction = (
export const canVerifyForAction = (

  nullifier: 无效器:
    | {
        uses: number; 用途:数量;
        nullifier_hash: string; nullifier_hash:字符串;
      }
    | undefined, |定义
  max_verifications_per_person: number
max_verifications_per_person:数字

): boolean => { ): 布尔值 => {
  if (!nullifier) { 如果 (!nullifier) {
    // Person has not verified before, can always verify for the first time
以前没有验证过的人,可以随时第一次验证

    return true; 返回 true;
  } else if (max_verifications_per_person <= 0) {
} else if (max_verifications_per_person <= 0) {

@@ -146,7 +147,7 @@ export const canVerifyForAction = (
@@ -146.7 +147.7 @@ 导出 const canVerifyForAction = (

  }

  // Else, can only verify if the max number of verifications has not been met
否则,只有在未满足最大验证次数时才能进行验证

  return nullifier.uses < max_verifications_per_person;
};

When people think of a “blockchain” or “Web3” project, they often assume that any vulnerabilities will be limited to the network or smart contract — this is often not the case. Today, Web3 still relies heavily on Web2, and this opens up a wide range of creative attack vectors. If you are a Javascript expert and you haven’t tried bug hunting on Web3 projects, then you are leaving money on the table! 
当人们想到“区块链”或“Web3”项目时,他们通常认为任何漏洞都将仅限于网络或智能合约——事实往往并非如此。今天,Web3 仍然严重依赖 Web2,这开辟了广泛的创造性攻击媒介。如果您是 Javascript 专家并且您还没有尝试过在 Web3 项目上寻找错误,那么您就是在把钱留在桌面上!

I would like to thank the World team for diligently fixing this issue and giving me permission to disclose it on Hacktivity. 
我要感谢 World 团队努力解决这个问题,并允许我在 Hacktivity 上披露它。

Addressing Race Conditions:
解决竞争条件:

To prevent or mitigate race condition vulnerabilities, developers and architects can employ several strategies, such as:
为了防止或缓解争用条件漏洞,开发人员和架构师可以采用多种策略,例如:

  • Implementing proper synchronization techniques to manage access to shared resources.
    实施适当的同步技术来管理对共享资源的访问。
  • Designing systems with concurrency in mind, ensuring that operations on shared resources are atomic.
    在设计系统时考虑并发性,确保共享资源上的操作是原子的。
  • Using high-level abstractions and programming constructs designed to handle concurrency safely.
    使用旨在安全处理并发的高级抽象和编程结构。
  • Conducting thorough testing, including stress tests and concurrency tests, to uncover and fix potential race conditions.
    进行全面的测试,包括压力测试和并发测试,以发现和修复潜在的竞争条件。

原文始发于Dane Sherrets:How a Race Condition Vulnerability Could Cast Multiple Votes

版权声明:admin 发表于 2024年4月21日 下午2:51。
转载请注明:How a Race Condition Vulnerability Could Cast Multiple Votes | CTF导航

相关文章