从信息搜集到漏洞验证:一次Web应用安全测试实战复盘
2026/7/3 13:20:28 网站建设 项目流程

1. 项目概述:一次真实的漏洞挖掘复盘

那次在某个SRC(安全应急响应中心)平台提交漏洞的经历,至今记忆犹新。不是什么惊天动地的零日漏洞,也不是复杂的逻辑链,但整个过程却像一次标准的“外科手术”,清晰地展示了从信息搜集到漏洞验证的完整链条。很多刚入门网络安全的朋友,总觉得漏洞挖掘高深莫测,需要掌握无数“黑科技”。其实不然,很多时候,一个能被有效利用的漏洞,恰恰源于对目标系统最基础、最细致的观察和理解。这次复盘,我就以一个真实的、已修复的案例为蓝本,拆解我当时完整的思路、使用的工具、踩过的坑,以及最终如何将一个看似平常的发现,转化为一个符合规范的漏洞报告。无论你是正在学习网络安全的学生,还是希望从渗透测试转向主动挖掘的安全工程师,希望这篇“战地笔记”能给你带来一些实实在在的启发。

漏洞挖掘,本质上是一场攻击者与防御者思维模式的对抗。你需要暂时放下“用户”的身份,以“建设者”和“破坏者”的双重视角去审视一个系统:它为什么这样设计?数据流向了哪里?哪些边界没有被充分校验?这次的目标是一个提供在线服务的Web应用,属于典型的B/S架构。我的核心目标很明确:在合规授权的范围内,寻找可能存在的安全缺陷,并证明其危害。

2. 漏洞挖掘的核心思路与前期准备

2.1 确立目标与范围界定

在开始任何技术操作之前,明确边界是重中之重。我这次的目标是一个企业级的在线文档协作平台。授权范围明确限定在该平台的公开演示环境(demo站点)和其提供的公开API接口。绝对不触碰任何用户数据、后台管理系统或其他未明确授权的子域名。这种自我约束不仅是法律和道德的要求,也能让你的测试过程更聚焦,避免在无关紧要的旁支上浪费精力。

注意:在没有获得明确书面授权的情况下,对任何系统进行漏洞测试都是非法的。务必通过正规渠道,如企业的SRC平台、众测项目或签订正式的渗透测试合同,获取测试许可。私自测试可能面临法律风险。

我的思路框架可以概括为“由外而内,由浅入深”:

  1. 信息搜集:不放过任何公开信息,包括子域名、关联IP、历史记录、使用的技术栈(框架、中间件、前端库等)。
  2. 攻击面测绘:基于搜集到的信息,绘制出所有可能的输入点(URL参数、表单、文件上传、API接口、请求头等)。
  3. 漏洞模式匹配:根据技术栈和功能点,推测可能存在的漏洞类型(如使用旧版本Struts可能存在RCE,富文本编辑器可能存在XSS)。
  4. 深度测试与验证:对高风险点进行手动+工具的深入测试,并准备完整的漏洞复现链。

2.2 信息搜集:比想象中更丰富的“开源情报”

很多人觉得信息搜集就是跑一下子域名扫描器,其实远不止于此。我习惯称之为“数字足迹梳理”。对于这个目标,我进行了以下几个层面的工作:

技术栈识别:使用Wappalyzer浏览器插件和WhatWeb命令行工具进行快速指纹识别。确认了前端主要使用 React,后端API疑似基于Java Spring Boot,Web服务器是Nginx,数据库标识不明显。这些信息至关重要,因为它直接决定了后续的测试重点。比如,针对Spring Boot,我会特别关注Actuator端点、SpEL表达式注入等;针对React,则要注意客户端路由和API接口的安全。

资产发现:

  • 子域名枚举:使用了subfinderamassassetfinder等多个工具进行交叉验证,避免单一工具的遗漏。发现了demo.example.comapi.example.comstatic.example.com等关键资产。
  • 端口与服务扫描:对主域名和关键子域名进行非全端口扫描(nmap -sS -sV -p 80,443,8080,8443,9000等)。重点是识别那些非80/443端口上开放的管理界面或调试接口。这次在api.example.com的8080端口发现了一个疑似Swagger UI的接口,这本身就是一个需要重点检查的攻击面。
  • 历史记录与归档:利用Wayback MachineArchive.org以及GitHub搜索公司名、项目名,寻找被删除但已被存档的页面、泄露的源码片段或配置文件。这次虽然没有找到源码,但发现了一个旧的测试页面路径,其中包含了对某个内部API的引用,这为后续的测试提供了线索。

