| Tested on | Kali GNU/Linux Rolling 2026.2 (kali-rolling) |
|---|---|
| Package | gobuster 3.8.2-1dirb 2.22+dfsg-7nikto 1:2.6.0-0kali4curl 8.20.0-5gau 2.2.4 (Go install)LinkFinder (GitHub clone + Python venv) |
| Applies to | Kali Linux |
| Lab environment | Kali + Metasploitable 2 on VirtualBox host-only — pentest lab setup |
| Privilege | Normal user for scans; sudo for apt install; Go toolchain for gau |
| Scope | Directory brute force with Gobuster, JavaScript route extraction with LinkFinder, archive URL collection with gau on example.com, validation with curl, and a short Nikto pass against Metasploitable Apache. Covers hidden URLs, web paths, and API-style routes. Does not cover deep recursive fuzzing, APK analysis, or GitHub secret hunting. |
| Related guides | Learn hacking with Metasploitable 2 |
Hidden endpoints are URLs and API-style paths that exist on a server but never appear in the site menu. After banner grabbing shows Apache or nginx on port 80, mapping those paths is a common next step in an ethical hacking lab.
This guide runs Gobuster, LinkFinder, gau, Nikto, and curl on Kali against Metasploitable 2 HTTP and authorized archive lookups on example.com. Every command and output below was captured on that layout.
What is hidden endpoint discovery in ethical hacking?
The rest of this guide maps URLs the web server answers before you fuzz parameters or test access control. You are widening the target list, not exploiting vulnerabilities yet.
A hidden URL is any path not linked in navigation, such as /phpMyAdmin/ or /backup.zip. A hidden endpoint is any route that accepts HTTP requests. A hidden API route is a machine-oriented path such as /api/v1/users or /graphql, often leaked in JavaScript before it appears in public docs.
Discovery methods overlap:
- Active brute force — wordlist guesses against the web root (Gobuster)
- JavaScript mining — strings inside
.jsbundles (LinkFinder, browser DevTools) - Passive archives — historical URLs from Wayback and Common Crawl (gau)
- Scanner fingerprints — common sensitive paths (Nikto)
- Proxy traffic — live API calls after login (Burp Suite)
Strings in minified JavaScript are leads, not proof. Validate each path with curl or your proxy before you report it.
Kali lab setup
Set the web target once so Gobuster, Nikto, and curl share the same base URL:
TARGET=192.168.56.114
WEB_URL=http://192.168.56.114
ARCHIVE_DOMAIN=example.com
LAB=/tmp/hidden-endpoints-lab
mkdir -p "$LAB"Install the core packages from Kali repositories:
sudo apt update
sudo apt install -y gobuster dirb nikto curl golang-goConfirm Gobuster before you brute-force paths:
gobuster version3.8.2Kali does not ship gau as an apt package on this image. Install it with Go when you need archive URL collection:
go install github.com/lc/gau/v2/cmd/gau@latest
export PATH="$PATH:$HOME/go/bin"
gau --versiongau version: 2.2.4Clone LinkFinder into the lab directory for the JavaScript section:
git clone https://github.com/GerbenJavado/LinkFinder.git "$LAB/LinkFinder"
python3 -m venv "$LAB/linkfinder-venv"
"$LAB/linkfinder-venv/bin/pip" install -r "$LAB/LinkFinder/requirements.txt"The tool sections below reuse WEB_URL, ARCHIVE_DOMAIN, and "$LAB" — only the discovery technique changes.
Compare hidden endpoint discovery methods
Pick a technique before you run high-volume fuzzers from URL fuzzer tools.
| Method | Tool | Best for | Typical success signal |
|---|---|---|---|
| Directory brute force | Gobuster | Unlinked folders on the web root | phpMyAdmin with status 301 or 200 |
| JavaScript mining | LinkFinder | API paths inside .js files |
/api/ or /graphql strings |
| Archive URLs | gau | Forgotten paths in crawls | Historical URLs in stdout |
| Validation | curl | Confirm a path is live | 200 or 403 instead of 404 |
| Scanner pass | Nikto | Known sensitive files and headers | OSVDB-style findings in output |
Combine brute force with JavaScript and archive passes on real engagements. Each source surfaces different paths.
Brute-force paths with Gobuster
Gobuster walks a wordlist against WEB_URL and prints HTTP status codes for each guess. Start with the bundled dirb common list before you load million-line files.
Run a quiet directory scan against Metasploitable:
gobuster dir -u "$WEB_URL" -w /usr/share/wordlists/dirb/common.txt -q -t 20 --timeout 5sSample output (trimmed):
dav (Status: 301) [Size: 319] [--> http://192.168.56.114/dav/]
phpMyAdmin (Status: 301) [Size: 326] [--> http://192.168.56.114/phpMyAdmin/]
phpinfo.php (Status: 200) [Size: 48026]
test (Status: 301) [Size: 320] [--> http://192.168.56.114/test/]
twiki (Status: 301) [Size: 321] [--> http://192.168.56.114/twiki/]phpMyAdmin and phpinfo.php are classic hidden-path findings on Metasploitable. A small wordlist will not list every lab app; escalate to larger lists or recursive fuzzers when scope allows.
Save results when you need a file for reporting:
gobuster dir -u "$WEB_URL" -w /usr/share/wordlists/dirb/common.txt -q -t 20 --timeout 5s -o "$LAB/gobuster.txt"Extract routes from JavaScript with LinkFinder
Single-page apps embed API bases and relative paths inside JavaScript bundles. LinkFinder applies regexes so you do not read minified files by hand.
Create a small sample file that mimics strings you see in real bundles:
cat > "$LAB/sample-app.js" << 'EOF'
const API_BASE = "https://api.example.com/v2";
fetch("/api/v1/users");
const admin = "/admin/debug/status";
const gql = "/graphql";
EOFRun LinkFinder against that file:
"$LAB/linkfinder-venv/bin/python" "$LAB/LinkFinder/linkfinder.py" -i "$LAB/sample-app.js" -o clihttps://api.example.com/v2
/api/v1/users
/admin/debug/status
/graphqlFilter results to your in-scope host before you send traffic. For a remote bundle on an authorized target, replace the path with -i https://your-scope.example/static/app.js.
Collect archived URLs with gau
gau (getallurls) pulls known URLs for a hostname from Wayback Machine, Common Crawl, and other indexes. Old API paths often survive in archives after teams remove them from the live site.
Collect URLs for the IANA reserved documentation domain:
gau "$ARCHIVE_DOMAIN" --blacklist png,jpg,gif,css,woff,svg 2>&1 | head -5Sample output (trimmed):
time="..." level=warning msg="error reading config: Config file .../.gau.toml not found, using default config"
http://example.com:80/Archive hits on example.com are sparse compared to production domains. On customer zones you typically see /api/, /v1/, and forgotten staging hosts after you filter static extensions.
Save and filter API-like paths when you have a longer list:
gau "$ARCHIVE_DOMAIN" --blacklist png,jpg,gif,css,woff,svg -o "$LAB/gau.txt"
grep -iE '/api/|/graphql|/v[0-9]/|/internal/' "$LAB/gau.txt" | sort -u > "$LAB/archive-api-candidates.txt"Drop third-party and out-of-scope hosts before you validate anything from archive-api-candidates.txt.
Validate endpoints with curl
A string in JavaScript or a 301 from Gobuster is not enough for a report. Confirm the path with a safe GET and record the status code.
Check paths Gobuster reported on the lab host:
curl -s -o /dev/null -w 'phpMyAdmin %{http_code}\n' "$WEB_URL/phpMyAdmin/"phpMyAdmin 200curl -s -o /dev/null -w 'twiki %{http_code}\n' "$WEB_URL/twiki/"twiki 200200 means the path answered. 401 and 403 still prove the route exists but blocked your request. 404 may mean the path is gone or hidden by routing rules.
Find common files with Nikto
Nikto checks hundreds of known sensitive paths and version fingerprints. It complements Gobuster by flagging configuration issues around the paths you already found.
Run a short pass against the lab web server:
nikto -h "$WEB_URL" 2>&1 | head -15Sample output (trimmed):
- Nikto v2.6.0
+ Target IP: 192.168.56.114
+ Target Port: 80
+ Server: Apache/2.2.8 (Ubuntu) DAV/2
+ [999986] /: Retrieved x-powered-by header: PHP/5.2.4-2ubuntu5.10.
+ [750500] /icons/: Directory indexing found.
+ [999965] /index: Apache mod_negotiation is enabled with MultiViews...Nikto highlighted PHP 5.2.4 and mod_negotiation on the same host where Gobuster found phpinfo.php. Feed those paths into CVE research and deeper URL fuzzing when scope allows.
Watch live traffic with DevTools and Burp
Browser DevTools and Burp Suite capture endpoints that brute force and archives miss, especially after login.
Open DevTools on an authorized web app, filter the Network tab to Fetch/XHR, and click through workflows you are allowed to test. Copy API paths that contain /api/, /graphql, /v1/, or JSON responses.
With Burp, proxy the browser, browse as a test user, and review HTTP history and the site map for JSON bodies and GraphQL calls. Export interesting paths into the same validation workflow you used with curl.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Gobuster finds almost nothing | Wordlist too small or wrong base URL | Try /usr/share/wordlists/dirb/big.txt or confirm WEB_URL has no trailing path |
gau: command not found |
Go binary not on PATH | go install ... and export PATH="$PATH:$HOME/go/bin" |
| gau lists out-of-scope hosts | Archive noise | Filter by domain; drop CDN and third-party names |
| LinkFinder pip install fails | PEP 668 on Kali Python | Use "$LAB/linkfinder-venv" as shown in lab setup |
| curl returns 404 for a JS string | Stale or client-only route | Treat JS output as a lead; try authenticated Burp traffic |
| Nikto scan runs a long time | Default test depth | Limit with -maxtime on lab hosts |
References
- Gobuster
- LinkFinder
- gau (getallurls)
- Nikto
- PortSwigger — Web application API testing
- IANA example domains
Summary
You mapped hidden web paths on Kali using Gobuster against Metasploitable 2, mined API-style strings from JavaScript with LinkFinder, collected archive URLs with gau on example.com, validated paths with curl, and ran a short Nikto fingerprint pass. Gobuster surfaced phpMyAdmin, phpinfo.php, and twiki while LinkFinder extracted /api/v1/users and /graphql from a sample bundle.
No single tool covers every endpoint. Brute force finds server paths, JavaScript and proxy traffic expose API routes, and archives resurrect old URLs. Validate every lead with curl or Burp before you fuzz parameters or test access control.
Run these workflows only on authorized targets. When you need recursive forced browsing or custom filters, continue with URL fuzzer tools and manual testing in Burp Suite.

