干了这么多年Web安全评估,我敢说目录扫描算得上是出活率最高、性价比最离谱的一项测试手段。很多看似固若金汤的系统,最后突破口往往不是0day,也不是什么高级攻击链,而是Web根目录下某个不该存在的.bak文件、一套没加访问控制的测试接口,或者干脆是暴露在外的.git源码仓库。今天这篇就把目录扫描这摊子事彻底聊透,重点围绕dirsearch这个工具、字典爆破的核心逻辑,以及敏感目录泄露挖掘的完整思路来展开。不管是刚入门的安全新人,还是需要给自己的站点做自查的运维开发,都能从里面拿到可以直接用的东西。
1. 敏感目录泄露的根源与风险
1.1 泄露是从哪儿来的
先说一个我自己的判断:绝大多数敏感目录泄露,根本原因就四个字——便利优先。开发阶段图省事,把后台路径命名为/admin、/manage这种一眼就能猜到的单词;测试阶段为了联调方便,把/api_debug、/swagger-ui.html这种调试入口直接留在生产环境;运维阶段做备份,习惯性地在站点根目录打一个backup.zip、site_2024.tar.gz。这些操作在当时看来都是“临时搞一下”,结果“临时”就变成了“永久”。
这类问题有多普遍?我在授权渗透测试里,十次有六七次都能在目标站点扫出至少一个敏感路径。有的直接是后台登录页,有的是一份包含数据库连接信息的配置文件,最夸张的一次是直接把整个网站的源码包挂在根目录下,连压缩密码都没设。所以别觉得这种漏洞“低级”就可以忽视,在实际攻防里,它往往是撕开防线的第一道口子。
1.2 泄露会造成什么后果
敏感目录泄露的威胁等级,要看泄露的是什么类型的文件。我们把风险从低到高排一下:
- 低危:一些无关紧要的静态资源目录,比如
/images、/css,这类目录泄露本身不致命,但会帮助攻击者了解站点结构,为后续精准攻击提供信息支撑。 - 中危:后台管理入口、测试页面、旧的接口文档,比如
/admin、/test.php、/api_doc.html。攻击者拿到这些路径后,等于省去了大半的信息收集工作,可以直接对登录接口和业务接口发起攻击。 - 高危:配置文件、备份文件、源码包、版本控制目录,比如
/.git/、/.svn/、/config.php.bak、/web.zip。一旦这些被下载下来,数据库账号密码、加密密钥、业务逻辑、历史漏洞就全部暴露了,性质等同于源代码级泄露。 - 致命:云凭据文件、内网代理配置、运维平台入口,比如
/aws_credentials、/jenkins、/kibana。这类信息可能直接打通从外网到内网的跳板,属于严重安全事件。
需要注意的是,目录扫描不是为了“找出一个后台地址然后尝试登录”,而是为了评估攻击者在不接触任何内部信息的情况下,通过公开可访问的路径能拼凑出多大的攻击面。理解了这一点,你就知道为什么字典选型和扫描策略这么重要了。
2. dirsearch工具能力深度拆解
2.1 为什么是dirsearch
市面上做目录扫描的工具不少,常见的有御剑、dirb、gobuster、wfuzz,以及Burp Suite里自带的Intruder。我为什么主力推荐dirsearch?三个原因:第一,它是纯Python实现的,跨平台能力好,Linux、macOS、Windows都能跑,依赖也简单;第二,它的功能设计非常贴近实战,比如递归扫描、指定扩展名、指定HTTP方法、多线程、请求速率控制,基本上你想要的它都有;第三,它的输出格式丰富,文本、JSON都能导,方便后续分析。
拿御剑这类Windows图形化工具来对比,御剑胜在“开箱即用”,双击就能扫,但它的问题是线程和字典耦合得太深,自定义能力弱,而且很久没更新了。dirsearch虽然需要敲命令,但熟练之后效率远高于图形化工具,尤其是在批量测试、结果自动化处理这些场景下,命令行工具的优势是碾压级的。
2.2 核心参数详解和常用组合
dirsearch的常用参数可以参考这个表格:
| 参数 | 作用 | 实战建议 |
|---|---|---|
-u/--url | 指定目标URL | 可以多次使用,批量扫描多个目标 |
-w/--wordlist | 指定字典文件 | 默认用自带字典,实战建议换成自定义字典 |
-e/--extensions | 附加扩展名 | 常用php,asp,aspx,jsp,txt,bak,zip |
-r/--recursive | 递归扫描子目录 | 强烈建议开启,但要配合--max-recursion-depth限制层数 |
-t/--threads | 线程数 | 内网目标可以开到20,外网建议10以内 |
-x/--exclude-status | 排除状态码 | 默认已排除404,建议再加403、400 |
--random-agent | 随机User-Agent | 推荐开启,避免被简单WAF识别 |
--batch | 批量模式 | 扫描时遇到提示自动选择默认项,无人值守必备 |
-o/--format | 输出结果 | 建议-o result.json --format json,方便后续分析 |
基础用法长这样:
dirsearch -u https://target.com -e php,txt,bak,zip -t 10 --random-agent --batch这行命令的意思是用10个线程扫描目标,附加php、txt、bak、zip这四种扩展名,用随机UA防止简单拦截,遇到交互提示自动选默认项。扫描结果默认会保存到reports/目录下。
我自己的习惯是再加两个参数:
dirsearch -u https://target.com -e php,txt,bak,zip,json,xml -t 10 -r --max-recursion-depth=2 --random-agent --batch -o target_scan.json --format json-r开启递归后,工具扫出来的每个目录都会往下继续挖,适合做大面积巡检;但递归层数一定要限制,否则遇到无限递归的目录结构会跑到天荒地老。--max-recursion-depth=2表示只往下追两层,这个深度在大多数场景下已经够用了。
2.3 常见安装问题:unable to locate package dirsearch
在Kali或者Debian系系统上,你大概率会遇到下面这个报错:
sudo apt install dirsearch Reading package lists... Done E: Unable to locate package dirsearch这种报错的原因是该系统版本的软件源里根本没有dirsearch这个包。Kali的软件源需要滚动更新,Debian稳定版更是往往不会收录这类工具。解决办法有两个:
第一个办法,直接从GitHub拉取源码运行,这也是我最推荐的方式:
git clone https://github.com/AstroWen/star_destroyer.git cd dirsearch pip3 install -r requirements.txt python3 dirsearch.py -u https://target.com注意不同时期dirsearch的仓库地址可能有变化,直接去GitHub搜索dirsearch找Star数最高的那个就可以。这类工具的更新频率很高,源码方式能保证你拿到的是最新版本,比你用apt装老版本靠谱得多。
第二个办法,如果你一定要用包管理器安装,先更新索引再看包源里有没有:
sudo apt update apt search dirsearch如果apt search也找不到,就换回源码方式。另外,如果提示ModuleNotFoundError: No module named 'requests'之类的依赖缺失,执行pip3 install -r requirements.txt就能解决。
3. 字典爆破的原理与字典选型
3.1 字典爆破为什么是目录扫描的灵魂
dirsearch本身只是一个“发请求、看响应、做判断”的引擎,真正决定扫描效果好坏的是你喂给它的字典。字典爆破的本质是枚举:把字典里的每一个路径拼到目标URL后面发请求,根据HTTP状态码和响应内容判断这个路径是否存在。
用个比方来解释,dirsearch就像一把精密的钥匙,字典就是钥匙上一个个齿痕;钥匙的材质再好,如果齿痕对不上锁芯,也一样打不开门。所以目录扫描不是“跑了工具就完事”,而是要花心思去研究目标、积累字典、构造字典。我在项目里经常看到有人拿着默认字典无脑跑一圈,然后报告里写“未发现敏感路径”,实际上换个合适的字典,分分钟就能扫出东西来。
3.2 字典来源与精选路径
字典可以从三个渠道获得:
- 工具自带的字典:
dirsearch在db/目录下自带了一些字典,比如wordlist.txt、common.txt,适合做快速初检,覆盖面一般。 - 社区维护的大型字典:比如SecLists项目的
Discovery/Web-Content目录,里面的raft-large-directories.txt、common.txt、big.txt都是好东西。SecLists的优势在于分类清晰、样本量大,几万条路径词条基本覆盖了常见命名习惯。 - 自己沉淀的字典:这个才是拉开差距的地方。我会把平时测试中命中率高的路径单独存到一个文件里,定期整理。比如各种备份文件命名规则、常见后台路径变体(
admin、houtai、manage、management、system)、开发阶段遗留的调试接口等。
我个人经常在字典里用到的路径词条,按用途分类:
| 分类 | 典型路径/文件名 |
|---|---|
| 后台入口 | admin, manage, manager, console, dashboard, systems, backend, houtai |
| 备份文件 | web.rar, web.zip, site.rar, site.tar.gz, backup.zip, www.zip, 域名+.zip |
| 配置文件 | .env, config.php, config.php.bak, setting.ini, web.config, application.yml |
| 版本控制 | .git, .git/config, .svn, .svn/entries, .hg |
| 调试接口 | api, api_debug, test, phpinfo.php, swagger-ui.html, debug, trace |
| 通用目录 | upload, uploads, file, files, data, database, download, tmp, temp, old, test, demo |
3.3 扩展名的组合策略
光有路径还不够,扩展名组合是一门学问。同一个路径词条,比如config,可以衍生出config.php、config.php.bak、config.txt、config.zip、config.xml等等。dirsearch的-e参数允许你指定多个扩展名,它的底层逻辑是:对字典里的每个路径词条分别追加这些扩展名去请求。
那扩展名怎么选?一个基本判断标准是:看目标站点的技术栈。如果目标响应头里的X-Powered-By显示PHP,那重点测php和phtml;如果从登录页或URL后缀能看出是.NET,那重点测aspx和asp;如果是Java系(Spring Boot等),那重点测json、action和do。通用的兜底扩展名组合是txt,bak,zip,json,xml——这些跟语言无关,配置文件、备份文件最常见的格式就是这些。
这里有个我踩过坑的经验:不要一上来就挂一大堆扩展名。扩展名越多,请求数量越多,扫描时间成倍增加,同时也更容易触发目标的频率限制。合理做法是先做一轮“无扩展名+基础扩展名”(比如只加php),快速把目录结构摸清楚,再针对可疑目标做第二轮带更多扩展名的精细化扫描。
4. 实战:敏感目录泄露挖掘的完整操作流程
4.1 扫描前的授权确认
在进入正题之前必须先把红线讲清楚:目录扫描只允许在你有明确授权的目标上开展,比如你自己公司的系统、客户委托的渗透测试项目、或者你搭建的本地靶场。未经授权扫描他人系统,不管出于什么动机,都是违规甚至涉嫌违法的高风险行为。下面整个流程都默认你已经有合法授权了。
4.2 第一步:信息收集是扫描的启动器
不少人的习惯是拿到一个URL就直接开扫,其实这不是最优做法。花一两分钟做信息收集,能让后续扫描精准得多。具体看这几个信息:
- 指纹识别:目标是什么Web容器(Nginx/Apache/IIS)?什么后端语言(PHP/Java/ASP.NET)?什么框架?这些决定了你选什么扩展名、重点看什么路径。工具可用
whatweb、Wappalyzer,也可以直接看响应头。 - 子域名收集:如果授权范围是整个域名,先把子域名枚举出来,重点测那些“不像生产环境”的子域,比如
test.*、dev.*、api.*。很多团队对主站管控严格,却忽略了测试子域的安全配置,那里往往藏着惊喜。 - 端口服务确认:目录扫描的本质是Web服务的路径枚举,但如果目标还有别的端口开放着Web服务(比如8080的管理台、9090的监控面板),这些也不要放过。用
nmap扫一遍全端口,把Web服务都列出来依次扫。
4.3 第二步:三种扫描策略与命令模板
信息收集做完,我会按下面的策略分三轮扫描,目的不同,参数配置也不同:
4.3.1 第一轮:快速广度扫描
目的是快速了解目标的整体目录结构和大致攻击面,用中等规模的通用字典,线程适中,扩展名挂常用几个。
dirsearch -u https://target.com -w /usr/share/seclists/Discovery/Web-Content/common.txt -e php,txt,zip,tar.gz -t 15 --random-agent --batch -o scan_round1.json --format json这一轮通常几分钟就能跑完。扫完先不急着深挖,重点看有没有.git、.env、backup、admin这类高价值路径,有的话优先验证。
4.3.2 第二轮:深度递归扫描
第一轮扫出来的目录,比如/api/、/uploads/、/includes/,每个都可能还有自己的子目录和文件。这一轮用递归模式往下挖,同时调大字典规模。
dirsearch -u https://target.com/api -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt -e php,json,xml,txt,bak -t 10 -r --max-recursion-depth=2 --random-agent --batch -o scan_round2.json --format json递归扫描很吃时间,所以我只会挑第一轮里状态码为200、301(且不是死循环)或者判断出“确实存在目录”的目标来做第二轮,不会对整个域名无脑递归。
4.3.3 第三轮:定向专项爆破
前面两轮是“广撒网”,第三轮是“定点清除”。针对明确的目标,比如已知某个后台路径,围绕它做变体枚举:
dirsearch -u https://target.com -w /path/to/custom-admin-dict.txt -e php,html,bak,zip -t 8 --random-agent --batch --user-agent "Mozilla/5.0" -o scan_round3.json --format json这轮也可以用Burp Suite的Intruder来做,好处是能看到完整的请求响应包,方便观察服务器处理差异。我的习惯是dirsearch负责“发现”,Burp负责“深挖”和“验证”,两者配合使用。
4.4 结果解析和验证
扫描结果出来之后,不能只看状态码就下结论。我的处理原则是“三个看”:
- 看状态码:200是存在且可访问,301是存在且跳转,401/403是存在但被限制访问(注意:403也可能是WAF统一拦截不存在路径导致的,需再验证),500是服务器错误(有的服务器对不存在路径也会返回500,要结合上下文判断)。
- 看响应体大小:
dirsearch输出的结果里包含响应体长度。当一个路径返回200但是响应体和首页一模一样时,多半是前端路由的兜底逻辑,并不是真实目录。反之如果响应体长度和其他路径明显不同,即使状态码是404也要注意,可能存在假404的情况。 - 看响应内容:最靠谱的验证方式是把返回的页面内容拉下来看一眼。我一般会写个小脚本,或者直接在浏览器里访问那个路径,看页面上有没有关键词、有没有报错信息、有没有跳转动作。
验证之后,把确认有问题的路径按风险等级记录到报告里,附上截图和访问方式,这一步就完成了。
5. 常见问题与排查技巧实录
5.1 识别“假404”和“泛解析”
实站里经常遇到一种情况:随便访问一个不存在的路径,服务器也返回200或者200状态码+一段固定页面。这种叫泛解析/优雅降级,尤其在前后端分离的SPA站点里特别常见——所有路径都会被index.html接管,后端响应200,前端再用路由去匹配。
如果目标有这种情况,单纯看状态码基本废了。我的应对手段是两招:第一,看响应体大小,如果扫出来的十几个路径响应体长度全都相同,极其可疑;第二,换工具或者写脚本,发送两种请求,一种是不存在的随机路径,一种是字典里的路径,对比响应的差异(比如标题、关键字、响应头)。如果两者毫无差异,那扫出来的路径大概率是无效的。dirsearch有一个--exclude-status参数,但对付这类场景还不够,得靠响应体判断。
5.2 扫描速度与服务稳定的平衡
线程开太高容易把目标打挂或者被WAF封IP,开太低又等得人心急。我踩过的坑是:有个目标用的是老旧的Windows Server+IIS,我把线程开到30,结果目标直接服务不可用,整个测试窗口被浪费了大半天。后来我就定了个规矩:外网目标线程控制在10以内,内网目标最多20;同时加一个--delay参数,在请求之间插入间隔,比如--delay=0.3表示每个请求间隔300毫秒。这样既能维持扫描强度,又不容易引起服务异常或触发硬性拦截。
如果目标有WAF,或者目标比较重要,我会把扫描时间拉长、频率降低,用“慢工出细活”的方式绕过速率检测。配合--random-agent使用,效果更好。
5.3 结果输出与后续联动
dirsearch输出成JSON格式后,我通常会直接用jq做二次过滤,比如只保留返回200和301的路径:
jq '[.results[] | select(.status == 200 or .status == 301)]' scan_round1.json这样能快速把有效路径筛出来,再结合Burp Suite做爆破或者人工访问验证。另外dirsearch还支持--csv格式,方便直接用Excel打开做表格。测试报告需要附截图,但截图证据一般来自后续浏览器的访问验证。
5.4 一个被我反复使用的组合思路
最后分享一个小组合,能很大程度提高敏感目录挖掘的完整度。我的标准流程是:
- 第一步,
nmap+whatweb把目标的技术栈和端口摸清楚; - 第二步,
dirsearch快速广扫,拿到候选路径; - 第三步,对高价值路径换大字典再定向爆破;
- 第四步,用Burp Suite的Intruder对可疑路径做扩展名和参数枚举;
- 第五步,把发现的所有路径全访问一遍,把页面内容存档留证。
这套流程看起来很笨,但非常管用。自动化工具负责把“可能性”筛出来,人工负责把“确定性”验证出来,两者缺一不可。
6. 一些关于字典和工具的心得
目录扫描这行的入门门槛很低,装个工具跑一下谁都会,但真正拉开差距的是对“路径命名规律”的理解和日常积累。比如中文团队习惯命名houtai,英文团队习惯backend,老项目可能有test、demo这种路径,新项目可能用gateway、auth这类微服务风格的路径。这些东西不会出现在默认字典里,只能靠日常测试一点点记下来。
我自己会把每次测试中高命中的路径、文件后缀、目录命名习惯都整理到一个笔记里,隔几个月做一次分类和去重。时间长了,这套自定义字典的命中率远超任何通用的公开字典。有时候甚至不用扫描,光凭经验猜就能直接猜到常见后台路径和备份文件名的组合。
还有一点想说:目录扫描只是敏感信息发现的第一步,扫到路径之后一定要跟进验证和利用——确认它是不是真的泄露了敏感内容、泄露的内容能否被进一步利用、影响范围有多大。只扫不验,测试报告就是一堆“疑似”和“可能”,价值大打折扣。
如果你打算长期做这块,我建议把dirsearch的源码翻一翻,看看它发请求、解析响应、去重、递归的实现方式。理解了工具内部逻辑之后,遇到奇怪的目标系统时,你才不会一头雾水,也能更灵活地组合参数去适配不同场景。这套东西看起来是“体力活”,但底层拼的还是思路和经验。