SecLists
SecLists is a large, organized collection of security wordlists: web paths, subdomains, usernames, passwords, and fuzzing payloads, all sorted into labeled folders. It is not a scanner; it is the fuel that makes ffuf, gobuster, Hydra, and Hashcat useful. Pick the list that fits the task and a tool finds the answer in seconds; grab the biggest file and you burn an hour on noise.
Mental model: tool -w /usr/share/seclists/<category>/<list>.txt .... SecLists supplies the file, the tool supplies the verb.
New to SecLists? Core concepts
- Category: the top-level folders -
Discovery,Usernames,Passwords,Fuzzing,Payloads,Web-Shells,Pattern-Matching. Browse withls. - Wordlist: a plain text file, one candidate per line, read top to bottom. Usually no format and no header.
- Task fit over size: a web-content list, a DNS list, a username list, and a password list are not interchangeable. Matching the task beats grabbing the largest file.
- Size is the tradeoff: small lists (
common.txt, ~4700) are fast and quiet; big lists (directory-list-2.3-big.txt, ~1.2M) are thorough but slow and loud. - Curated vs raw: some lists are deduped and ordered by likelihood (great for triage, the
raft-*set); others are raw dumps meant for deep passes. - The consuming tool owns the syntax: SecLists only names the file.
-w,FUZZ, threads, and filters all come from ffuf, gobuster, or Hydra. - Two base paths:
/usr/share/seclists/(apt) and~/SecLists/(git clone). Kali also symlinks/usr/share/wordlists/seclists.
When to reach for SecLists (and when not)
Reach for it when you need to enumerate the unknown: hidden web paths and files, subdomains, virtual hosts, likely usernames, weak passwords for an authorized login test, or payload strings to fuzz an input. It is the default answer whenever a tool asks you for a list.
Reach for something else when you already know the exact path or credential (just request it), when you need attack payloads rather than discovery names (PayloadsAllTheThings, fuzzdb), when you want freshly generated data-driven subdomains (assetnote, commonspeak), or when a single classic file is enough (rockyou.txt). A wordlist finds names, not flaws, so it never replaces manual verification.
Install, update, verify#
sudo apt install -y seclists # Debian / Ubuntu / Kali (-> /usr/share/seclists)
git clone https://github.com/danielmiessler/SecLists.git ~/SecLists # any distro, full history
git clone --depth 1 https://github.com/danielmiessler/SecLists.git ~/SecLists # much smaller, no history
sudo apt install --only-upgrade -y seclists # update (package)
cd ~/SecLists && git pull # update (clone)
ls /usr/share/seclists # categories listed == installed
wc -l /usr/share/seclists/Discovery/Web-Content/common.txt # self-test: expect ~4700 lines
SecLists has no binary and no --version: “installed” just means the folder of text files is present where your tools expect it. On Kali the package is the standard choice and matches the /usr/share/seclists paths used in most writeups. Use a shallow clone on other distros or when you want the newest lists.
Flags you’ll actually use#
SecLists itself has no flags. These are the file tools that inspect a list and the consuming-tool flags that take a list path. Skim these first; the cheat sheet below is these combined.
| Piece | Does | Piece | Does |
|---|---|---|---|
ls DIR | Show the category folders | -w PATH | Point ffuf/gobuster at a list |
find -iname | Locate a list by keyword | FUZZ | ffuf placeholder in URL or header |
wc -l FILE | Count entries (judge cost) | -e .php,.txt | ffuf: append file extensions |
head FILE | Preview the first entries | -x php,txt | gobuster: append file extensions |
grep -i PAT | Carve a focused list | -mc / -fc | ffuf: match / filter status codes |
sort -u | Dedupe a merged list | -fs / -fw | ffuf: filter by size / word count |
sed -n '1,Np' | Take the top N lines | -ic | ffuf: ignore # comment lines |
shuf FILE | Randomize request order | -t N | Threads / tasks (speed vs noise) |
Cheat sheet#
Set the prefix once, then most blocks build up: stop at the line that does the job.
export SECLISTS=/usr/share/seclists # shave the common prefix off every path below
# Find and inspect lists
ls $SECLISTS # top-level categories
find $SECLISTS -iname '*subdomain*' # locate a list by keyword
wc -l $SECLISTS/Discovery/Web-Content/common.txt # how big (== how slow)
head $SECLISTS/Discovery/Web-Content/common.txt # preview the first entries
# Web content discovery: stop at the pass that finds it
ffuf -w $SECLISTS/Discovery/Web-Content/common.txt -u http://TARGET_IP/FUZZ # 1. quick, ~4700 paths
ffuf -w $SECLISTS/Discovery/Web-Content/common.txt -u http://TARGET_IP/FUZZ -e .php,.txt,.html # 2. + file extensions
ffuf -w $SECLISTS/Discovery/Web-Content/raft-medium-directories.txt -u http://TARGET_IP/FUZZ # 3. + deeper, curated
ffuf -w $SECLISTS/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://TARGET_IP/FUZZ -ic -recursion -recursion-depth 2 # 4. + recurse (ignore # comments)
# Same first pass with gobuster (note: -x, not -e, for extensions)
gobuster dir -u http://TARGET_IP/ -w $SECLISTS/Discovery/Web-Content/common.txt -x php,txt,html -o scans/gobuster.txt
# DNS / subdomain discovery
gobuster dns -d DOMAIN -w $SECLISTS/Discovery/DNS/subdomains-top1million-5000.txt -o scans/dns.txt
ffuf -w $SECLISTS/Discovery/DNS/subdomains-top1million-20000.txt -u http://TARGET_IP/ -H 'Host: FUZZ.DOMAIN' -fs 0 # vhost fuzz, filter default size
# Parameter and value fuzzing
ffuf -w $SECLISTS/Discovery/Web-Content/burp-parameter-names.txt -u 'http://TARGET_IP/page?FUZZ=1' -fs 0 # find a param name
ffuf -w $SECLISTS/Fuzzing/SQLi/quick-SQLi.txt -u 'http://TARGET_IP/item?id=FUZZ' # feed SQLi payloads
ffuf -w $SECLISTS/Fuzzing/LFI/LFI-Jhaddix.txt -u 'http://TARGET_IP/?file=FUZZ' # feed LFI payloads
# Authorized credential testing (short lists, low tasks)
hydra -L $SECLISTS/Usernames/top-usernames-shortlist.txt \
-P $SECLISTS/Passwords/Common-Credentials/10-million-password-list-top-1000.txt \
-t 4 -f TARGET_IP ssh # -f stops at the first valid pair
# Offline cracking (lab hashes only, no live traffic)
hashcat -m 0 -a 0 hashes.txt $SECLISTS/Passwords/Common-Credentials/10-million-password-list-top-100000.txt
john --wordlist=$SECLISTS/Passwords/Leaked-Databases/rockyou.txt hashes.txt # extract rockyou first (see gotchas)
# Carve a big list into a focused one
grep -i admin $SECLISTS/Discovery/Web-Content/directory-list-2.3-medium.txt > wordlists/admin.txt # topic slice
sed -n '1,500p' $SECLISTS/Discovery/Web-Content/big.txt > wordlists/top500.txt # fast triage slice
sort -u a.txt b.txt > wordlists/merged.txt # dedupe merged lists
Command breakdowns#
Each block is one task, the exact command, and what to expect back.
List the categories and locate a list by keyword#
ls $SECLISTS
find $SECLISTS -iname '*subdomain*'
ls shows the top-level categories so you know what exists. find -iname searches every filename for a keyword, which is how you get the current name when a writeup’s path has moved or been renamed.
Preview and size a list before you commit#
wc -l $SECLISTS/Discovery/Web-Content/common.txt
head $SECLISTS/Discovery/Web-Content/common.txt
wc -l tells you the cost up front (a 4700-line list finishes in seconds, a 220k list does not). head confirms the entries look like the task you actually have (paths, not usernames).
Discover web directories with a small list#
ffuf -w $SECLISTS/Discovery/Web-Content/common.txt -u http://TARGET_IP/FUZZ
The standard first pass. FUZZ is where ffuf substitutes each line of the list. Expect a short set of paths with non-404 status codes. Start here before anything bigger.
Also catch files, not just directories#
ffuf -w $SECLISTS/Discovery/Web-Content/common.txt -u http://TARGET_IP/FUZZ -e .php,.txt,.html
-e appends each extension to every word, so admin is also tried as admin.php and admin.txt. This is how you find config.php style hits. Gobuster spells the same idea -x php,txt,html.
Go deeper with a curated medium list#
ffuf -w $SECLISTS/Discovery/Web-Content/raft-medium-directories.txt -u http://TARGET_IP/FUZZ
When the quick pass justifies more, the raft-* lists are deduped and ordered by real-world frequency, so you get depth without the million-line slog of directory-list-2.3-big.txt.
Recurse into directories you already found#
ffuf -w $SECLISTS/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://TARGET_IP/FUZZ -ic -recursion -recursion-depth 2
-recursion re-fuzzes inside each directory ffuf discovers, down to depth 2. -ic ignores the # comment header these directory-list-2.3 files carry, otherwise ffuf requests the license text as if it were paths.
Discover subdomains by DNS brute force#
gobuster dns -d DOMAIN -w $SECLISTS/Discovery/DNS/subdomains-top1million-5000.txt
Tries FUZZ.DOMAIN against DNS and prints the names that resolve. The -5000 list is the sane default; move up to -20000 or -110000 only when the target warrants it.
Find virtual hosts behind one IP#
ffuf -w $SECLISTS/Discovery/DNS/subdomains-top1million-20000.txt -u http://TARGET_IP/ -H 'Host: FUZZ.DOMAIN' -fs 0
Same lists, different technique: it varies the Host header instead of DNS, so it finds name-based vhosts that do not resolve publicly. -fs 0 (or the real default response size) filters the identical catch-all page.
Find a hidden parameter name#
ffuf -w $SECLISTS/Discovery/Web-Content/burp-parameter-names.txt -u 'http://TARGET_IP/page?FUZZ=1' -fs 0
Fuzzes the parameter key, not its value, to discover inputs the page reads but does not advertise. Filter by the baseline size so only parameters that actually change the response show up.
Feed fuzzing payloads into a known parameter#
ffuf -w $SECLISTS/Fuzzing/SQLi/quick-SQLi.txt -u 'http://TARGET_IP/item?id=FUZZ'
Here the list is payload strings, not names. The Fuzzing/ category holds SQLi, LFI (LFI-Jhaddix.txt), XSS, and special-character sets to probe how an input reacts. Watch for errors or size changes, then verify by hand.
Test a login with short lists (Hydra)#
hydra -L $SECLISTS/Usernames/top-usernames-shortlist.txt -P $SECLISTS/Passwords/Common-Credentials/10-million-password-list-top-1000.txt -t 4 -f TARGET_IP ssh
-L and -P take the user and password lists, -t 4 keeps it gentle, -f stops at the first valid pair. Keep both lists small: password lists cause account lockouts and flood auth logs.
Crack captured hashes offline#
hashcat -m 0 -a 0 hashes.txt $SECLISTS/Passwords/Common-Credentials/10-million-password-list-top-100000.txt
Offline means no traffic to the target, so a big list is fine here. -m 0 is raw MD5, -a 0 is straight dictionary. John’s equivalent is john --wordlist=LIST hashes.txt. Start with a top-N slice before the full million.
Carve a focused list from a big one#
grep -i admin $SECLISTS/Discovery/Web-Content/directory-list-2.3-medium.txt > wordlists/admin.txt
When you only care about one theme, grep a huge list into a tiny targeted one, then run that in seconds instead of paying for the whole file.
Take a fast triage slice#
sed -n '1,500p' $SECLISTS/Discovery/Web-Content/big.txt > wordlists/top500.txt
Lists are ordered by likelihood, so the first N lines are the highest-probability candidates. A 500-line slice gives a near-instant first look before you commit to the full file.
Filter out catch-all noise#
ffuf -w $SECLISTS/Discovery/Web-Content/common.txt -u http://TARGET_IP/FUZZ -fs 1234
When every path returns 200 (a wildcard route or SPA), grab the size of a known-bad path and pass it to -fs (filter size), or use -fw / -fc, so only genuinely different responses survive.
Reading the output#
SecLists emits nothing itself; you read the consuming tool’s result and judge signal from noise.
| Signal | Meaning | Do next |
|---|---|---|
| A few hits, varied sizes | Real paths or names | Verify each one by hand |
| Many hits, all the same size | Catch-all / wildcard page | Filter with -fs SIZE or -fc |
| Zero hits on a big list | List does not fit the tech | Switch to a task-fitted list |
| Endless crawl, little found | List too big for triage | Start small, widen only if justified |
| Hydra prints a green pair | Valid credential | Confirm by logging in once |
| Lockouts or auth errors | Login test too fast/broad | Shrink lists, lower -t, confirm scope |
Troubleshooting#
| Problem | Cause | Fix |
|---|---|---|
No such file or directory | Not installed / wrong base path | Install seclists; check /usr/share/seclists vs your clone |
| Empty or tiny list file | Bad download or partial clone | Reinstall the package or re-clone the repo |
| Tool runs but finds nothing | List does not fit the task | Switch to a list built for that task (web, DNS, creds) |
| Everything returns a hit | App serves a catch-all page | Filter by size/words/status (-fs, -fw, -fc) |
| ffuf requests garbage license text | directory-list-2.3 # header | Add -ic to ignore comment lines |
| Run is painfully slow | List too large for triage | Start small (common.txt), widen if justified |
| Account lockouts | Password list too large or fast | Shorten the list, lower -t, confirm lockout policy |
| Path differs from a writeup | Package vs git layout, or renamed list | Adjust the base path; find -iname for the current name |
Gotchas#
- rockyou ships compressed in SecLists (
Passwords/Leaked-Databases/rockyou.txt.tar.gz). Extract it before use, or point tools at Kali’s/usr/share/wordlists/rockyou.txtinstead. directory-list-2.3files start with a#comment block (a license header). ffuf and some tools will request those lines as paths unless you pass-icor strip them withgrep -v '^#'.-eis ffuf,-xis gobuster for extensions. Swap them and the flag is silently ignored or errors out, and you quietly stop finding files.- Bigger is not better online.
directory-list-2.3-big.txt(~1.2M) and the 10-million password list get you rate-limited or locked out long before they help. Save the huge files for offline cracking. - Package path and clone path differ. A writeup’s
/usr/share/seclists/...may be~/SecLists/...on your box (Kali also symlinks/usr/share/wordlists/seclists). Set$SECLISTSonce and reuse it. - A wordlist finds names, not flaws. A hit is a candidate, not a finding: confirm every path, subdomain, or credential by hand before you trust it.
Pairs with#
ffuf and gobuster or feroxbuster consume the Discovery lists for path, DNS, and vhost work; SecLists is the fuel, they are the engine. Hydra and medusa take the Usernames and Passwords lists for authorized login testing, and Hashcat and John eat the Passwords lists as dictionaries for offline cracking. grep, sort, sed, and shuf carve a big list into a focused one, and jq parses the JSON that ffuf writes into tidy notes. For attack payloads beyond discovery names, reach for PayloadsAllTheThings or fuzzdb; for freshly generated subdomains, assetnote and commonspeak lists pair well rather than replace SecLists.