目录扫描这东西做Web安全的人几乎每天都要接触。新手入门碰到的第一个扫描工具大概率就是dirsearch它不像那些重型漏扫那么复杂不需要装Agent也不用注册账号一条命令扔过去几百上千个路径呼啦一下全出来你根据状态码和响应长度就能判断出这个站点的目录结构和敏感文件。正因为太常见很多人反而把它当成“随便跑一跑”的执行工具忽略了它背后真正的价值——敏感目录泄露挖掘。这篇文章我打算结合自己这两年实际用下来的经验把dirsearch完整过一遍。从安装时最常见的一个报错unable to locate package dirsearch开始讲接着是字典爆破的机制和字典选型再往下是我自己用BurpSuite配合生成定向字典的方法最后重点聊聊敏感目录挖掘时最容易漏掉的那几类文件以及扫描完之后的筛选思路。内容主要面向正在入门Web安全方向渗透测试的朋友也适合那些已经会用dirsearch但一直没系统整理过“为什么这么用”的工程师。事先说明一点所有操作都建议在授权测试环境、CTF靶场或你自己搭的演练环境里进行。1. 先搞清楚目录扫描在实际测试里的定位1.1 为什么有漏洞扫描器还不够用很多人一开始会疑惑我现在用别的漏扫都能扫出SQL注入、XSS为什么还要单独拿dirsearch扫目录这是个好问题但方向反了。漏洞扫描器解决的是“这个URL上有什么漏洞”而目录扫描解决的是“这个站点还有哪些URL是我不知道的”。真实测试里目标范围往往大得吓人入口路径经常藏在某个冷门目录后面。你拿着漏扫开始跑但漏扫的爬虫只能顺着已知链接爬爬不到的地方它就无从下手。这时候漏扫引擎能覆盖的范围完全取决于你喂给它的入口URL。dirsearch解决的就是“把入口URL全量找出来”这个前置问题。先有目录后有漏洞这个顺序倒过来整个测试流程就会非常被动。我自己习惯把目录扫描放在信息收集阶段域名解析、指纹识别做完之后立刻开始跑拿到一批存活路径之后再带着这些路径去跑漏扫或者手工验证。这个流程走顺了后面每一步都省力。1.2 一万个路径和一百个有效结果之间差了什么同样拿dirsearch跑同一个目标新手和老手出来的结果差距可能很大。不是工具本身差距大而是用法差距大。新人常常不管三七二十一默认字典一把梭跑完看一堆200就觉得自己完事了。实际上几千几万条请求发出去八成以上的结果都要靠后续判断才能确认是不是“有效结果”真正有价值的那一百来个路径往往被淹没在302跳转、自造403和伪200页面里。差在什么地方差在三个方面字典是否贴合目标、线程和延迟参数是否合理、结果筛选是否做了排除和验证。这三件事做好了dirsearch的输出从“一堆URL”变成“一条清晰的攻击路径”效率直接翻倍。后文我会分别展开。1.3 授权边界与使用前提不是套话我见过不少文章把“仅供授权测试使用”当免责声明随手一贴好像就是一句废话。但目录扫描这东西本质上是在对目标做大规模路径探测如果你没有授权这种行为本身就非常敏感。更麻烦的是目录扫描经常会把目标站点的日志打满流量一大甚至会影响线上业务。所以在动手之前一定要确认三件事目标是你的项目授权范围内、你选择了合适的线程和延迟不会压垮业务、你用的字典内容不会去碰那些明显与业务无关的路径。这条虽然看起来是常识但我在实际过程中看到太多人因为漏掉“确认授权”这一步而翻车。放到最前面提醒比放在结尾当作免责声明管用得多。2. 安装时碰到 unable to locate package dirsearch 的全过程复盘2.1 报错原因发行版软件源里根本没有这个包很多人在Kali或Debian系环境里第一反应就是sudo apt install dirsearch然后终端无情地回了一句E: Unable to locate package dirsearch。第一次遇到这个报错时我也有点懵因为Kali里明明预装过其他工具怎么到dirsearch这儿就装不了后来查了一下发现原因很简单dirsearch并不在Debian/Ubuntu的官方软件源里它是个GitHub上活跃维护的开源项目版本更新非常频繁发行版维护者根本没有把它收进apt源。所以在apt的软件包列表里搜索不到这个东西自然也就无法用apt安装。Kali某些版本里虽然自带但那是Kali额外打包进去的不代表你在Ubuntu、Debian或WSL里也能直接装上。理解了这一点你就能明白单纯执行apt update是解决不了这个问题的因为软件源里压根没有这个包更新一百遍也没用。热词里能看到很多人因为这个问题卡住我在本地虚拟机复现过一次报错很稳定。踩过一次之后后面再遇到类似“某工具apt装不上”的情况我第一反应就会去官方GitHub仓库找安装说明而不是继续跟apt较劲。2.2 绕过软件源直接跑起来的三步操作正确方式是从源码安装。dirsearch是纯Python写的源码安装非常简单只要机器上有Python 3.8以上环境和git就行了。我在这台全新Ubuntu上完整操作过一遍命令如下# 1. 先保证基础环境就绪 sudo apt update sudo apt install -y git python3 python3-pip python3-venv # 2. 克隆官方仓库 git clone https://github.com/maurosoria/dirsearch.git cd dirsearch # 3. 安装Python依赖 python3 -m pip install -r requirements.txt # 4. 验证安装结果 python3 dirsearch.py --help如果你不想把pip的包装到系统环境下强烈建议在第三步之前先创建一个虚拟环境避免和你本机的其他Python项目发生依赖冲突。具体做法是python3 -m venv venv source venv/bin/activate pip install -r requirements.txt很多人在这一步省事直接用root跑短时间没什么问题但我在实际项目里因为系统Python环境被污染重启后好几个脚本都起不来非常折磨。所以现在一律推荐虚拟环境一劳永逸。如果你希望全局都能直接用dirsearch命令而不是每次进目录敲python3 dirsearch.py可以加一个软链接sudo ln -s $(pwd)/dirsearch.py /usr/local/bin/dirsearch做完这三步再执行dirsearch -u http://example.com就能正常出结果了。2.3 装完别急着扫先做两个“冒烟测试”工具装好之后不急着拿去扫描先花一分钟做两个小验证免得后面工具有问题还以为是目标的问题。第一个是版本验证。运行python3 dirsearch.py --version看看当前版本号。dirsearch的版本策略是几乎每个月都有小更新如果你看到远古版本号说明克隆的目录很旧可能是之前缓存过建议去GitHub重新拉取或执行git pull。第二个是本地靶场验证。随便在本地起一个临时HTTP服务放几个假目录和文件进去再用dirsearch扫一下确认它能正常发现并打印结果。比如mkdir -p /tmp/target_test/admin touch /tmp/target_test/admin/login.html cd /tmp/target_test python3 -m http.server 8080 # 另开终端 python3 dirsearch.py -u http://127.0.0.1:8080 -e html这一步能帮你排除掉权限问题、内容过滤器配置错误、依赖缺失等乱七八糟的因素。我在给别人做环境排查时发现很多“扫不出来”的案例其实都是工具本身没装好跟目标一点关系没有。3. 字典爆破的工作机制和字典选择策略3.1 dirsearch 发请求时到底做了什么很多用户用dirsearch是把它当成一个“黑盒按钮”——输入URL看到进度条跑完然后看结果。但如果你不理解它内部的工作方式遇到问题就很难定位。dirsearch的核心逻辑非常朴素。它维护一个字典默认在db/dict.txt每一行就是一个候选路径词条比如admin、backup、.git、config.php等等。扫描时工具把URL和每个词条拼接成一个完整的路径然后发起HTTP请求收集响应的状态码、响应长度、标题等信息再按照你设置的规则过滤输出。这里有个经常被忽略的机制扩展名参数。当你指定-e php,html时dirsearch对每个基础词条会生成多个候选路径比如基础词条是install就会依次尝试install.php、install.html。如果你不指定-e它只尝试字典里原本的写法。所以扫描动态站点时-e php几乎是必须的。我在一次测试中扫同一台服务器加不加-e php存活结果数量大概差了四倍因为目标有一堆PHP文件根本没在字典里以带后缀的形式出现过。另一个容易被忽略的机制是重定向跟随。dirsearch默认会根据301/302响应自动拼接跳转后的URL这能帮你发现以“/”结尾和没有“/”结尾的目录之间的真实路径关系。但同时这也带来一个问题某些302跳转会指向登录页让你误以为发现了一个有效路径。这个我放到后面的结果筛选部分细说。3.2 状态码与响应长度读结果的三个判断门先看一张我已经用了很久的状态码速查表它也是我筛选dirsearch结果时的第一道过滤逻辑状态码常见含义在目录扫描中的处理建议200正常访问优先验证重点分析301/302重定向跟着跳转看目标防止被登录页蒙蔽401需要认证大概率是敏感路径记录并验证403禁止访问很可能存在但不允许匿名访问敏感度很高404不存在默认被过滤不需要关注429/503限流或服务不可用说明并发太高需要降速重试我自己的经验是403在目录扫描里非常值钱。比如你扫到一个/server-status返回403说明Apache的state模块可能开着只是源IP不在允许列表里换个内网入口或配置了正确的Host头之后可能就能访问。401同理它在告诉你“后面有东西只是你没权限”。这两类结果宁多看不多看。第二道过滤是响应长度。dirsearch默认会显示每个结果的内容长度同一台服务器上所有404页面的大小通常都差不多比如都是20KB的自定义404模板。一旦某个返回200的响应长度明显不同于404页面的大小那它很可能是一个真实的文件或目录。反过来如果200响应长度和404完全一样那基本可以判定是自定义404行为也就是俗称的“假200”。第三道过滤是响应标题。扫描结果里每行有个TITLE字段比如titleApache2 Debian Default Page/title这能让你一眼看出某个路径是不是默认安装页面。我扫到路径时第一眼不是看状态码而是看标题。标题能直接告诉你这个路径后面托着的应用是什么比抠URL有意义多了。3.3 通用字典、定向字典、扩展名字典怎么搭配目录扫描的效果很大程度取决于用的字典dirsearch自带的字典已经不错但它面向的是海量Web应用的通用场景。我自己在测试时会把字典分成三类按阶段切换使用第一类是通用字典。开局的时候先用默认字典或主流的字典库过一遍目标是把常见路径和默认安装文件摸清楚。比如admin/、phpmyadmin/、.git/、backup.zip这种。这个阶段不求精细目的是获得站点的整体轮廓。第二类是扩展名字典。比如专门针对PHP的心跳字典专门针对Java或ASP.NET的路径字典。这类字典不看目录名看的是“这个中间件/框架常见的文件和路径后缀是什么”。比如Java站点的WEB-INF/web.xml、.class文件反编译路径Spring框架的actuator端点这些都是通用字典里不一定有、但真实存在的高危路径。第三类是定向字典。要根据目标的具体业务、域名、模块名来手工构造。这个我下一节详细讲。三类字典的顺序是从粗到细先用通用字典画地图再用扩展名字典捞深度内容最后用定向字典做定点爆破。这个顺序一旦搞反结果会很零散还容易在前期就触发目标的风控策略。4. 用BurpSuite配合生成定向爆破字典4.1 从抓包和站点结构里挖词根字典爆破不是让你瞎猜路径而是有一套“词根”的收集过程。所谓词根就是目标站点的特征词比如项目代号、产品名、开发人员昵称、公司电话后几位、英文简称、上线年份。这些词根从哪来我最常用的来源是BurpSuite的抓包记录。你正常浏览一遍目标站点Burp的HTTP History里会留存所有请求记录。打开Burp的Target标签页看看Site map甚至直接把主域名展开看实际调用了哪些接口、文件名是什么命名风格。比如说我发现目标所有的图片都放在/images/接口路径都是类似/api/v1/get_order_list的驼峰风格那我构造字典时就会把这种命名习惯带进去比如OrderList、get_order、OrderController等。另一个来源是目标站点的JS文件。几乎每个站点都会加载一堆JSBurp里可以看到这些JS的路径和文件名。很多时候后端接口的路径就硬编码在前端代码里直接拼URL。我拿到这些JS之后会保存下来用grep搜一下api/、admin/、config这类关键词顺手就能挖出好几个目录扫描字典里根本不会出现的路径。4.2 变体规则的推演词根如何扩展成候选路径词根本身是死的关键看你怎么把它变活。这部分我一般用BurpSuite的Intruder配合一个小脚本来完成核心是“把一个词根扩展成一系列候选路径”。举个例子假设我从抓包里提取到一个项目代号bluewhale那我会把它扩展出下面这一系列变体变体类型实际候选路径原词bluewhale首字母大写Bluewhale全大写BLUEWHALE加年份bluewhale2024加业务模块bluewhale_admin/bluewhale_api常见文件后缀bluewhale.php/bluewhale.sql/bluewhale.tar简写形式bw/bw_admin/blw加下划线/中线/点blue_whale/blue-whale/blue.whale生成这个变体表之后我再把目标站点可能出现的顶级目录词根套进去。比如web、upload、files、assets、static、resources每个词根再结合变体规则生成一批路径。这个过程很枯燥但非常值得做因为很多站点部署者会顺手把备份文件命名为bluewhale_bak.tar.gz这种路径是通用字典扫一百遍都扫不到的。4.3 自建字典去重与排序的细节字典生成之后不是直接用先做两件小事。第一件是去重把所有候选路径过一遍sort -u把重复行干掉减少无效请求。第二件是把更有价值的内容往前放比如.git、.svn、.env、config这些高价值路径排在前面它们一旦存在后续测试方向会被极大影响。我会在字典头部放一个“高优先级段”然后再放常规路径。dirsearch是按字典顺序逐行请求的高优先级段排前面万一目标限流导致扫描中途被断至少最重要的内容已经扫过了。去重后的字典可以直接存成纯文本文件一行一个路径dirsearch的-w参数直接指定它就行。我一般还会把同一份字典保存一份.txt和一份.json格式方便在不同工具里复用。这里提醒一句字典里不要放注释行和空行dirsearch不会像某些工具那样帮你自动跳过遇到空行会发出空请求既浪费时间又容易触发风控。5. 敏感目录泄露挖掘时最该盯住的三类文件5.1 备份压缩包与源代码泄露目录扫描里最有价值的发现之一就是备份文件。很多站点开发者在更新代码之前会把整站打包成压缩包放在Web根目录下比如www.zip、web.tar.gz、site.rar、backup.zip文件名简单粗暴。这种压缩包一旦被下载等于把整站源码打包送人配置、数据库账号、密钥全在里头。这类文件的特征很明显文件体积通常比普通页面大好几个数量级状态码200响应内容类型是application/zip或application/x-gzip。dirsearch输出结果里如果看到Content-Length字段特别长、内容类型是压缩包一定要优先去下载验证。我每次拿到备份包之后第一件事就是解压找.env、config.php、database.php这类配置文件以及.git目录是否存在。除了整站打包还有一种更隐蔽的是单文件备份比如运维人员手滑把config.php备份成config.php.bak、config.php~或config.txt。这类文件不会出现在首页目录列表里但通过目录扫描很容易暴露。字典里一定要包含带.bak、~、.old、.save、.temp后缀的词条这种低成本路径往往能捡到漏。5.2 隐藏版本库与配置文件泄露.git和.svn这两个目录是目录扫描里的“头奖”。如果站点根目录下存在/.git/说明开发环境的版本库被直接部署到了服务器上。Git的提交历史里几乎必然藏着旧版本的敏感信息比如数据库密码、第三方API密钥、内网地址。一个常见的误判是目录扫描跑出/.git/返回200页面内容却是一堆HTML标签。实际情况是服务器把.git目录的访问重写到了某个框架入口页比如所有请求都转到index.php但只要/.git/HEAD这个文件能直接访问且内容返回ref: refs/heads/master那就证明版本库泄露了。配置文件是第二类高价值目标。我在扫描时专门会在字典里放这些路径/.env、/config.json、/config.yaml、/conf.php、/settings.py、/web.config、/crossdomain.xml。有些框架会把配置写在根目录默认不认识的人是想不到去访问的但dirsearch只要字典里有一行就能精准命中。这类文件泄露意味着数据库凭据或内部服务地址暴露是需要立即上报处理的高危问题。5.3 管理后台运维入口的典型特征管理后台和运维入口是敏感目录挖掘里最后一大类。常见的路径有/admin、/administrator、/manage、/manager、/system、/backend不同框架还有各自的固定后台路径比如PHPMyAdmin的/phpmyadmin、Tomcat管理台的/manager/html、Jenkins的/jenkins、Docker管理界面的/portainer。这一类的扫描要点在于“验证”而不是“发现”。路径返回200不一定就是后台可能是前端路由到首页了路径返回403也不一定就不能访问有时候换一个X-Forwarded-For: 127.0.0.1头就能绕过IP白名单。我一旦发现这类路径会立刻切到BurpSuite里手动跟几个请求看响应头里有没有WWW-Authenticate、Set-Cookie等相关字段判断它背后到底是不是一个需要认证的管理界面。在测试过程中我习惯把这一类结果单独拉进一个列表和高价值备份文件、版本库泄露分开管理。报告里优先级排序也是这个顺序备份源码泄露 版本库泄露 配置泄露 管理后台。前三类属于直接可导致越权或接管的问题后台至少还需要继续爆破账号风险级别相对没那么紧急。6. 扫描完成后的结果筛选与组合工作流6.1 误报是怎么来的怎么用排除参数压下去扫描完成不是终点断言还得继续。dirsearch默认会过滤404但实际环境中误报仍然很多最常见的两种误报场景如下。第一种是自定义404页面返回200。有些站点没有配置标准404而是把不存在的URL都转发到首页或某个统一样式页响应状态码是200。这种情况下dirsearch会认为你去访问的路径是存在的然后就报给你看。处理方法是打开dirsearch的--exclude-status参数排除已知的无效状态码更重要的一点是盯住响应长度。如果多个明显不存在的路径返回的长度完全一样那它们大概率都是同一个伪200页面我通常会直接用黑名单逻辑记住这个长度后续结果里凡是长度等于这个值的全部忽略。第二种是302跳转到登录页。很多站点的未授权访问都会被重定向到/login目录扫描就会收到一排302结果。这东西看着像有路径实际只是一张空壳。排除方法是看Location头如果所有302的Location都指向同一个登录页那这些路径基本没内容可挖。你可以在dirsearch里配置--exclude-status302也可以事后再对带302的结果逐一验证。我个人倾向后者因为某些302的目标地址本身可能有信息全部一刀切容易漏。6.2 递归扫描和扩展名参数的正确打开方式递归扫描是dirsearch很实用的一个功能它会在发现有效目录后自动对该目录下的路径继续发起扫描。比如扫到/admin/存在就会继续扫/admin/xxx、/admin/yyy。这个功能用好了能快速摸清目录层级但用不好会把请求量瞬间放大几十倍直接把目标限流或封IP。我的经验是开局第一轮扫描不要开递归。先用浅层次扫描把站点结构大概过一遍找到有价值的前几个目录再单独针对这些目录开递归。命令大概是这样的python3 dirsearch.py -u http://target.com -e php,html,bak,txt -t 30 --exclude-status403,403 --delay0.05在目录被递归进入时我会格外注意.git、backup、uploads这类目录一旦命中往往意味着后续扫描路径会指向真正的敏感文件。关于扩展名参数我的建议不是越全越好。-e参数需要结合目标指纹来判断PHP站点就写php,txt,bakASP.NET站点就写aspx,config,txt。把字典里没有关系的一堆扩展名加进去只会让扫描时间翻几倍而有效结果的增量非常有限。dirsearch支持--prefix和--suffix参数可以用来构造自定义的前后缀规则比如所有词条后面加.bak、所有词条前面加test_这个小功能适合做定向爆破时使用。6.3 把 dirsearch 接入现有测试流程的个人习惯最后分享一个我工作时的完整组合流程。拿到授权目标之后我通常不会只跑一遍dirsearch完事而是会连续做三件事第一先用统一的参数跑一轮通用字典扫描输出到一个文本文件同时备份一份JSON格式的完整输出。命令python3 dirsearch.py -u https://target.com -e php,txt,bak -t 20 --random-agent --formatplain -o first_scan.txt第二把第一轮结果里的关键路径挑出来比如发现的/admin/、/backup/、/.git/再分别用递归参数定向跑一轮深度扫描。这一轮我会把线程降低到10以下延迟调大确保不会被目标的风控策略拦截。第三把深度扫描结果和第一步的通用结果合并去重后导进一个统一清单。接下来我才会开始对这些路径做手工验证在BurpSuite里打开每一个可疑路径观察页面内容、Set-Cookie、响应头、JS引用等细节。目录扫描只是发现入口最终确认和利用是另一个环节的事但入口发现环节做得扎实后面会顺利很多。这个流程是我在实际被各种目标按在地上摩擦之后总结出来的。好用的地方在于它不依赖某个具体工具也不依赖某次扫描的结果而是把目录信息这条线完整地串起来了。说实话dirsearch并不是一个“技术含量”多高的工具它的价值恰恰体现在怎么用、什么时候用、用完怎么判断。把这些细节理顺之后你的扫描效率会比大多数人高出一截。