Web 目录扫描工具对比与实战流程
目录扫描最容易出现两个极端:只跑一份默认字典导致遗漏,或同时启动多个高并发工具制造大量重复请求。更有效的方式是先理解站点基线,再根据技术栈和当前线索选择工具、词表、扩展名及过滤条件,最后人工验证结果。
目录枚举会产生大量请求。仅对明确授权的系统执行,并根据服务器容量设置速率、线程和超时;遇到错误率上升或服务异常应立即降速。
工具怎么选
| 工具 | 更适合的场景 | 主要特点 |
|---|---|---|
| Gobuster | 快速目录、DNS 或虚拟主机枚举 | 参数直观,适合第一轮扫描 |
| ffuf | 路径、参数、Header 和请求体 Fuzz | 过滤与匹配能力强,位置灵活 |
| Feroxbuster | 递归发现深层目录 | 自动递归、链接提取和扩展名收集 |
| Dirsearch | 常见敏感路径和多扩展名检查 | 内置词表与扩展名处理方便 |
| Dirb | 简单环境或快速交叉验证 | 经典、轻量,行为容易理解 |
| Katana | 从页面和 JavaScript 提取真实端点 | 是爬虫,不依赖纯字典猜测 |
| CeWL | 生成与业务、组织相关的定制词表 | 利用站点文本提高命中率 |
没有一个工具可以覆盖所有场景。常见组合是“Katana 提取真实链接 + Gobuster 做第一轮路径枚举 + ffuf 验证参数或定制位置”,发现深层目录时再使用 Feroxbuster。
推荐流程
1. 建立响应基线
先确认协议、主机名、重定向和随机不存在路径的行为:
curl -skI https://app.example.test/
curl -sk -o /dev/null -w '%{http_code} %{size_download} %{url_effective}\n' \
https://app.example.test/this-path-should-not-exist-7f31
记录 200、301/302、401/403 和不存在页面的状态码与响应长度。某些站点对所有路径都返回 200,这就是“软 404”;不先测基线,会得到成千上万个假阳性。
2. 先爬取,再猜测
爬虫可以发现页面、脚本和 Source Map 中已经存在的路径:
katana -u https://app.example.test -d 3 -jc -kf all -o katana.txt
同时检查 robots.txt 与静态资源、HTML 注释、JavaScript 路由和 API 基础路径。这些真实线索通常比盲目扩大字典更有效。
3. 用小词表进行第一轮枚举
gobuster dir -u https://app.example.test/ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-t 10 -x php,txt,html -o gobuster-common.txt
扩展名应来自技术栈证据,而不是无差别堆叠:PHP 站点关注 php、inc、bak,Java 应用关注 jsp、action,静态站点则优先检查 JavaScript、JSON、Source Map 和配置文件。
4. 使用过滤器处理软 404
ffuf 可以按状态码、响应长度、单词数或行数过滤:
ffuf -u https://app.example.test/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt \
-mc all -fc 404 -fs 1234 -rate 20 -of json -o ffuf.json
-fs 1234 只是示例,应替换为基线测得的响应长度。动态页面长度波动时,可以组合单词数、行数和正文特征判断,不能只看状态码。
5. 对有效目录递归和定制词表
当 /admin/、/api/ 或 /assets/ 确认存在后,再限定递归范围:
feroxbuster -u https://app.example.test/admin/ \
-w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt \
-t 10 -d 2 --rate-limit 20 -o ferox-admin.txt
站点带有明显业务术语、人名或项目名时,使用 CeWL 生成定制词表,与常用前后缀组合,比直接上超大字典更节省请求。
6. 不要遗漏虚拟主机
访问 IP 看到的默认站点不一定是目标应用。先从 DNS、证书 SAN 和页面跳转收集域名;详见 TLS 虚拟主机发现。确认基线后,可把 FUZZ 放进 Host 头:
ffuf -u https://192.0.2.10/ -H 'Host: FUZZ.example.test' \
-w subdomains.txt -mc all -fs 0 -rate 20
过滤条件必须以随机 Host 的响应为基线。解析到新主机名后,先添加授权范围内的 DNS/hosts 映射,再对该虚拟主机单独建立目录扫描基线。
结果如何判断
| 现象 | 可能含义 | 下一步 |
|---|---|---|
| 200 且内容独特 | 有效页面或接口 | 浏览器/curl 人工确认 |
| 301/302 | 目录规范化或登录跳转 | 跟随跳转并比较目标 |
| 401 | 资源存在且需要认证 | 记录认证类型,不做未授权爆破 |
| 403 | 路径可能存在或被统一拦截 | 与随机路径、大小和 Header 对比 |
| 相同长度的大量 200 | 软 404 或 WAF 模板 | 按长度/单词数过滤并降速 |
| 429/5xx 增多 | 限速或服务压力 | 暂停、降低并发和请求速率 |
每条高价值结果都应保存 URL、状态码、长度、发现来源、验证命令和时间。工具输出是候选线索,只有人工复核后才能进入漏洞验证阶段。
常见误区
- 忽略结尾
/、大小写、URL 编码或重写规则造成的差异。 - 用一个超大字典替代技术栈分析和页面爬取。
- 看到 403 就尝试大量绕过,未先确认随机路径是否同样返回 403。
- 多个工具使用相同字典重复扫描,却没有补充参数、Header、虚拟主机或业务词表。
- 没有保存 JSON/文本结果,导致后续无法去重和复测。
发现服务之前可先按 端口扫描流程 建立服务地图;完成 Web 入口验证并获得低权限账户后,可进入 Linux 提权检查清单。