Web Enumeration
#Overview
Web enumeration involves systematically discovering directories, files, virtual hosts, API endpoints, and technologies running on HTTP/HTTPS services. This is the most common attack surface in modern penetration tests, as web applications often expose vulnerabilities that lead to initial foothold. The process includes directory/file brute-forcing, virtual host discovery, technology fingerprinting, SSL/TLS inspection, and source code analysis.
#Prerequisites
- Tools: gobuster, ffuf, feroxbuster, dirb, whatweb, curl, wget, Burp Suite
- Wordlists: SecLists (raft-large-words, directory-list-2.3-medium, common.txt, big.txt), bitquark-subdomains-top100000.txt
- Access Level: Network access to target web server (HTTP/HTTPS)
- Recommended: Browser with Wappalyzer extension, Burp Suite for request inspection
#Detection & Enumeration
#Adding Discovered Domains to /etc/hosts
Essential first step when nmap or initial browsing reveals domain names:
# Add single domain
echo "10.10.11.11 board.htb" | sudo tee -a /etc/hosts
# Add multiple domains
echo "10.10.10.161 htb.local FOREST.htb.local" | sudo tee -a /etc/hosts
# Add subdomain discovered during enumeration
echo "10.10.11.11 crm.board.htb" | sudo tee -a /etc/hosts
echo "10.10.11.194 soc-player.soccer.htb" | sudo tee -a /etc/hosts
# Add domain controller and FQDN
echo "10.129.178.26 support.htb dc.support.htb" | sudo tee -a /etc/hosts
BASH
#Technology Fingerprinting
# whatweb -- fast technology identification
whatweb http://10.10.10.175
whatweb -a 3 http://board.htb # Aggression level 3 (more thorough)
# curl headers inspection
curl -I http://10.10.10.175
curl -s -D- http://10.10.10.175 | head -20
# Inspect SSL/TLS certificate for virtual hosts and SANs
openssl s_client -connect 10.10.10.161:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep DNS
# Check robots.txt and sitemap.xml
curl -s http://target.htb/robots.txt
curl -s http://target.htb/sitemap.xml
BASH
whatweb flags:
-a: Aggression level (1=passive, 3=aggressive/heavy, 4=very heavy)- No flags: Default balanced scan identifies CMS, frameworks, server software
#Directory and File Brute-Forcing
gobuster (Fast, Go-based)
# Basic directory scan with common wordlist
gobuster dir -u http://soccer.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
# With extensions and status code filtering
gobuster dir -u http://board.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words.txt -x php,txt,html,bak,zip -o gobuster_scan.txt
# Ignore specific status codes and add delay for stealth
gobuster dir -u http://target.htb -w /usr/share/wordlists/dirb/common.txt -x aspx,asp,php -b 404,403 --delay 500ms
# Common options:
# -x : Extensions to append (php,aspx,txt,html,bak,zip,old)
# -b : Blacklist status codes (ignore these)
# -o : Output file
# -t : Threads (default 10)
# -k : Skip SSL certificate validation
# --delay : Delay between requests
BASH
ffuf (Fast, Flexible, Rust-based)
# Basic directory fuzzing
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://10.10.10.175/FUZZ
# With size filtering (ignore baseline response size)
ffuf -w /usr/share/wordlists/dirb/common.txt -u http://board.htb/FUZZ -fs 15949
# Extension brute-force
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-words.txt -u http://target.htb/FUZZ -e .php,.aspx,.txt,.html,.bak
# With match codes (only show specific HTTP codes)
ffuf -w /path/to/wordlist -u http://target.htb/FUZZ -mc 200,301,302,403
# Recursive depth
ffuf -w /path/to/wordlist -u http://target.htb/FUZZ -recursion -recursion-depth 2
# Rate limiting (requests/sec)
ffuf -w /path/to/wordlist -u http://target.htb/FUZZ -rate 50
BASH
feroxbuster (Recursive, Rust-based)
# Basic recursive scan
feroxbuster -u http://target.htb
# With extensions and depth control
feroxbuster -u http://target.htb -x php,html,txt,bak -d 3
# Quiet mode with output
feroxbuster -u http://target.htb -x php -q -o ferox_scan.txt
BASH
dirb (Classic, Slower)
# Basic scan
dirb http://target.htb
# With custom wordlist and extensions
dirb http://target.htb /usr/share/wordlists/dirb/big.txt -X .php,.html,.txt
BASH
#Wordlist Selection Guide
| Wordlist | Size | Best For |
|---|---|---|
dirb/common.txt | ~4,600 | Quick initial scan |
dirbuster/directory-list-2.3-medium.txt | ~220,000 | Thorough directory discovery |
seclists/Discovery/Web-Content/raft-large-words.txt | ~120,000 | Broad word coverage |
seclists/Discovery/Web-Content/big.txt | ~20,000 | Medium coverage |
seclists/Discovery/Web-Content/common.txt | ~4,700 | Quick scan with good coverage |
seclists/Discovery/Web-Content/CGIs.txt | ~3,500 | CGI script discovery |
#Virtual Host (VHOST) Discovery
# ffuf VHOST fuzzing (subdomain enumeration via Host header)
ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt:FUZZ \
-u http://board.htb/ -H 'Host: FUZZ.board.htb' -fs 15949
# Multi-level subdomain discovery
ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ \
-u http://domain.htb/ -H 'Host: FUZZ.domain.htb' -mc 200,301,302,403
# VHOST discovery with gobuster
gobuster vhost -u http://board.htb -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt
BASH
Key VHOST flags:
-H 'Host: FUZZ.domain.htb': The FUZZ keyword is replaced with each wordlist entry in the Host header.-fs: Filter by response size (ignore the baseline/default response size).-mc: Match specific HTTP status codes.- VHOST enumeration works because the web server returns different content based on the
Hostheader.
#SSL/TLS Certificate Inspection
SSL certificates often leak internal hostnames, subdomains, and organizational information:
# Full certificate dump
openssl s_client -connect 10.10.10.161:443 </dev/null 2>/dev/null | openssl x509 -noout -text
# Extract Subject Alternative Names (SANs) -- reveals vhosts
openssl s_client -connect target.htb:8443 </dev/null 2>/dev/null | \
openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
# Check certificate expiry
echo | openssl s_client -connect target.htb:443 2>/dev/null | \
openssl x509 -noout -dates
# Nmap SSL certificate script
nmap --script ssl-cert -p 443,8443 target.htb
BASH
#Source Code Inspection
# Download page and grep for comments, hidden fields, and secrets
curl -s http://target.htb | grep -i '<!--\|hidden\|password\|api\|key\|token\|secret'
# Extract all JavaScript files for review
curl -s http://target.htb | grep -oP 'src="[^"]*\.js"' | cut -d'"' -f2
# View page source for hidden input fields and comments
curl -s http://target.htb | grep -E '<input.*type="hidden"|<form|<script'
# Inspect WebSocket endpoints in source
curl -s http://target.htb | grep -i 'ws://\|wss://\|WebSocket'
# Find .git directory exposure
curl -s http://target.htb/.git/HEAD
curl -s http://target.htb/.git/config
# Git dumping when .git is exposed
git-dumper http://target.htb/.git/ ./dumped-git/
BASH
#API Endpoint Discovery
# Common API paths
curl -s http://target.htb/api/
curl -s http://target.htb/api/v1/
curl -s http://target.htb/swagger/
curl -s http://target.htb/graphql
curl -s http://target.htb/.well-known/
# REST API fuzzing with ffuf
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/api-endpoints.txt \
-u http://target.htb/FUZZ -mc 200,403,401
# Swagger/OpenAPI documentation discovery
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/swagger.txt \
-u http://target.htb/FUZZ
BASH
#WebSocket Enumeration
WebSocket services may run on non-standard ports and can be vulnerable to injection attacks:
# Identify WebSocket endpoints from JavaScript
curl -s http://target.htb | grep -oP "ws://[^'\"]+|wss://[^'\"]+"
# Test WebSocket connectivity
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" http://target.htb:9091/
# sqlmap can test WebSocket services for SQL injection
sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "*"}' --dbs --threads 10 --level 5 --risk 3 --batch
BASH
#CMS-Specific Enumeration
# WordPress
wpscan --url http://target.htb --enumerate p,u,t # plugins, users, themes
# Drupal
droopescan scan drupal -u http://target.htb
# Joomla
joomscan -u http://target.htb
# Dolibarr (ERP/CRM) -- default credentials admin:admin
# Check version from page footer or admin dashboard
BASH
#Additional Web Scanning Tools
# nikto -- Web vulnerability scanner (extremely noisy, well-signatured)
nikto -h http://10.10.10.10
nikto -h http://10.10.10.10 -Tuning 1234 # Run specific test categories
# Warning: nikto is very noisy and its User-Agent is widely signatured by WAFs/IDS
# Best for: Quick vulnerability overview on non-monitored targets
# dirsearch -- Alternative directory brute-forcer
dirsearch -u http://10.10.10.10 -w /usr/share/seclists/Discovery/Web-Content/common.txt
dirsearch -u http://10.10.10.10 -e php,html,js,txt
# nmap http-enum for initial path discovery
nmap --script http-enum -p 80,443 10.10.10.10
# ffuf API fuzzing with JSON content type
ffuf -u http://10.10.10.10/api/FUZZ -H 'Content-Type: application/json' -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt
BASH
#Common Pitfalls
- Forgetting to add domains/subdomains to
/etc/hostsbefore scanning. Services like Kerberos, SMB, IIS, and VHOSTs require proper name resolution. - Using the wrong wordlist size for the context.
raft-large-words.txtis great for thorough scans but takes much longer thancommon.txt. - Not filtering by response size (
-fs) in ffuf, causing false positives where the server returns the same default page for all missing paths. - Ignoring 403 Forbidden responses. A 403 means the resource exists but access is denied -- this is actionable intel.
- Not checking for file extension variations. A backup file like
config.php.bakorweb.config.oldcan leak credentials. - Using HTTP when the server redirects to HTTPS. Always check both and handle redirects.
- Not reviewing SSL certificate SAN entries. These often reveal internal subdomains not listed anywhere else.
- Overlooking WebSocket endpoints in JavaScript source. They often run without authentication.
- Not attempting default credentials for discovered CMS/platforms (e.g.,
admin:adminfor Dolibarr,admin:admin@123for Tiny File Manager).
#OPSEC Considerations
- Directory brute-forcing generates hundreds to thousands of HTTP requests in a short period. This is a clear signal to any WAF, IDS, or log monitoring system. Use rate limiting (
--delayin gobuster,-ratein ffuf) for stealth. - 403 Forbidden responses from WAFs may indicate your IP is being throttled or blocked. If you start getting 403s universally, the WAF has likely blacklisted you.
- User-Agent strings identify your tooling. gobuster defaults to "gobuster/version", ffuf uses "Fuzz Faster U Fool". Customize with
-H 'User-Agent: Mozilla/5.0 ...'to blend in. - VHOST brute-forcing with Host headers is logged by the web server and may trigger alerts for DNS rebinding or host header attacks.
- Technology fingerprinting (whatweb) sends identifiable request patterns. Use passive mode (
-a 1) for lower profile. - SSL certificate inspection is passive and generates no application-layer logs. It is one of the stealthiest enumeration techniques.
- Checking for .git exposure (
curl http://target/.git/HEAD) is a single request and relatively stealthy, but repeated checks for many paths add up. - CMS scanners like wpscan are extremely noisy and well-signatured. They should only be used with authorization in non-stealth engagements.
- OPSEC: feroxbuster uses a distinctive User-Agent -- can be flagged by WAFs.
- OPSEC: nikto is one of the most well-signatured scanning tools -- almost all WAFs detect it.
- OPSEC: dirsearch is quieter than nikto but still creates distinctive request patterns.
#Post-Exploitation Value
- Web enumeration commonly reveals admin panels, configuration files, and backup archives that lead to initial foothold.
- Discovered directories often expose the technology stack (framework, CMS, language) which guides vulnerability research.
- Source code comments and hidden HTML fields may contain credentials, API keys, or internal paths.
- Virtual hosts discovered through VHOST enumeration often host less-secure applications or development instances.
- Internal web applications accessible only post-exploitation (on localhost or internal subnets) often have weaker security.
- Configuration files (
conf.php,web.config,.env) in web roots frequently contain database credentials that can be reused for lateral movement.
#Cross-References
#Tool References
| Tool | Description | Link |
|---|---|---|
| gobuster | Directory/VHOST/DNS brute-force (Go) | https://github.com/OJ/gobuster |
| ffuf | Fast web fuzzer (Rust) | https://github.com/ffuf/ffuf |
| feroxbuster | Recursive content discovery (Rust) | https://github.com/epi052/feroxbuster |
| dirb | Classic directory brute-forcer (C) | Built into Kali |
| whatweb | Website technology fingerprinting | https://github.com/urbanadventurer/WhatWeb |
| Wappalyzer | Browser extension for technology identification | https://www.wappalyzer.com/ |
| git-dumper | Downloads exposed .git repositories | https://github.com/arthaud/git-dumper |
| wpscan | WordPress vulnerability scanner | https://wpscan.com/wordpress-security-scanner |
| droopescan | Drupal/SilverStripe scanner | https://github.com/SamJoan/droopescan |
| sqlmap | SQL injection detection/exploitation (including WebSocket) | https://sqlmap.org/ |
| curl | Command-line HTTP client | Built into most systems |
| Burp Suite | Web application security testing platform | https://portswigger.net/burp |
#Source Machines
- BoardLight (Easy, Linux) -- ffuf VHOST discovery finds
crm.board.htb, Dolibarr default credentials lead to RCE - Sauna (Easy, AD) -- ffuf web scan, usernames derived from "About" page, ASREPRoasting
- Soccer (Easy, Linux) -- gobuster finds
/tinydirectory, default Tiny File Manager credentials, WebSocket SQLi on port 9091 - Support (Easy, Windows) -- No web server, shifted directly to SMB/LDAP enumeration
- Broker (Easy, Linux) -- nmap identifies ActiveMQ, web enumeration confirms version 5.15.15 for CVE targeting
- Authority (Medium, AD/Windows) -- HTTPS on 8443 reveals PWM password manager, SSL certificate inspection