目录与文件探测:使用dirsearchgobuster搭配精心准备的字典,对目标站点进行目录爆破。字典的选择很有讲究,我会结合技术栈(如Spring Boot的/actuator/env;PHP的/phpinfo.php)和常见的管理后台、备份文件后缀(如.bak.zip.tar.gz)进行定制。这一步发现了/admin(返回403)、/upload/api/v1/swagger.json等关键路径。

3. 攻击面分析与漏洞假设建立

完成信息搜集后,我得到了一张相对清晰的“目标地图”。接下来就是分析哪些地方最脆弱。

3.1 绘制功能点与数据流图

我手动浏览了demo站点的所有功能:用户注册/登录、文档创建/编辑/分享、评论、文件上传、个人资料设置。对于每个功能,我在笔记中简单绘制了其可能的数据流:

  • 输入点:表单字段、URL查询参数、JSON请求体、上传的文件、Cookie、HTTP头(如X-Forwarded-For)。
  • 处理环节:前端JS校验 -> 后端API接收 -> 业务逻辑处理 -> 数据库/存储操作 -> 响应返回。
  • 输出点:页面渲染、API响应、错误信息、导出的文件。

这个练习帮助我系统性地思考,而不是随机点击。例如,文档的“分享”功能,生成一个分享链接。这个链接的权限控制(是否可被未登录用户访问?是否有时效?)就是一个潜在的逻辑漏洞点。

3.2 基于技术栈的漏洞假设

结合之前识别的技术栈(Spring Boot, React, Nginx),我列出了优先测试的漏洞假设清单:

  1. 身份认证与授权漏洞

    • 水平越权:能否通过修改/api/v1/docs/{id}中的{id},访问或修改其他用户的文档?
    • 垂直越权:普通用户能否访问/admin下的功能(即使返回403,某些API接口可能未校验)?
    • JWT令牌问题:如果使用JWT,是否未校验签名?算法是否为none?密钥是否弱?
  2. 注入类漏洞

    • SQL注入:虽然现代框架使用ORM能防住大部分,但复杂的查询、排序参数(order by)、报表功能仍是高风险区。
    • NoSQL注入:如果后端使用MongoDB等,查询参数可能存在注入。
    • 命令注入:文件上传后的处理、服务器信息查询等功能点。
    • SSRF(服务器端请求伪造):Webhook设置、头像URL设置、文档内图片URL导入等功能。
  3. 客户端漏洞

    • XSS(跨站脚本):富文本编辑器、评论框、个人资料页(用户名、简介)、文档内容渲染。特别注意React应用中的DOM型XSS。
    • CSRF(跨站请求伪造):关键操作(修改邮箱、删除文档)是否缺少CSRF Token或同源校验?
  4. 配置与信息泄露

    • Spring Boot Actuator:检查/actuator/actuator/env/actuator/heapdump等端点是否暴露敏感信息(数据库密码、API密钥)。
    • 调试接口:类似Swagger UI (/v2/api-docs,/swagger-ui.html) 是否未授权访问,甚至允许直接调用接口?
    • 敏感文件泄露.git目录、.DS_Store、备份文件、配置文件(.yml,.properties)。

4. 实操过程:从假设到验证

有了清晰的攻击面列表,我开始进行手动测试,并辅以工具进行批量验证和深度探测。

4.1 越权漏洞的挖掘与验证

我首先注册了两个测试账号:userAuserB。用userA创建一篇文档,获得文档ID为doc_123。用userB登录后,直接尝试访问GET /api/v1/docs/doc_123

第一次尝试:返回{"error": "Document not found"}。这看起来是安全的,但不要轻易放弃。我检查了请求和响应,发现后端可能进行了权限校验,返回了统一的“未找到”信息,以避免信息泄露(这是好的实践)。

转换思路:我注意到文档分享功能。userA生成一个分享链接,形如https://demo.example.com/share/abc123def。我用userB访问这个链接,可以正常查看。那么,这个分享链接的权限模型是什么?是“知道链接即可访问”,还是“仅指定用户可访问”?

关键测试:我以userB的身份,尝试调用“修改文档内容”的API,但将请求中的文档ID替换为doc_123userA的文档),同时在请求头中携带userA生成的分享链接中的某个Token(假设为share_token=abc123def)。我构造的请求如下:

PUT /api/v1/docs/doc_123/content HTTP/1.1 Host: api.example.com Authorization: Bearer <userB's_JWT> Content-Type: application/json X-Share-Token: abc123def { "content": "Hacked by userB via share token!" }

实操心得:在测试越权时,不要只测试“读”越权(水平/垂直),更要测试“写”越权。同时,关注所有与对象关联的令牌(Token)、密钥(Key)、链接,它们有时会被错误地用于授权校验,而非单纯的访问控制。

