ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

dirsearch目录扫描实战:敏感目录泄露挖掘与字典定制全攻略

dirsearch目录扫描实战:敏感目录泄露挖掘与字典定制全攻略 前几天群里有位朋友发了个报错截图安装目录扫描工具dirsearch时终端弹出一行“unable to locate package dirsearch”下面跟着一排问号加感叹号。这个报错我太熟了几乎每个第一次在自己电脑上装dirsearch的人都会撞上。顺着这个话题群里从安装问题聊到字典爆破又聊到靠这个工具挖出过哪些敏感目录我干脆把这几年的使用经验整成一篇完整记录免得以后每次都要重复讲一遍。目录扫描工具这个大类圈内出镜率最高的就是dirsearch轻量、快、输出清晰配合字典爆破的思路能在几分钟内把目标站点的目录结构摸个大概。它解决的核心问题其实很简单Web服务器上那些“不该被外人看到”的文件和路径到底藏没藏住。敏感目录泄露挖掘本质上就是在跟“粗心的部署”赛跑——开发往网站根目录扔了个备份包、忘记删掉的管理后台、暴露在公网的日志文件这些都是扫描结果里的常客。这篇内容主要写给三类人刚接触Web安全、想搞懂目录扫描原理的初学者已经会基本使用但想优化字典和扫描流程的进阶玩家负责系统运维、想排查自家站点有没有敏感文件泄露的开发同学。我会从原理讲到实战把安装踩坑、字典定制、结果分析这些环节掰开揉碎尽量让每个看的人都能直接上手。1. 目录扫描究竟是干什么的1.1 为什么Web站点需要目录扫描先聊一个最基础的问题为什么目录扫描能成为Web安全测试里的固定动作。我们平时访问一个网站看到的是首页、商品列表、详情页这些“前台页面”但一个Web站点在服务器上本质是一堆文件的集合——HTML、PHP、JS、图片、配置文件、备份压缩包。URL的路径基本就对应着服务器上的文件路径。前台页面只是管理员主动暴露出来的那一小部分剩下的大部分文件靠的是“你不说外人就不知道”这种朴素的安全假设。问题恰恰出在这里。很多文件虽然没有链接入口但它们是真实存在、可以访问的。比如某个旧版本的后台登录页还挂在服务器上或者是某个接口文档被随手传到了可访问目录。目录扫描工具干的事情就是拿着一个装满路径单词的字典逐条去请求目标URL看哪些路径真实存在。只要服务器返回的响应码和“不存在”的响应不一致这个路径就被“扫出来”了。这种“试探”的效率和人工完全不在一个量级。一个几千条的字典配合多线程几分钟就能跑完。人肉一个个拼路径去试可能一上午都试不了一百个。我见过最快的一次测试默认字典5000多条10个线程三分钟多点就跑完了扫完直接发现一个未删除的备份文件。这个效率是任何手工操作都没法比的。1.2 敏感目录泄露的危害到底有多大一次扫描可能扫出几十个文件但真正有价值、够“敏感”的其实就那几类。最典型的是源码备份文件比如www.zip、backup.tar.gz、某个.bak文件这类文件一旦下载成功整个站点的源代码等于直接白送。攻击者拿到源码后可以做代码审计找出SQL注入、越权、逻辑漏洞比从零开始黑快得多。第二类危险的泄露是配置文件。很多框架会把数据库连接信息、密钥、第三方服务的凭据写进配置文件里如果config.php.bak或者.env这类文件暴露出来数据库地址、账号密码、Salt值这些关键信息一口气全漏了。我处理过一次风险报告一个后台拷贝的配置文件里包含了Redis连接密码而Redis恰好是未做认证的通过它还能进一步读取会话数据。一串文件泄露能牵扯出一整条攻击链。第三类是开发环境残留。比如/phpinfo.php、/server-status、/actuator这些调试或监控页面虽然单个看起来不致命但会泄露服务器的软件版本、绝对路径、环境变量。这些信息看着不起眼却是攻击者规划下一步攻击路线时的重要拼图。另外还有一类是管理后台路径比如/admin、/manage、/manager没有入口但不代表不存在一旦被扫出来攻击面就从“猜”变成了“尝试登录”。1.3 目录扫描工具的工作原理搞清楚原理才能更好地用工具。dirsearch这类工具的核心逻辑并不复杂读取字典文件把每一行当作路径拼接到目标URL后面然后发起HTTP请求用返回的状态码判断这个路径是否存在。常规情况下服务器对一个不存在的路径会返回404对存在的路径返回200、301、302、403等“非404”状态码。工具就根据这个差异来圈定候选结果。但这里有一个坑不同服务器对404的处理方式不一样。有的返回404有的返回200但内容是一个统一的“页面不存在”模板还有的反代配置得比较特殊随便输什么路径都返回302。如果只看状态码误报率会高到没法看。所以dirsearch这类工具后来都加了响应内容比对的能力它会先请求一个“几乎不可能存在”的随机路径把这次响应的长度和内容当作404基准再拿其他路径的响应跟这个基准做对比凡是长度、内容都接近基准的就当作“疑似404”过滤掉。这一版比对逻辑是扫描质量的关键分水岭。老牌工具和新兴工具拼的其实就是这块的准确性。理解了这一点后面看扫描结果时就不会傻乎乎地相信每一个带200状态码的条目也会明白为什么有时候工具会提示“inferred: 404”这个词说的是“工具推断当前站点的404规则是这样的”不是真的返回了404。2. dirsearch安装与基础使用全记录2.1 安装踩坑unable to locate package dirsearch回到开头的那个报错。在Ubuntu或Debian系系统上执行apt install dirsearch大概率会看到unable to locate package dirsearch。这句话翻译过来是“找不到叫dirsearch的软件包”原因很简单默认的apt软件源清单里根本没收录这个包或者源地址还没有执行更新同步。很多人第一次看到这个报错就懵了以为是软件名拼错了其实不是。解决办法分几步走。第一优先是把软件源信息更新一遍执行sudo apt update把本地的包索引同步到最新然后再试一次sudo apt install dirsearch。如果源里恰好收录了这个包更新完就能正常装。如果更新完还是报错说明当前源确实没有那就得换方案。更稳妥的安装方式是从源码运行这也是官方推荐的用法。步骤很简单git clone https://github.com/Auxy科普/dirsearch.git cd dirsearch pip3 install -r requirements.txt python3 dirsearch.py --helpGitHub上拉取失败的话可以换https://github.com/maurosoria/dirsearch.git这个仓库地址这是一个长期维护的版本功能和参数都比较全。依赖装好后直接用python3 dirsearch.py启动不需要系统级的安装所以也不会污染环境。在Kali Linux上一般会预装或可以直接从官方源安装因为Kali的目标本来就有渗透测试工具集合。普通用户如果只是偶尔用一次我推荐直接用git clone的方式省事、版本新、后续升级也方便。装好之后跑一下python3 dirsearch.py --help能看到参数说明就说明环境没问题。2.2 基础扫描命令与参数逐项拆解先来一条最常用的命令python3 dirsearch.py -u http://192.168.1.10/ -e php,bak,zip这条命令的意思是对目标地址http://192.168.1.10/做扫描并尝试补充php、bak、zip三种扩展名。-e参数是dirsearch的一大特色它会把字典里的每一个路径按“原样路径”和“路径扩展名”两种形式分别请求一次比如字典里有admin这一行就会同时试/admin和/admin.php、/admin.bak、/admin.zip。这样就等于把一份字典的覆盖面放大了好几倍不需要额外维护一大堆带扩展名的路径条目。再给几个高频参数按我实际使用的频率排序参数作用使用场景-u指定目标URL必填注意要带协议头http://或https://-e指定要追加尝试的扩展名按目标站点技术栈设定PHP站加php,bakJava站加jsp,html,action-w指定自定义字典文件默认字典不满意时切换-t线程数默认是10本地目标可以开到30-50公网目标建议保守一点-x排除指定状态码比如-x 403可以把“存在但禁止访问”的路径排除掉-r递归扫描发现一个新目录后自动进入该目录继续扫--random-agent随机User-Agent避免被简单的UA频率限制策略拦掉--delay每请求之间的延时秒数个人测试时不需要但公司内合规场景可能需要控制速率-o输出结果到文件推荐配合-f使用保存报告这套参数看起来多其实真正每天用的就那么几个。我的常规操作模式是先用默认字典和-e参数跑一圈拿到初步结果之后再针对敏感点加-r递归深挖。2.3 结果输出与报告解读dirsearch跑完之后会在终端把发现的路径带状态码打印出来同时默认把结果保存到reports目录下文件名包含目标域名和时间戳。这个设计非常实用因为实际测试时不可能只扫一轮保存的报告方便后续回溯。输出格式有三种常用选项plain文本格式、JSON、以及XML。我习惯在自动化脚本里用JSON能方便地解析路径和状态码做二次处理人工查看时直接用默认的plain就好简洁直观。看结果时建议按这个优先级处理先关注200且带敏感关键词的条目比如备份文件、源码包、配置文件这些基本可以直接验证利用价值其次是301/302跳转路径它们往往指向后台或者API入口手工确认一下跳转后的内容最后是403路径很多人直接跳过其实403也有可能包含可访问的子文件只是目录本身禁止列举。3. 字典爆破核心原理与字典定制3.1 字典文件的结构与作用机制目录扫描工具的“弹药”就是字典字典质量直接决定扫描效果。dirsearch的字典文件放在安装目录下的db文件夹里打开一个看会发现每个字典就是一行一个路径的文本文件。比如dicc.txt是通用综合字典包含大量常见的目录名和文件名backup.txt专门放备份文件特征词admin.txt收录管理后台路径extension.txt、languages这些则用于扩展名的补充尝试。很多人有个误区以为字典越大越好。我曾经干过把SecLists的几万条目录字典直接喂给dirsearch的蠢事结果扫一个中型站点跑了快一个小时最后有效结果还没有默认字典多。原因是字典越大无效请求和重复请求就越多真正有区分度的路径特征反而被稀释了。字典爆破追求的是“覆盖率高”和“噪音低”的平衡不是单纯地堆数量。一个合理的字典应该包含这些类别的词条按字母排列的常见英文单词如admin、backup、test、temp、logs文件扩展名组合如.bak、.old、.swp、.txt、.zip数字组合序列如admin1、2020、backup2021这种带年份风格的再就是框架特征路径比如ThinkPHP的runtime、applicationSpring Boot的actuatorWordPress的wp-content。拼出这样一个字典之后覆盖效率会远高于一个大杂烩字典。3.2 如何根据目标站点定制字典定制字典的起点是“指纹识别”。先用浏览器或者whatweb之类的工具看一下目标站点用了什么技术栈。看到PHPMySQL的站点字典里就重点放php、mysql、admin、config、backup这类词看到Spring Boot的标志性报错页或者/actuator路径就针对性加入actuator/env、actuator/heapdump这类特有的路径。我开始是按行业去积累的比如政务类站点常见/zwgk、/wcm这种栏目路径电商类站点常见/cart、/checkout、/pc这种业务路径。虽然这些路径未必是“敏感目录”但扫出来能帮我们判断站点的目录结构为后续测试提供线索。举一个定制字典的实际例子。假设目标是一个ThinkPHP5的站点默认字典可能扫不出太多东西但如果你把application、runtime、thinkphp入口文件路径加进去配合-e php很可能直接发现未删除的调试页面或者框架的缓存目录。这类特征路径靠通用字典是覆盖不全的必须结合技术栈做动态补充。3.3 目录扫描与Burp Suite爆破字典的配合目录扫描工具负责“发现路径”Burp Suite这类工具则更适合“在一个路径下继续深挖”两者的字典可以互相转换、配合使用。最常见的配合场景是dirsearch先发现了一个后台登录地址/admin/login.php接下来需要对这个登录接口做弱口令测试这时就把常见的用户名和密码字典导入Burp Suite的Intruder模块通过设置两个字典做Cluster bomb爆破。Burp Suite的爆破字典和目录字典格式上是通用的都是纯文本一行一个词条。但内容方向差异很大目录字典里放的是路径单词爆破字典里放的是用户名、密码、Token和常见的组合规则。我习惯把SecLists的Passwords目录下几个常用弱口令列表统一去重合并做成自己的weak_pass.txt同时配一个users.txt里面包含admin、test、root、admin1这类常见账号名。实际操作中最容易踩的坑是字典里的空行和重复项。Burp对空行和重复payload不会报错但会白白增加请求量拖慢爆破速度。所以我每次切换字典之前都会先做一遍清洗去掉空行、去掉首尾空格、排序去重。这个动作我在脚本里固化下来了免得每次手动操作。4. 敏感目录泄露挖掘的完整实战流程4.1 一个标准目标从开始到出报告的完整流程下面是用dirsearch做一轮标准敏感目录挖掘的完整步骤我按自己日常操作的顺序写出来。第一步确认授权边界。这一步非常重要。扫描前先确定目标域名/IP属于自己公司或已获得甲方书面授权而且要明确授权的测试范围千万别跑到授权范围之外去扫。正规公司做渗透测试都会有授权书或测试方案个人学习建议用靶场环境如DVWA、Pikachu或者自己搭的虚拟机。第二步基础信息收集。用curl -I看目标服务器的响应头判断Web服务器类型、是否开启了目录列举、是否套了CDN或者WAF。这一步花不了两分钟但对后续参数选择很有帮助。比如看到Server: nginx而且没有明显的WAF特征就可以放心用默认线程看到提示cloudflare或者国内云WAF就要适当降低线程并做好延迟准备。第三步基础扫描。执行命令python3 dirsearch.py -u http://target.com/ -e php,txt,bak,zip --random-agent -t 20 -o report.txt我用-e覆盖了最常见的四种扩展名把结果落到报告文件里。这一步扫完站点的基础目录地图就出来了。第四步递归深挖。基础扫描发现/admin、/backup这种有进一步探索价值的目录后执行python3 dirsearch.py -u http://target.com/admin/ -e php,bak -r-r参数让工具在成功进入/admin/之后继续扫描其子目录。这一步能发现不少藏在后台目录深处的残留文件。第五步验证结果。扫出来一堆条目不代表都有价值我习惯把报告导出来用脚本筛选出状态码是200且路径包含bak、zip、config、env、git、svn这些关键词的条目然后逐个用浏览器或curl查看。确认这些内容真的能被下载、能读到有效信息才算是有实际风险。第六步输出报告。把验证过的敏感路径、泄露的数据级别、修复建议整理成报告提交给运维或开发修复。整个流程看起来长实际执行起来基础加递归两轮扫描加上验证半天时间能全部搞完。4.2 常见敏感文件与目录特征速查我整理了一张高频敏感路径特征表这份表是我自己平时验证结果时重点关注的清单遇到这些路径基本都要手工点开看一眼。敏感类型典型路径风险说明源码备份/www.zip、/backup.tar.gz、/web.rar直接打包下载源码全站源码泄露风险极高版本控制泄露/.git/、/.svn/、/.DS_Store.git目录可回溯全部源码历史.DS_Store泄露目录结构信息配置文件/.env、/config.php.bak、/web.config.bak数据库连接、密钥、第三发凭据可能直接暴露管理后门/admin/、/manager/、/manage/、/console/后台入口暴露配合弱口令爆破风险放大调试监控/phpinfo.php、/actuator、/server-status、/jolokia泄露运行环境、类路径、配置项辅助后续攻击日志文件/logs/、/error.log、/access.log日志里可能包含SQL语句、用户信息、攻击痕迹文档导出/api-docs、/swagger-ui.html、/docs/接口文档泄露暴露未授权的接口及其调用方式这张表不用背但看到这些路径时心里要有警觉。尤其是/.git/很多新手以为扫到.git/只意味着一个目录存在但实际上可以使用专门的工具从git泄露中恢复源码风险等级完全可以排到最高级。4.3 扫描结果的验证与分析扫描工具给出的是“候选名单”不是最终结论。验证的重要性怎么强调都不过分因为误报和真实风险之间的差异非常大。举个典型的例子很多站点对所有未知路径都返回200但页面内容是同一个前端模板。如果只看状态码你会觉得扫出来几百个目录实际全部是假的。所以我验证结果时第一件事就是看响应内容长度和页面的title一旦发现全是长得差不多的页面基本可以断定这个站点做了全路径返回200的“特殊处理”。验证一个具体条目的推荐做法是curl -I http://target.com/backup.zipcurl -I只拿响应头快速判断文件是否真实存在以及内容类型。如果需要下载下来确认敏感度再用wget或者浏览器正常下载。下载文件后先检查后缀和文件头不能只凭路径名字就下结论。比如一个叫backup.txt的文件实际内容可能是一个空文件也可能是几十兆的数据库导出文件这两者风险级别天差地别。分析完单个条目的风险之后我会把结果按“敏感度可利用性影响范围”三个维度排个序优先深入验证风险最高的那些然后把完整结论写进报告。这样既能保证不遗漏也不会在低价值条目上浪费时间。5. 高频问题排查与性能调优实录5.1 扫描太慢或者卡住了怎么办遇到扫描慢先分清是“工具性能问题”还是“目标网络条件限制”。工具侧的解决办法主要是提升线程数但线程数并不是越大越好。我曾在一台普通配置服务器上把线程开到80结果目标服务器直接开始丢包请求超时率飙升扫描速度反而下降了。对大多数目标来说20到30个线程是比较平衡的选择。如果目标本身很慢或者网络链路有损耗那就改用分级扫描策略第一轮用精简的高价值字典快速扫一遍只留最可能出结果的路径第二轮再用大字典带-r递归补充。这样分两轮跑比一次跑一个超大字典要快很多还能减少目标服务器的压力避免还没扫完就被限速。卡住还有一个常见原因是字典文件里存在无法编码的字符或者超大行。我遇到过几次工具在扫描中途直接退出排查下来都是因为我导入的字典里有一行特殊字符导致请求异常。遇到这种情况先检查字典是否有乱码、空行、超长行清洗干净再重跑。5.2 误报太多导致没法看怎么办误报太多通常是两个原因目标服务器设置了“所有路径统一返回200”或者“所有路径统一返回到登录页”以及没有正确配置排除状态码。面对第一种情况工具自带的内容比对机制一般能解决大部分但如果站点模板对404响应和200响应的大小差异很小就需要手工核实。面对第二种情况配置-x参数能直接过滤掉干扰项。比如目标站点对无权限路径统一返回403对不存在的路径也统一返回403这种情况下403就没有区分度可以直接-x 403。同理如果站点所有不存在路径都返回302并跳转统一页面加-x 302效果也一样。另外可以灵活使用--minimal参数。这个参数的功能是设置一个最小响应长度小于该长度的响应直接视为无效。它能自动过滤掉很多内容几乎为空的响应我实测对误报率偏高的情况改善非常明显。5.3 安装运行时的常见报错汇总这里把目录扫描过程中最高频的几个报错和解决办法一次性列出来都是群里经常问到的。第一类unable to locate package dirsearch。这个前面讲过先sudo apt update不行就改用git clone方式安装或者使用Kali系统自带的包管理。第二类ModuleNotFoundError: No module named requests。运行python3 dirsearch.py时提示缺少requests模块直接执行pip3 install requests装一下就好。第三类Permission denied。用默认端口扫描或者输出报告时遇到权限不足检查是否用了sudo以及报告目录是否有写权限。第四类Target is not defined或者URL format error。这类错误几乎都是因为-u后面的URL写错了比如漏了http://协议头或者带了空格。URL规范是目录扫描工具最容易忽略但最基础的点检查一下就能解决。第五类No valid directory found。这个提示不是报错而是说当前字典在当前目标下没有发现有效目录不代表工具出了问题可能是目标站点确实做了很好的收敛也可能是字典跟站点的技术栈不匹配。换一份技术栈定向字典再跑一次基本就能确认。5.4 扫描规范与红线提醒目录扫描是一把很实用的“侦察工具”但使用边界必须清楚。每次扫描前我都会先确认三件事第一目标是否在授权范围内第二扫描强度是否控制在目标可承受的范围内会不会对业务造成影响第三扫描过程中发现的敏感数据是否遵守了“不下载扩散、及时上报处理”的原则。发现敏感目录泄露之后正确的处理路径是记录路径、截图留证在报告中标明风险等级然后通知业务方或安全负责人修复而不是继续深挖。这份克制既是职业道德也是法律底线。对负责防御的同学来说建议把目录扫描纳入上线流程的一部分每次发版前用默认字典快速扫一遍很多泄露事故根本走不到公网。我个人的习惯是在测试完以后会把扫描用的临时文件、下载的缓存统一清理掉然后给目标站点做一个防护建议清单。比如关闭服务器目录列举、删除配置文件备份、将后台路径改名、上线前扫描一遍敏感文件。这些动作做完比单纯报告一个“发现某路径可访问”要有价值得多。最后分享一个小技巧dirsearch的socks代理参数配合一些合规的调试场景非常实用比如测试环境在不出网的内网需要走代理完成访问。但要注意代理的配置要一次写对写错了会一直报连接超时排查起来反而费时间。这类小细节都是跑得多了才慢慢磨出来的经验。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进