一个登录页,一张只有公司简介的官网首页,甚至是一段“系统建设中”的占位字符——做渗透测试的人,最熟悉的就是这种开场。你手里拿着授权书,目标就在眼前,可浏览器打开之后什么都没有,连一个像样的功能入口都找不到。这种“空白页”局面,十次渗透里能碰上三四次。很多人卡在这一步,拿着目录扫描器跑完一轮,凑合交一份“未发现高风险漏洞”的报告就结束了。
我自己做这一行多年,遇到空白页的次数不少。说实话,真正的突破口往往不是从一个大漏洞开始的,而是从一条不起眼的信息开始的:某个备份文件、一段注释掉的接口路径、一台暴露的子域服务。本文就把我从“空白页”到“突破口”的七条信息发现思路完整拆开讲,覆盖其中涉及的原理、工具、参数和经验教训。无论你是刚学安全测试的新手,还是已经有一定经验的从业者,这套方法论都能直接套用到你手头的项目里。
1. 空白页问题的本质:不是没漏洞,而是还没看到入口
1.1 空白页是怎么造成的
“空白页”并不是真的空。它背后通常有三种情况。第一种是目标确实很小,比如一个内部工具、一个快速上线的前端页面,只有少数几个功能,攻击面天然有限。第二种是目标把功能藏起来了,公网只开放一个门户页,真正的业务系统部署在内部网络或特定网段,外部访问不到。第三种是目标做过基础加固,比如把后台路径改了名、隐藏了管理入口、或者默认不愿意暴露任何技术细节。
分清这三种情况很重要,因为它决定了你后续的工作量。如果是第一种,信息发现的重点就是“把隐藏文件挖出来”;如果是第二种,重点就变成“找到关联资产”;如果是第三种,就进入了“和技术对抗”的阶段。最怕的是不做区分,拿着一个字典无脑扫,白白浪费授权周期。
1.2 信息发现的“翻译”逻辑
我特别喜欢把信息发现理解为一种“翻译”工作。目标系统会拒绝给你直接的目录列表,但它在公开可见的层面——HTTP响应头、页面源码、JS文件、DNS记录、历史快照——留下了大量无意识的痕迹。信息发现做的事情,就是把“网站”这种产品形态翻译回“代码工程”和“基础设施”的语言,再从中找到可操作的测试点。
举个例子,一个看起来平平无奇的登录页,源码里可能躺着一行注释:“// TODO: resolve the upload bug before release”。这行注释告诉你三件事:系统有文件上传功能、这个功能存在未解决的缺陷、开发风格比较随意。这些信息单独看都不算漏洞,但叠加起来,就给你指出了下一步测试的方向。信息发现的价值就在这里:它不是在找漏洞,而是在找通往漏洞的路。
1.3 这套思路适用的场景与前提
七种思路适用于绝大多数Web渗透测试项目,尤其是黑盒测试场景,也就是你只知道目标域名或IP、不知道内部结构、没有拿到代码和文档的那种测试。有一点必须强调,也是整个行业反复强调的底线:所有操作必须在合法授权的范围内进行。无论是目录扫描、子域名枚举还是历史快照查询,都要求你对该目标拥有书面测试授权。没有授权的前提下,连发起一次HTTP请求都不应该。
2. 七种思路的整体编排与优先级
2.1 为什么是这七种思路
网上关于信息收集的资料很多,但大多是散点式的一堆工具罗列。我总结出来的七种思路,核心依据是“信息的访问入口”维度,也就是目标系统最终会通过什么渠道向你泄漏信息:
| 序号 | 信息发现思路 | 依赖的信息源 | 产出类型 |
|---|---|---|---|
| 思路一 | 路径扫描与备份文件猎取 | Web服务器文件系统 | 隐藏路径、备份文件、配置文件 |
| 思路二 | 前端资源深度审计 | HTML、JS、Source Map | 接口路径、参数名、业务逻辑线索 |
| 思路三 | 指纹识别与响应差异分析 | HTTP响应头、错误页、页面行为 | 技术栈、版本、开发者习惯 |
| 思路四 | 子域名与关联资产扩展 | DNS、证书日志、IP关系 | 新域名、新系统、薄弱环节 |
| 思路五 | 历史快照与变更追踪 | 网页归档、搜索引擎缓存 | 旧接口、历史漏洞、已删页面 |
| 思路六 | 公开情报与搜索引擎组合 | 代码托管平台、文档站点、社交平台 | 源码片段、密码、员工行为线索 |
| 思路七 | 接口与调试端点探测 | 前后端交互模式、API路由规则 | 未授权接口、调试入口、管理端点 |
这七种思路的划分逻辑很简单:先看服务器有什么,再看前端代码泄漏了什么,然后看技术栈告诉你什么,接着把视野拉到整个企业资产,再借时间维度去看历史变化,然后跳出单一站点去查公开信息,最后聚焦在接口层做定向枚举。七条线走完,一个空白页基本就被翻了个底朝天。
2.2 执行顺序与依赖关系
很多新人喜欢把工具一股脑全跑起来,最后桌面开了一堆终端窗口,结果谁也没出结果。我建议按“静态优先、动态在后、主动扩展收尾”的顺序来。具体来说,思路五(历史快照)和思路六(公开情报)属于纯被动收集,不向目标发送任何额外流量,应当最先执行,风险最低、回报又稳定。然后是思路二(前端审计)和思路三(指纹识别),通过正常浏览就能完成。之后才进入主动探测阶段,按思路一(路径扫描)、思路四(子域名扩展)、思路七(接口枚举)的顺序推进。
这样编排的原因有二。一是避免打草惊蛇,越往后动作越大,先收集齐被动的信息,能让你在主动扫描时知道该把火力集中在哪里;二是存在信息依赖,比如前端JS里看到的新域名,会直接补充进子域名枚举的目标列表,而子域名扫描出来的新系统,反过来又会产生新的“空白页”,需要回到思路一和思路二重新处理。这个过程是螺旋上升的,不是一条直线。
2.3 一个可复用的信息发现流程
我自己常用的信息发现流程大致是这样的:先建一个项目文件夹,按“01-被动收集”、“02-前端审计”、“03-主动扫描”、“04-关联扩展”四个子目录存放产出物。被动收集阶段把历史快照、搜索引擎结果、公开代码搜索的结果全部归档;前端审计阶段保存所有JS文件,并做接口路径提取;主动扫描阶段先做目录扫描再调试参数;最后把子域名和关联IP的结果汇总成资产列表。每次测试都按这个流程走,不容易漏项,写报告的时候也有据可查。
3. 思路一与思路二:路径扫描加上前端资源审计
3.1 思路一:路径扫描的字典选择门道
目录扫描的思路核心是猜测那些不公开的路径。你访问一个网站,服务器只给你看它想给你看的东西,但Web服务器和框架的默认结构是固定的,备份文件、临时文件、开发环境目录都有相对固定的命名习惯。路径扫描的本质,就是用字典去碰这些约定俗成的文件名。
很多新手最纠结的问题是“用什么字典”。我的观点很明确:别一上来就上超大字典。几万条的超大字典扫出来的结果往往淹没在大量误报里,你要花大量时间验证,效率反而低。优先选择针对性的中等字典,覆盖常见目录名(admin、backup、temp、test、api)、常见备份后缀(.bak、.zip、.tar.gz、.sql、.old)、常见文件名(index.php.bak、web.config.bak这类)。扫出来结果后再用大字典做补充轮,重点覆盖内容管理系统和开发框架的固定路径。
目录扫描的另一个关键点是状态码的甄别。不要只盯200,404之外的所有状态码都有价值:301说明路径经过了重定向、403说明路径存在但拒绝访问、405说明此处有接口但方法不对、500说明路径命中了一个会报错的代码逻辑。很多隐蔽目录就是用301跳转暴露出来的,因为它把请求指到了一个你原本不知道的真实位置。
3.2 思路二:前端源码与JS接口挖掘细节
前端资源审计被我排在所有主动扫描之前,是因为它几乎零风险,而且信息密度极高。拿到一个空白页,第一件事是右键查看源码,然后按这个顺序排查:HTML注释、隐藏表单字段、iframe属性、link和script标签的路径。注释是开发者最直白的表达,我曾经在一个部署到生产环境的页面里看到过整段数据库连接池配置的示例代码,虽然已经被过滤了敏感信息,但表名和库名结构全都在。
JS文件是更大的信息富矿。现代Web应用几乎都是前后端分离架构,前端的逻辑全部打包在JS里,而后端接口的路径、参数名、数据结构定义也被迫跟着写进前端代码。实际操作时不要只点开一个app.js看完就完,完整的做法是把所有JS文件下载到本地,用脚本一次性提取所有URL路径、接口地址、参数关键字(如token、upload、admin、config这些),再人工梳理一遍。每次我从JS里扒出未披露接口时的那种兴奋,不亚于直接挖到漏洞。
3.3 Source Map与调试信息的额外收获
按理说,生产环境不应该开启Source Map,但真实情况是大量站点把这东西留在了生产环境。当你在前端资源列表看到.js.map文件时,意味着源码经过逆向恢复可以直接还原成接近原始的代码。这不是什么高深操作,熟练之后几分钟就能恢复一个前端工程目录。恢复出来的代码能让你看到完整的业务逻辑、第三方SDK的集成方式、甚至后端接口的完整定义。这条经验算是前端审计里性价比最高的动作之一,强烈建议每次遇到JS文件时都顺手探测一下对应的.map文件是否存在。
这两条思路组合起来的效果很奇妙。目录扫描帮你找到服务器上的隐藏文件,JS审计帮你找到业务层的隐藏接口,两者往往在后期会汇合——比如JS里提到的某个内部路径,恰好对应着目录扫描扫出来的那个403文件。一旦形成这种交叉印证,突破口基本上就稳了。
4. 思路三与思路四:指纹识别与关联资产扩展
4.1 思路三:用响应差异拼出技术栈
指纹识别的本质是看响应差异。你不用去猜目标用了什么框架,而是让目标自己告诉你。打开Burp Suite或浏览器开发者工具,先看响应头:Server头暴露Web服务器类型,X-Powered-By暴露脚本语言,Set-Cookie里往往藏着框架特征。比如一个名为PHPSESSID的Cookie大概率对应PHP站点,一个形如csrf-token的响应头则暗示后端使用了特定的Web框架。
除了响应头,还要看错误页的样式。404页面的排版风格非常独特——ThinkPHP的404长得和Spring Boot的404完全是两回事。有些框架还自带默认的favicon,直接用哈希去比对公开的图标库,就能反查出框架版本。我习惯把指纹信息全部记录进一个表格:域名、Web服务器、脚本语言、框架、版本、已知漏洞列表。后面所有主动探测的参数选择,都会基于这张表来定。
响应差异不仅用于指纹,也用于逻辑判断。登录页提交错误的用户名和密码,提示是“用户名不存在”还是“密码错误”;注册页提示“邮箱已被注册”时,你换一个输入值看响应字数的变化。这些看似琐碎的差异,在许多测试里就是判断账号枚举和数据存在的依据。信息发现这个阶段,你每记下一个响应差异,都是在为后续测试储备弹药。
4.2 思路四:子域名与关联资产的全局视角
当一个主站干干净净的时候,把视野从主域名拉宽到整个企业资产,常常会有意外收获。子域名的价值在于,不同团队、不同时期的系统往往部署在同一个主域名下,而维护水平参差不齐。测试团队严加看管的概率,远高于一个两年前上线、无人问津的旧版本管理系统。
子域名枚举的主流手段有三:字典爆破、证书透明度日志、DNS记录分析。字典爆破依赖词库,对系统命名习惯的覆盖直接决定效果;证书透明度日志是通过公开的证书签发记录查询平台,把某个主域名下所有申请过证书的子域名捞出来——这个方法不需要对目标发任何包,纯被动收集,效率却极高。实际操作中,我把三种手段的结果合并去重后,再对每个子域名做一次存活探测,很快就能得到一张企业数字资产的全局地图。
4.3 关联资产里的“弱隔离”现象
子域名系统有一个共性弱点:“弱隔离”。主站安全做得好,但测试环境、演示环境、文档站点往往用同一个内网认证体系或共享数据库。如果你在某个子域上发现了调试模式开启、或直接能访问管理后台,那这条路径的价值就远不止单个子域本身了。我整理资产清单时还会同时记录IP信息,因为同一台服务器上可能存在多个网站(IIS、Nginx的虚拟主机配置),通过IP反查证书和域名,能挖掘出“旁站”关系。一个高防护的站点旁边,常常站着一个裸奔的邻居。
5. 思路五与思路六:历史快照与公开情报
5.1 思路五:网页归档里的时间宝藏
网页归档是一个被很多人忽视但极为稳定的信息源。它对历史的每一次状态进行快照,记录了大量“曾经公开、现在已被删除”的页面和接口。对这些历史快照做信息发现,等于站在时间维度上挖掘目标系统的“前任”资产。
实际操作方法很直接:用网页归档服务查询目标域名的历史快照列表,按时间排序浏览,重点查看网站早期上线阶段和重大改版前后的页面。早期版本往往功能简陋、未经过安全完善,很可能残留测试接口、默认账号提示、甚至整个后台的入口路径。这些内容在你的授权书规定的时间窗口内,依然是目标系统的一部分,测试它们完全合法合理。还有一招是关注快照里提到的接口路径,很多老版本的接口在后端并未删除,只是前端不再调用。你手动访问这些老接口,有时还能直接触发已经无人监控的业务逻辑。
5.2 思路六:搜索引擎与代码托管平台的组合拳
搜索引擎是信息发现的传统武器,关键在搜索语法。针对单个站点,可以搜“site:目标域名”结合文件类型(filetype:pdf、filetype:docx)来找公开文档;结合目录关键字(inurl:admin、inurl:upload)来找没被收录到入口的路径。这类通过搜索引擎实现的搜索方式,是把目标自己发布出去的碎片信息重新拼起来。
代码托管平台是另一个不可忽视的信息源。开发人员可能把部分代码设为误公开权限的商业项目、或是在配置示例中填入真实服务器的连接参数。直接去代码托管平台搜目标公司名和域名关键词,有时能捞到配置文件片段。这里我要特别提醒:在代码托管平台上发现的敏感信息,处理流程和正式漏洞一样,要在授权范围之内进行测试和报告,绝不能在未经授权的情况下利用它进行超出范围的访问。公开情报的价值在“发现”,而不是“扩大授权范围”。
5.3 被动收集的时间窗口把握
历史快照和公开情报属于纯被动收集,不产生任何目标流量,所以我总是把它们放在项目最前面做。原因有两个:一是某些查询结果有时效性,晚一步页面可能就被删除或更新了;二是这些信息可以直接指导后面的主动扫描,让他们少走弯路。比如历史快照里看到一个旧的登录接口路径,你就可以把它加入字典优先扫描列表,命中率远高于通用字典。换句话说,这两条思路在前、主动探测在后的编排,本质上是让“已知信息”最大化地赋能“探测动作”。
6. 思路七:接口与调试端点探测
6.1 常用候选端点与其命名习惯
最后这条思路解决的是“页面空白但接口活跃”的场景。现代应用经常是前后端分离,页面可能只有一个空壳,核心业务全在API层。发现API层的方式主要有两种:一是观察正常功能时浏览器发出的异步请求,二是直接猜测候选端点。
长期测试下来,我整理了一份“高频候选端点”清单,按顺序覆盖这几类路径:健康检查类(/health、/healthz、/actuator、/status),API文档类(/swagger-ui.html、/swagger/index.html、/api-docs、/openapi.json、/v2/api-docs),调试类(/debug、/dev、/console、/phpinfo.php、/server-status),以及版本类路径(/api/v1、/api/v2)。在路径扫描的主字典之外,单独针对这些端点跑一轮,经常能在空白页下面挖出活跃的API服务。特别是健康检查端点,它在运维场景是标准的组件,安全团队却经常忘记对它做访问控制。一旦它返回了内存使用、服务列表、数据库连接状态,你的后续测试就有了明确方向。
6.2 从正常业务逻辑反推隐藏接口
猜测接口不能完全靠蒙,更高级的玩法是从正常业务逻辑反推。你看到登录页面就去找登录接口的同类路径模式;看到文件下载功能,就去推测上传接口可能就藏在上传目录的旁边;看到用户中心有查询功能,就去枚举同资源的不同操作方式。接口命名的规律性极强,开发者习惯用资源名词加操作动词的组合。一旦你摸清了一套接口的命名风格,剩下几十个未公开的接口就都是可枚举的了。
这个方法的核心心法是“对称思维”:前端能用的接口,后端大概率还存在同一资源模型下的其他版本操作。比如前端调用了/user/profile(查询个人中心),那/user/list、/user/export、/user/delete这些接口即使前端没用,也可能在后端是完整的。这类接口是否经过权限校验,是渗透测试里最激动人心的验证点——因为很多被遗忘的接口使用默认配置,并不经过业务层的权限检查。
6.3 API文档与调试入口的最终验证
无论是Swagger还是其他API文档框架,它们的关系有点像“用户手册大白本被放在了展柜里”:开发时用来联调,上线后却经常忘记锁进柜子。我在测试中遇到过一个模拟项目X,管理后台登录页干干净净,但Swagger文档把所有内部接口、参数结构、鉴权方式写得明明白白,甚至连测试账号都写在描述里。这种案例不算罕见,所以API文档的探测值得作为固定动作。
需要注意两点。第一,发现API文档后先截图固定证据,再确认它需要的鉴权方式,很多文档页面本身是公开的,但文档背后的实际接口仍然有鉴权。第二,探测动作要适可而止,枚举出端点后先评估风险再决定是否深入,不要为了演示而发起大量未授权请求。接口探测这条思路的产出,往往直接决定最终是“有发现”还是“无发现”。
7. 实战经验:常见问题与避坑记录
7.1 扫描结果为空?先检查这五个地方
很多人在做完一轮路径扫描和信息收集后,报告“一无所获”,然后开始怀疑目标真的没有漏洞。根据我的经验,在提交这个结论前,至少先检查这五个地方:
第一,字典选择是否匹配目标技术栈,用纯PHP时代的字典去扫一个Java微服务系统,等于用中文词典考英文听力。第二,所有JS文件是否都下载完整并提取了接口,前端资源审计不彻底是最常见的漏项。第三,子域名结果是否做过IP关联,可能遗漏了同一IP上的旁站。第四,历史快照是否覆盖了目标上线早期的关键节点,早期页面信息价值最高。第五,常规接口端点是否用专门的字典跑过独立一轮,混在主字典里的接口路径会被大量无关请求淹没,命中率极低。
如果这五处都没问题,再考虑目标是否真的收缩了攻击面。我见过一些要求极高的系统,公网暴露面确实被压缩到了极致,但即便是这种系统,在关联资产和历史快照两个维度上依然有空间。换句话说,信息发现做到位了,“空白页”才真正可能是空的。
7.2 合规边界:信息发现不等于无限扩大授权
信息发现阶段技术门槛不高,真正考验人的是边界感。目录扫描扫出了内网地址段,要不要直接访问;历史快照里找到了一个云端存储链接,内容是目标系统的用户导出表,要不要拉取;这些情况在真实项目里都遇到过。我的处理原则是:只做授权范围内的主动验证,遇到明显超出授权范围的敏感数据,记录下来源和位置,停止深入,并写进报告让甲方决定下一步。作为安全测试人员,约束自己比发现漏洞更重要,这也是行业能够持续健康运转的基础。
7.3 信息沉淀:把每次发现变成可复用资产
最后说一个很多人忽视的点:信息发现不是一次性动作,而是笔积累的财富。每次测试我都把字典命中情况、JS接口提取结果、技术栈指纹、历史快照时间线记录在案,项目结束之后归档。长此以往,你手头会形成自己的“私有信息库”:哪个行业的系统常用什么路径命名习惯、哪类框架的默认文件有哪些、哪些接口命名模式在真实项目里命中率最高。这些经验书面上买不到,完全是在一次次空白页测试里攒出来的。下次再遇到新目标,你的初始扫描命中率会比第一次尝试时高出一大截。
说实话,能把“空白页”做出突破口的人,靠的从来不是运气,而是把每一种信息源都榨干、把每一条线索都认真验证的耐心。七种思路全走一遍之后,目标在你眼里就不再是一个空壳页面,而是一张已经画出了等高线的地形图。剩下的事情,就是沿着等高线找到那个最薄弱的下坡路。