简介:目录扫描工具dirsearch-master是一份基于Python开发的Web目录/文件发现工具资源,面向渗透测试人员、安全运维及Web安全学习者,用于自动化探测网站敏感目录、隐藏文件与潜在漏洞入口。该工具支持HTTP、HTTPS及Socket等多协议扫描,内置多线程与递归目录挖掘,并可搭配自定义字典提升命中率,扫描结果支持TXT、XML、JSON等格式导出,整体实用性较强。压缩包为RAR格式,大小约933KB,包含217个文件,涵盖50个Python源码、92个编译后的pyc字节码、57个字典与说明类txt、7个Markdown文档,以及配置文件(yml/conf/cfg)、Dockerfile、HTML报告模板等,结构清晰,轻量易部署。目前已吸引2182人学习下载。通过这份资源,读者可获得可直接运行的目录扫描工具、自定义字典示例、容器化构建文件和报告模板,既适合安全测试时快速布署,也便于阅读源码、理解多线程扫描与递归探测的实现思路。 做Web安全评估的人,对dirsearch这个工具应该都不陌生。它是用Python写的开源目录扫描工具,核心功能很简单:根据字典批量枚举目标站点的目录和文件名。目录扫描这件事听起来基础,实际价值却非常高,因为大量安全问题都藏在那些没有被页面公开过的路径里——后台入口、备份压缩包、旧版本接口、残留的配置文件,随便命中一个,后续测试都会轻松不少。这篇文章准备把dirsearch从原理到实操完整过一遍,包括怎么安装、常用参数怎么配、字典怎么选、结果怎么判断,以及我用它时踩过的坑。刚接触目录扫描的新手可以把它当入门指南,已经用过一阵子的朋友,重点看看字典和误报排查这两部分,应该也有收获。
先说个前提:目录扫描会给目标服务器制造大量请求,必须只在你自己拥有权限或者明确获得授权的系统上使用,练习最好从本地靶场开始。记住了这一点,后面说什么都可以放心折腾。
1. 目录扫描到底在扫什么?先把原理搞清楚
1.1 一次HTTP请求能暴露什么
目录扫描的原理并不复杂,本质上就是“枚举”:你准备一份候选名字列表,工具拿着这份列表挨个向服务器发HTTP请求,然后根据返回的状态码、响应头和响应长度来判断“这个路径是否存在”。
举一个比较直白的类比:你站在一栋办公楼外面,不知道哪些房间开着门,于是就一间一间去敲门。有应答的房间,你就记下来;没人应的,就跳过。目录扫描工具干的就是这个“敲门”的活儿,只不过它敲的是URL路径,比如/admin、/backup、/config.php。
dirsearch会为字典里的每个词条构造完整URL,并尝试不同的扩展名组合。比如字典里有一条backup,你设置了-e zip,sql,那它就会尝试/backup、/backup.zip、/backup.sql。服务器返回404,说明这个路径大概率不存在;返回200、301或403,就需要重点留意了。
1.2 为什么目录扫描是Web测试的必修项
拿到一个目标之后,你通常只知道一个主页URL,这时候最迷茫的就是“从哪下手”。爬虫能把页面上能看到的链接抓下来,但很多敏感路径并不会出现在页面里,它们只能靠猜,也就是枚举。
目录扫描能帮你快速建立目标站点的结构图:哪里是后台、哪里有上传目录、哪里挂了旧版本接口、哪个路径返回了异常响应。这些信息是整个测试流程的出发点,没有这一步,后面很多工作都像无头苍蝇。
我见过不少新人花了很多精力去研究漏洞利用,结果第一步信息收集就没做好,漏掉了一个显眼的/admin。目录扫描虽然是个“笨办法”,但它把手工不可能完成的枚举工作压缩到了几十秒内,这也是它至今仍然是安全测试工具箱里常备工具的原因。
1.3 dirsearch与“漏洞扫描器”的区别
有人会问:既然AWVS、Nessus这些漏洞扫描器也能扫目录,为什么还要单独用dirsearch?这里面的定位差异很关键。
漏洞扫描器更像一个“体检医生”,它会用已知漏洞库去套目标,判断有没有已知的CVE、错误配置之类的问题。它的目录发现功能通常是顺带的,路径样本量少,也不容易定制。而dirsearch是专职干路径发现这一件事的,它配置灵活、字典可控、速度快,可以很方便地接入你自己的日常工作流。
实际测试中两者是互补关系。先用dirsearch把目录站点的“骨架”摸出来,再根据需要上漏洞扫描器做定向检测,比直接拿重型扫描器乱打要高效得多,噪音也小得多。
2. 环境准备与安装
2.1 安装方式与版本选择
dirsearch是开源项目,源码托管在GitHub上。你可以在dirsearch/dirsearch仓库里直接git clone,也可以下载zip压缩包。下载zip解压之后,文件夹名字通常就是dirsearch-master——很多人看到这个后缀会疑惑,其实那只是GitHub默认的打包命名方式,不用多想,直接进目录用就行。
安装命令很简单:
git clone https://github.com/dirsearch/dirsearch.git cd dirsearch python3 dirsearch.py --version如果运行时提示缺少依赖,先执行:
pip install -r requirements.txtdirsearch基于Python 3.x,依赖很少,主要就是requests这类常用库,基本不会遇到环境上的坑。Kali Linux里通常自带这个工具,但自带的版本可能比较旧,我还是推荐从仓库拉最新代码,新版本在递归策略、输出格式和并发控制上都有明显改进。
2.2 用一句话验证工具可用性
安装完先别急着上生产目标,拿本地靶场或测试站点跑一条最简单的命令验证一下:
python3 dirsearch.py -u http://your-target -e php,html正常的话,终端会列出扫描进度,跑完后输出一份路径列表,包含状态码、响应大小和路径。看到这个界面,就说明工具已经能用了。我第一次用的时候直接对着一个不熟悉的线上站点开扫,结果把人家日志刷爆,印象极其深刻,从那以后就老老实实先在靶场练手。
3. 命令行实操:常用参数与扫描姿势
3.1 基础扫描命令
dirsearch最常用的几个参数其实一只手数得过来:
python3 dirsearch.py -u https://example.com -e php,html,txt-u指定目标URL,-e指定要尝试的扩展名。为什么扩展名这么重要?因为字典里的词条大多不带后缀,它只是基础路径名。如果你不告诉工具该猜哪些文件类型,那它就只会扫到纯目录和没有扩展名的文件,会漏掉大量.php、.bak、.zip这类关键目标。
不过加了扩展名之后,扫描量会成倍增加。比如字典里有10000条记录,设置三个扩展名,实际请求量就是40000左右。所以扩展名不是越多越好,要根据目标技术栈来定。目标首页是PHP写的,那就优先-e php;看到下载链接里有zip包,可以补一个zip。
3.2 过滤和输出:扫描之外的细节
扫描结果中噪音太多,最常用的过滤手段有两个。一个是用-x排除状态码,比如:
python3 dirsearch.py -u https://example.com -e php -x 404,400另一个是按响应体大小过滤,使用--min-response-size和--max-response-size。有些站点对不存在的路径会返回一个空白页面,长度几乎是固定的,这时候设置一个最小长度阈值,就能把一大部分假阳性过滤掉。
输出参数也值得花点时间设置:
python3 dirsearch.py -u https://example.com -e php -o result.json --format=json-o指定结果文件,--format=json让结果变成结构化数据,方便后续用脚本处理。如果你只是临时看一眼,默认的终端输出就够了;但如果扫描目标多、结果量大,一定要养成导出结果的习惯,不然后面想回溯分析会很痛苦。
这里有一个我踩过的坑:别在扫描一开始就把403排除掉。403经常表示“路径存在,但禁止访问”,对后台目录、受保护接口来说,这本身就是一条重要情报。你可以在清洗结果的时候单独筛掉它,但不要从一开始就见不到它。
3.3 递归扫描:让发现更彻底
只扫一层目录很多时候不够。你发现了一个/admin,但这个目录下面还有assets、upload这些子目录,这些子目录里可能还有更多文件。这时候就要开递归扫描:
python3 dirsearch.py -u https://example.com -e php -r -R 2-r开启递归,-R限制最大递归深度。这里的-R 2意思是扫描到第二级子目录为止。
递归扫描很强大,但也容易失控。目录层级深的目标,请求量可能指数级增长,扫到后面既费时间又容易触发防护。我个人的习惯是:第一遍先不递归,拿到结果做一轮过滤和人工判断,挑出真正有价值的目录之后再针对这些目录单独递归。别指望一次扫描解决所有问题,分阶段进行反而更可控。
3.4 一个比较完整的扫描命令
把上面这些串起来,一条比较完整的命令长这样:
python3 dirsearch.py -u https://example.com \ -w db/dicc.txt \ -e php,bak,zip,html \ -t 20 \ -r -R 3 \ --random-agent \ --exclude-status 404 \ -o report.json --format=json拆开看:-w指定自定义字典,-t 20开20个线程,-r -R 3做三层递归,--random-agent给每个请求随机User-Agent,降低被WAF特征拦截的概率,--exclude-status 404把404排除出结果。
线程数这个参数特别需要根据场景调整。本地靶场我经常开到50甚至100,速度快到飞起;但线上真实目标我一般从10开始,观察一下服务器的响应情况,再决定要不要加。有些站点并发稍微一高就直接断连,这时候调低线程、加一点延时,反而效率更高。
4. 字典选型与优化
4.1 默认字典的结构与定位
dirsearch的db目录下自带了一批字典,这是很多人容易忽略的部分。里面有通用字典dicc.txt、dirs.txt,也有按语言和场景分类的php.txt、asp.txt、backup.txt、admin.txt等,还有精简版的small.txt。
我的建议是:拿到工具之后先ls db看一眼,翻翻里面的内容结构。你不需要背下每个文件名,但至少要知道自己有哪几张牌可打。绝大多数场景,默认字典已经覆盖了大路货路径,比如admin、login、uploads、backup,真正要补的是跟目标框架相关的私有路径。
4.2 靠字典吃饭:什么项目用什么字典
目录扫描的覆盖率七成取决于字典质量,工具本身只是负责“问话”的,问什么词条才是决定胜负的环节。
通用目标我一般用dicc.txt,配合-e php,html,txt扩展名扫描。如果确定目标是PHP站点,优先用php.txt或者把通用字典加上-e php;做备份文件专项排查时,选backup.txt,扩展名加上zip,sql,old,swp,专门找.bak、.sql、.swp这类残留文件。
还有一种常见场景是找管理后台,这时可以直接上admin.txt。很多后台路径是有规律可循的,比如/admin、/administrator、/manage、/system,用专用字典比通用字典命中率高得多。
如果你是针对某个CMS做测试,最好的字典来源是那套CMS自己的目录结构和默认文件名。把安装包里常见的路径、上传目录、配置文件路径整理出来,做成一个专属字典,命中率比什么通用字典都强。
4.3 自定义字典的通用思路
自定义字典没有什么高深技巧,核心就是积累和归纳。平时测试遇到真实存在的路径,随手记录;看目标响应头里的Server字段,判断是什么语言和中间件;翻页面前端代码,找出接口路径和JS文件名,这些都能沉淀成字典条目。
有几个细节容易忽略。第一是大小写,Linux上的nginx、apache区分大小写,/Admin和/admin可能是两个完全不同的路径,Windows环境的IIS则不区分,所以字典里什么时候大小写都留一个变体,需要结合目标环境判断。第二是备份文件的命名习惯,除了常规的xxx.bak、xxx.zip,还有xxx~、xxx.swp、xxx.old这些,一个都不能漏。第三是字典一定要去重,用sort -u处理一下,能省下很多重复请求。
sort -u custom.txt -o custom.txt字典不是越大越好。一个全是噪音的大字典,既拖慢扫描速度,又淹没真正的命中结果。小而精的字典,配合合理的扩展名,往往比一味堆词条效果更好。
5. 结果解读与误报排查
5.1 状态码的“人话”翻译
扫描结果出来以后,第一件事不是急着高兴,而是先读懂每个状态码。我把常见状态码的含义整理了一张表,不管用dirsearch还是其他扫描器,这份判断逻辑都通用。
| 状态码 | 大致含义 | 需要关注吗 |
|---|---|---|
| 200 | 正常返回,路径很可能存在 | 重点关注 |
| 301/302 | 存在并跳转,需要看Location | 重点关注 |
| 401/403 | 存在但禁止访问,或WAF拦截 | 重点关注 |
| 404 | 默认路径不存在 | 忽略 |
| 500/502 | 服务端异常 | 重点留意 |
这里最容易踩的坑是“自定义404”。有些站点会把所有不存在的路径统一返回一个带200状态码的模板页面,这时候扫描结果里会冒出一堆假的200。判断方法很简单:手动访问一个完全不存在的随机路径,比如/asdf10000,看它返回什么状态码。如果它也返回200,那说明这个站点存在自定义404,所有200结果都不能直接采信。
5.2 响应长度和页面特征:高频误报来源
dirsearch的扫描结果里,每个路径后面会跟着响应长度。这个数值是判断误报的重要线索。
有一种典型情况:前后端分离站点的路由由前端接管,不管请求什么路径,服务端都返回同一个index.html,长度完全一样。这时候你会看到一大排长度相同的200,它们像是命中,其实全是同一个入口页面。遇到这种情况,不要急着兴奋,先挑几个路径访问一下,看看页面内容是不是完全相同。
其他高发误报包括:重定向到登录页的未授权接口、CDN层面的默认响应、全局错误提示页。这些结果都有一个共同特征:不同路径返回的响应内容和长度非常接近。所以我在实际使用中会把状态码当第一道筛子,响应长度当第二道筛子,两边一对比,很多假阳性就现形了。
5.3 手动验证三步法
工具扫出来的结果只能算“候选名单”,手动验证才是盖章认定的过程。我的验证流程固定是三步。
第一步,先拿随机字符串路径做基准:
curl -s https://example.com/random-not-exist | wc -c记录基准路径的状态码和响应长度。第二步,对扫描命中的路径逐条请求:
curl -I https://example.com/backup.zip curl -s https://example.com/backup.zip | head -c 500第三步,把命中路径的响应和基准路径做对比。如果响应长度、页面标题、关键内容差异明显,比如出现了“Index Of”“login”或者文件下载头,那基本可以确认是真实命中。如果内容和基准路径几乎一样,只是状态码都是200,那大概率是假阳性。
这套流程看着慢,但能让你对目标站点的真实结构建立起准确认知。扫描器给的是线索,判断才是你的工作。
6. 常见问题与避坑经验
6.1 扫描速度、并发与封禁的平衡
目录扫描本质上就是高频请求,速度越快越接近一个“流量炸弹”。我见过一些人为了追求速度把线程直接拉到200,结果扫到一半目标开始疯狂断连,什么都拿不到,还把自己的出口地址暴露了。这里最关键的是观察和调整。
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
| 扫描几十条后请求全部超时 | 并发过高,目标连接数被占满 | 调低-t,适当增大超时时间 |
| 结果里出现大量403 | 请求特征被WAF识别 | 启用--random-agent,降低线程,放慢节奏 |
| 某些路径访问正常但扫描不报 | 目标对无UA或异常UA请求统一拦截 | 用--header模拟真实浏览器请求头 |
我自己的习惯是先用-t 10试探目标响应情况,看几分钟内的结果是否稳定,再决定是否上调。靶场上可以放开手脚,线上目标一定要控制节奏。
6.2 递归扫描“爆炸”怎么办
递归扫描的逻辑是把发现的新目录继续作为起点往下扫,目录层级一深,请求量会指数上涨。尤其是那种自动生成多级目录的站点,扫一会儿就能跑出几十万请求,既慢又惹眼。
解决思路有两个。一是限制递归深度,-R 2或-R 3就够用,不要贪。二是先跑非递归扫描,把结果过滤一遍,挑中高价值目录单独递归,对小目录直接放弃。这样既不会漏太多,也不会让扫描时间失控。
6.3 动态页面与框架重定向导致的漏报
目录扫描有一个天然盲区:它只能枚举字典里有的路径,对于那些由规则动态生成的接口,比如/api/v1/order/12345、/index.php?r=user/info,字典枚举基本无效。还有一些SPA站点把所有路由交给前端,后端只提供API,这种场景下纯目录扫描能发现的东西非常有限。
针对这种情况,我会把扫描范围从“路径枚举”扩展到“资源收集”:翻页面源码里的JS文件,提取里面写死的接口路径;用浏览器的开发者工具观察实际发起的网络请求;把后台管理页面里出现过的操作路径记录下来。这些路径整理进字典后,再针对目标补扫一轮,效果会好很多。
6.4 与Burp、Nuclei等工具联动
dirsearch很少单打独斗,它的下游还有一堆工具等着接力。扫描完拿到候选URL列表后,你可以把结果整理成文本文件,逐个用浏览器或curl验证;也可以把有价值的URL导入Burp的流量记录里,继续做登录测试、越权验证等后续步骤;如果要批量检测已知漏洞,把过滤后的URL清单交给Nuclei这类工具,让它们跑一遍漏洞模板,能节省大量时间。
我自己的日常流程大概是:dirsearch先铺开扫一遍,结果导出JSON,筛选出有效路径,手动验证关键项,最后再交给其他工具做深入测试。筛选时重点保留200、403和301,这些路径最有故事。
最后再分享一点个人习惯。目录扫描这类工具,用熟了之后真正决定差距的不是参数记得多熟,而是字典积累和结果判断。我每次测试结束,都会把新发现的真实路径加进自己的自定义字典,几个月下来,这套字典对同类目标明显比默认字典更“懂行”。工具给你的是速度和便利,真正值钱的还是你那套经过验证的方法论。
本文还有配套的精品资源,点击获取