What Is Password Reset Poisoning?💀

Password reset poisoning is a vulnerability where an application incorrectly handles user-supplied input in the password reset flow, causing the reset link or token to be sent to unintended recipients.

This usually happens when:

  • The backend trusts client-provided email parameters
  • Multiple email values are accepted for a single reset request
  • The reset token is not strictly bound to one user or email

As a result, an attacker may receive the same password reset link as the legitimate user, without compromising the victim's email account.

Now that we know what the vulnerability is , lets go through the experience of finding it👍

Step 1: Capturing the Password Reset Request

None

I began by triggering the Forgot Password functionality for the temporary email on the website I was testing on and intercepted the request using Burp Suite.

Original Request Structure:

POST /auth/passwordlink HTTP/2
Content-Type: application/json
{
  "email": "victim@gmail.com"
}

The server responded with a success message, confirming the normal password reset flow. Now as an Ethical Hacker , My interest peaked to test the function.

Step 2: Playing Around With Common Bypass Techniques

I tested a few common bypass and injection patterns to understand how strictly the backend validated input.

Well, there are multiple approaches one can take, such as :

1. email=victim@gmail.com&email=attacker@gmail.com
2. email=victim@gmail.com%20email=attacker@gmail.com
3. email=victim@gmail.com |email=attacker@gmail.com
4. email=victim@gmail.com%0d%0acc:attacker@gmail.com
5. email=victim@gmail.com&code=my_password_reset_token

but most of these resulted in a error, specifically for the JSON parsing:

{
  "success": false,
  "status": 400,
  "message": "Expected ',' or ']' after array element in JSON at position 58"
}

This showed that the backend was expecting valid JSON and rejecting malformed input.

Since these approaches didn't work, I moved on to a different approach.

Step 3: Changing the Data Type — One Attempt Worked

None

Instead of breaking the JSON structure, I kept the request valid and changed the data type of the email parameter. You can find the modified payload by scrolling down.

Modified Request Payload

None
POST /auth/passwordlink HTTP/2
Content-Type: application/json
{
  "email": [
    "victim@gmail.com",
    "attacker@gmail.com"
  ]
}

This request was accepted by the backend without any validation errors.

Step 4: Checking the Emails🔍

After the successful response, I checked both mailboxes.

Observation:

  • The password reset email was delivered to both email addresses
  • The email content and reset link were the same
  • The timestamps matched, confirming duplication (Ill attach a screenshot for you guys at the end😉)

Although this behavior was already identified as a duplicate😭 and was under fixing during my testing, the exercise itself was valuable.

It reinforced an important lesson:

If one approach doesn't work, try another.

Not every test will succeed on the first attempt. Sometimes it's not about forcing an exploit, but about changing perspective — from values to structure, from payloads to data types.

And that's where learning really happens.

None
None

That's it for today guys, meet you next time with a new finding😎 Twilight out🫡🫡