Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

exposure-scanner.py

Find exposed files containing credentials on web services.

Basic scan:

python3 exposure-scanner.py https://test.com

Follow redirects and re-classify — this is the mode you want, because your box returns 301 on HTTP→HTTPS and you never see the real status until you follow:

python3 exposure-scanner.py https://test.com --follow-redirects

Slow it down (be polite to your own box and any WAF):

python3 exposure-scanner.py https://test.com --delay 0.25 --workers 4

Save results, compare next week:

# First run
python3 exposure-scanner.py https://test.com --json-out scan-2026-09-11.json

# Next week
python3 exposure-scanner.py https://test.com --json-out scan-2026-09-18.json --diff scan-2026-09-11.json

Only show what matters:

python3 exposure-scanner.py https://test.com --only-critical

Show everything including 404s (useful for verifying the scanner is actually hitting paths):

python3 exposure-scanner.py https://test.com --show-info

What it covers

Category Examples
.env variants All the ones your adversary used, plus ~50 more (.env.php-bak, .env-smtp.log, .env-sendgrid, etc.)
Cloud creds credentials.json, service-account.json, gcp-key.json, firebase-adminsdk.json, AWS/Azure/GCP configs
SSH/TLS keys id_rsa, .pem, .key, keystore.jks, authorized_keys
VCS metadata .git/config, .git/HEAD, .git-credentials, .svn/entries
CI/CD configs .github/workflows/*.yml, .gitlab-ci.yml, Jenkinsfile, cloudbuild.yaml, buildspec.yml
Docker/K8s docker-compose.yml, Dockerfile, k8s.yml, Helm values
IaC terraform.tfstate, terraform.tfvars, Ansible vaults, Pulumi
AI/LLM configs .claude/settings.json, .cursor/mcp.json, .continue/config.json, .openai/api_key, claude_desktop_config.json, mcp.json
Backups backup.sql, www.zip, dump.sql.gz, .tar.gz variants
WordPress wp-config.php.bak, wp-admin/install.php, xmlrpc.php, wp-content/debug.log
PHP probes phpinfo.php, test.php, adminer.php, i.php, pi.php
Editor swaps index.php~, config.php.swp, .DS_Store
Package files package.json, composer.lock, yarn.lock, requirements.txt
Logs debug.log, laravel.log, storage/logs/laravel.log, access.log

Combined with ~200 directory prefixes (backend/, .git/, .claude/, staging/, api/, etc.), that's roughly 60,000+ paths to test.

How the severity logic works

  • CRITICAL — A known-sensitive file returned 200 (e.g., .env, id_rsa, credentials.json, wp-config.php.bak). This is the "rotate everything now" bucket.
  • MEDIUM — 401 (auth challenge on a sensitive path), 500-series errors on a probe, a directory listing (200 on a path ending in /), or an unclassified 200. Worth manually inspecting.
  • LOW — 403 (file exists but is blocked — this is actually good, but confirms the path), 405, 204, or an informational file (README, package.json) returning 200.
  • INFO — 404, 301/302/307/308 redirects, "not found" results.
  • ERROR — Connection failures, timeouts, unexpected exceptions.

Important notes

  1. Authorization: Only run this against your own infrastructure. It's aggressive by nature. Running it against a host you don't own is unauthorized access in most jurisdictions.
  2. Redirects: The scanner does not follow redirects by default — because on your box, most .env hits were 301s that turned out to be HTTP→HTTPS. Run with --follow-redirects to get the real answer, but be aware this doubles the number of requests.
  3. Download limits: It reads at most 4 KB per response — so a 200 on /backup.sql won't download your entire database. It just confirms the resource is served.
  4. SSL Verification: verify=False — the scanner accepts self-signed certs. Since you're scanning your own box, this is fine and avoids failures if a vhost has a cert issue. If you want strict verification, change verify=False to verify=True in the probe method.
  5. Rate limiting: Rate limiting is per-worker — with --workers 8 --delay 0.1, you'll do about 80 requests/second. That's aggressive for a small VPS. Start with --workers 4 --delay 0.5 and see how the box handles it.
  6. Customization: Extend the wordlist easily — BASE_FILES and APP_DIRS are plain Python lists. Add anything you want. The combinator is base × dirs, so 1 new base file × 200 dirs = 200 new probes.

Suggested weekly workflow

Run the scan and log it:

cd /root/scans
python3 exposure-scanner.py https://test.com \
    --follow-redirects \
    --delay 0.2 --workers 4 \
    --json-out "scan-$(date +%F).json" \
    --quiet --only-critical 2>&1 | tee "scan-$(date +%F).log"

Then diff next week:

python3 exposure-scanner.py https://test.com \
    --follow-redirects \
    --json-out "scan-$(date +%F).json" \
    --diff "$(ls -1t scan-*.json | head -2 | tail -1)"

The --diff output will tell you exactly what changed since last week — new critical findings, resolved ones — so you can act on deltas rather than re-reading the whole report.

About

Find exposed files containing credentials on web services.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages