AkashHamal0x01.me

Bypassing HackerOne 2FA due to race condition.

A race condition in HackerOne’s 2FA recovery flow created multiple active reset requests, allowing one cancellation to leave others valid.

Published
Updated

Overview

I found a race condition in HackerOne’s two-factor authentication recovery flow. Racing the reset request created several independent recovery attempts. Cancelling one attempt did not cancel the others, so a user could believe the account was safe while another reset remained active.

The original report is available through HackerOne’s limited disclosure.

Expected recovery flow

With 2FA enabled, a normal sign-in requires a valid email and password followed by the authenticator code. If the code is unavailable, the sign-in page offers a recovery path.

HackerOne sign-in form with email and password fields

The HackerOne sign-in page.

HackerOne two-factor authentication prompt with recovery links

The 2FA prompt includes a reset option.

Starting recovery displays a confirmation, then sends an email with a cancellation link. The reset completes after 24 hours unless the account owner cancels it.

Confirmation dialog for resetting two-factor authentication

Confirmation before a recovery request is created.

Account recovery email containing a link to cancel the two-factor reset

The recovery email gives the account owner a way to cancel.

After one request is active, the interface disables the reset link. That suggests recovery is a single active operation.

Disabled reset two-factor authentication link after a recovery request

The interface prevents a second ordinary request.

The race condition

The GraphQL mutation below creates a 2FA reset. Sending the same request concurrently produced multiple successful recovery attempts even though the interface presented the operation as single-use.

POST /graphql HTTP/2
Host: hackerone.com
Content-Type: application/json
X-Csrf-Token: <CSRF_TOKEN>

{
  "operationName": "TwoFactorReset",
  "variables": {
    "email": "<EMAIL>",
    "password": "<PASSWORD>",
    "fingerprint": "<FINGERPRINT>"
  }
}

Several HackerOne two-factor recovery emails delivered at the same time

Concurrent requests created several recovery emails at the same timestamp.

Impact and prerequisites

An attacker first needed the account’s valid email and password. They could then create several recovery attempts. If the account owner clicked one cancellation link, the remaining attempts stayed active. Exploitation also depended on the owner not noticing and cancelling every request before the recovery window ended.

Resolution

HackerOne rated the report Medium. The production fix made cancellation apply to the full recovery set: using any cancellation link invalidates the other reset and cancellation links, and the user is notified.

HackerOne report summary showing Medium severity and a 4.8 CVSS score

The limited-disclosure report was resolved as Medium severity.

Takeaway

A recovery flow is a state machine, not just a button. Rate limits and disabled UI controls are not enough when concurrent requests can create several valid states. Creating or cancelling one recovery attempt should invalidate every competing attempt for that account.