结果:服务器返回了200 OK,并且文档内容被成功修改!这是一个典型的基于令牌的权限绕过漏洞。后端逻辑可能是:当请求中包含有效的X-Share-Token时,系统误认为该令牌赋予了用户对文档的完全编辑权限,而忽略了实际调用者(userB)是否是该文档的拥有者。正确的逻辑应该是,分享令牌仅用于绕过“读”权限的验证,对于“写”操作,必须严格校验当前用户是否为文档所有者或有明确的协作编辑权限。

4.2 接口未授权访问与信息泄露

根据信息搜集阶段发现的api.example.com:8080路径,我直接访问了http://api.example.com:8080/swagger-ui.html。果然,一个完整的Swagger UI界面展现在眼前,而且没有任何认证。这意味着攻击者可以:

  1. 浏览所有API接口的详细定义,包括参数、数据结构。
  2. 直接在界面上调用这些接口,进行增删改查操作。

我立即尝试了几个看起来敏感的接口:

  • GET /api/internal/users:返回了所有注册用户的邮箱和昵称列表(用户信息泄露)。
  • GET /api/internal/config:返回了数据库连接字符串(明文密码)、第三方API密钥等核心配置信息(严重信息泄露)。
  • POST /api/internal/cache/clear:成功调用,清除了应用缓存(服务干扰)。

这个漏洞的根源在于开发/测试环境与生产环境的配置混淆。Swagger UI这类调试工具本不应该部署在公开的生产或演示环境中,即使部署,也必须施加严格的访问控制(如IP白名单、基础认证)。

4.3 对文件上传功能的深度测试

目标平台允许用户上传头像和文档附件。我首先测试了常见的绕过手段:

  1. 前端绕过:修改前端JS或直接发送POST请求,上传.php.jsp后缀文件。结果被后端拦截,返回“文件类型不允许”。
  2. 双写后缀、大小写绕过:如test.pHptest.php.jpg。同样被拦截。
  3. 修改Content-Type:将image/jpeg改为image/jpgtext/plain。无效。

看起来有基础防护。我转而分析响应。上传一个正常图片后,返回的JSON中包含一个文件访问URL,如https://static.example.com/uploads/2023/10/27/abcdefg.jpg。我注意到路径中似乎没有使用原文件名,而是用哈希值重命名了,这通常是安全的做法。

新的突破口:我尝试上传一个包含SVG格式的XML文件(test.svg),内容为:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="300"> <script>alert(document.domain)</script> <rect width="100%" height="100%" fill="red"/> </svg>

上传成功!返回的URL是https://static.example.com/uploads/.../hashvalue.svg。当我直接在浏览器中打开这个URL时,JavaScript弹窗成功触发,显示了static.example.com。这是一个存储型XSS漏洞,但由于SVG文件被当作静态资源托管在独立的子域名下,其JavaScript执行环境受到同源策略的限制,危害相对有限(只能攻击同域下的其他资源,无法直接窃取主站cookie)。但这仍然是一个安全风险,如果该静态域名下托管了其他敏感应用,就可能构成威胁。

注意事项:文件上传漏洞的测试,绝不能只盯着“获取服务器权限”。上传恶意SVG、HTML、PDF文件导致的XSS、SSRF(如果文件内容会被解析并发起网络请求)也是常见的利用场景。同时,要关注文件存储的位置、URL的生成规则以及后续的访问策略。

5. 漏洞利用链构建与报告撰写

单个漏洞的危害可能有限,但组合起来就可能产生更大的影响。例如,结合发现的信息泄露漏洞(Swagger UI)和越权漏洞,可以构造更精准的攻击。

5.1 构建简单的利用链

场景:攻击者首先访问未授权的Swagger UI (/swagger-ui.html),通过GET /api/internal/users接口获取到目标用户(如管理员admin@example.com)的信息。然后,利用水平越权漏洞(如果存在),尝试遍历或猜测该管理员的文档ID并进行访问或篡改。虽然这个例子中越权漏洞需要分享令牌,但它说明了思路:信息泄露为后续攻击提供了“弹药”。

5.2 编写高质量的漏洞报告

找到漏洞只是成功了一半,清晰、专业地报告漏洞同样重要。一份好的报告能帮助开发人员快速理解和修复问题。我的报告通常包含以下部分:

1. 漏洞标题:简明扼要,如“X-Share-Token请求头导致文档编辑权限绕过”。2. 风险等级:根据CVSS标准或平台规则评估(如中危、高危)。3. 影响范围:明确指出受影响的URL、接口、功能模块。4. 详细描述: -漏洞位置:完整的API端点URL和HTTP方法。 -重现步骤:一步一步,像教程一样清晰。我会提供: - 测试账号信息(可在测试环境注册)。 - 具体的HTTP请求包(用代码块展示,包含所有Header和Body)。 - 每一步的预期结果和实际结果。 -请求/响应示例:提供原始的Burp Suite抓包或cURL命令。5. 漏洞原理:简要分析后端可能存在的逻辑缺陷。6. 修复建议:给出具体、可操作的方案。例如: - 对于越权漏洞:“在执行文档编辑操作前,应首先验证当前用户身份(通过Session或JWT),并判断其是否为文档所有者或拥有编辑权限的协作者。X-Share-Token等令牌应仅用于验证查看权限,且其权限范围需在服务端明确界定和校验。” - 对于未授权访问:“立即将Swagger UI等调试接口从生产/演示环境移除,或配置严格的访问控制(如IP白名单、强制身份认证)。” - 对于文件上传XSS:“对上传的SVG文件进行内容安全检查,过滤或转义<script>等危险标签;或设置静态资源服务器的响应头Content-Type: image/svg+xml而不执行其中的脚本(但浏览器兼容性需测试);最佳实践是将用户上传的所有文件存储在无法执行脚本的对象存储服务中,并通过CDN分发。”7. 其他信息:测试时间、使用的浏览器/工具版本等。

6. 常见问题、排查技巧与防御思考

6.1 漏洞挖掘中的常见困境与突破

  1. 遇到WAF(Web应用防火墙)怎么办?

    • 慢速攻击:调整请求速率,使用延时。
    • 混淆编码:对Payload进行多次URL编码、Unicode编码、HTML实体编码等。
    • 参数污染:同一个参数多次出现(如id=1&id=2),WAF和后端解析可能不一致。
    • 更换请求方法:GET、POST、PUT、DELETE等交替尝试,有时WAF规则对某些方法监控不严。
    • 利用协议特性:如HTTP参数污染(HPP)、分块传输编码(Chunked)绕过。
    • 终极方案:理解WAF规则的本质是模式匹配,寻找其规则库的盲区,或者直接测试逻辑漏洞,这类漏洞往往不依赖特殊字符,WAF难以防御。
  2. 黑盒测试感觉无从下手?

    • 坚持“输入-输出”分析:找到每一个用户可控的输入点,观察系统对正常输入和异常输入的反应。错误信息、响应时间差异、返回数据的变化都是线索。
    • 对比分析:注册两个账号,对比相同操作下请求与响应的差异。这有助于发现水平越权。
    • 关注业务逻辑:充值1元能否修改为-1元从而增加余额?优惠券能否重复使用?密码重置流程的6位验证码能否暴力破解?逻辑漏洞的挖掘更依赖于对业务的理解。
  3. 工具扫描结果很多,如何筛选?

    • 优先验证“中危”及以上:但不要完全相信工具的分类。
    • 关注“信息泄露”类:这些往往是进一步攻击的跳板。
    • 手动验证每一个“疑似”点:工具报的SQL注入、XSS很多是误报,但手动测试可能发现盲注或更复杂的触发场景。
    • 结合上下文:在登录后的功能模块里发现的漏洞,价值通常高于未授权区域的漏洞。

6.2 从攻击者视角看防御

这次挖掘经历也让我从防御角度有了更深的体会:

  1. 最小权限原则:每个功能、每个接口的权限必须划分清晰。分享链接就是“只读”权限,绝不能隐含“编辑”权。用户只能访问自己的数据,后端必须在每次数据访问时进行所有权校验。
  2. 默认拒绝:对于管理接口、调试接口、监控端点,默认配置应该是禁止外部访问。必须通过显式的、安全的配置来开放。
  3. 输入校验与输出编码:前端校验是为了用户体验,后端校验是为了安全。所有用户输入必须经过白名单或严格规则的校验。所有输出到前端的数据,都要根据上下文进行HTML编码、URL编码等,以防XSS。
  4. 安全的错误处理:不要向用户返回详细的堆栈信息、数据库错误。统一返回模糊的错误提示,如“操作失败”。
  5. 依赖组件安全管理:定期更新框架、库、中间件。使用已知存在漏洞的组件(如旧版Fastjson、Log4j2)是极其危险的。
  6. 安全意识培训:让开发人员了解常见漏洞原理,在代码编写阶段就避免安全问题,比事后修补成本低得多。

漏洞挖掘是一个需要耐心、细心和系统化思维的过程。它不像电影里演的那样充满炫技,更多的是枯燥的信息搜集、反复的测试验证和严谨的逻辑推理。每一次成功的挖掘,都是对目标系统一次更深层次的理解。对于防御方而言,理解攻击者的这些常规思路和手法,正是构筑更坚固安全防线的起点。真正的安全,始于对细节的敬畏和对所有“可能性”的审视。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询