攻防实录:从 Swagger 泄露到内网漫游,一条完整的攻击链
攻防实录:从 Swagger 泄露到内网漫游,一条完整的攻击链
本文首发于白帽江湖,记录一次市级政务攻防演练实战经历。所有漏洞均已修复,敏感信息已脱敏处理。
一、背景
2026 年 5 月,某地组织了年度网络安全攻防演练。作为攻击方,我们面对的是一张覆盖各级政府单位、医疗机构、公共服务平台的复杂网络。
本次演练的核心目标是某基层治理政务服务平台——一个基于 RuoYi-Vue 框架搭建的管理系统,承担着基层组织和事件调度职能。
除此之外,我们还对某医院门户网站、教育信息化平台以及多个企业资产进行了全面测试。
本文将从攻击方的视角,完整复盘这次攻防实战中的技术细节、攻击链设计和心得体会。
二、信息收集:摸清家底是成功的一半
资产测绘
一口吃不成胖子,我们先做资产盘点。利用子域名枚举、端口扫描、指纹识别等手段,逐步勾勒出目标的攻击面。
使用的工具链:
子域名 → Subfinder + 手动DNS枚举
端口 → Naabu(Top 1000)
指纹 → EHole + WhatWeb + httpx
路径 → ffuf + 手工验证
高价值目标一览
在扫描过程中,我们发现了一批有意思的目标:
| 目标 | 关键发现 |
|---|---|
| 政务服务平台 | RuoYi-Vue, Swagger 泄露 |
| 医院门户 | DedeCMS + 创宇盾 WAF |
| 企业集群 | 多个 Spring Boot, Druid/Swagger |
| 多服务主机 | Zabbix 5.0.18 + KubeSphere 3.1.1 |
| 设备网关 | beego 框架 API |
三、突破口:Swagger 泄露,142 个接口全裸奔
这是整场演练中最简单但也最致命的漏洞。
访问 Swagger UI 页面,Knife4j 的界面直接呈现在眼前。再访问 API Docs 端点,完整的 Swagger 文档 JSON 被原样返回。
GET /prod-api/v2/api-docs
→ 200 OK
→ 33,278 行的 JSON,包含 142+ 个 API 接口定义
暴露了哪些信息?
- 所有后端 API 的路径、HTTP 方法、请求参数格式
- 数据模型的字段定义(包含
password、phoneNo、idCard等敏感字段名) - 用户管理、角色管理、部门管理、文件上传/下载等核心接口
- Test Controller 测试接口(开发环境未清理)
- 系统配置、操作日志、登录日志等审计接口
更关键的是,这个系统是 RuoYi-Vue 框架——国内使用量极大的开源后台管理框架。一旦 Swagger 泄露,攻击者可以针对 RuoYi 的常见配置和默认行为精准构造攻击载荷。
为什么这很致命?
因为 Swagger 文档不仅暴露了路径,还暴露了哪些接口不需要认证。我们通过分析文档中的 @Security 注解和实际响应,找到了三个未授权接口。
四、组合拳:未授权接口利用链
4.1 手机号枚举接口
GET /prod-api/phone/code?phoneNo=138xxxx8000
→ 500 {"msg":"138xxxx8000"}
这个接口不需要任何认证。虽然短信服务当时处于故障状态(返回 500),但理论上攻击者可以:
- 枚举已注册手机号(根据响应差异区分)
- 向任意手机号发送验证码短信(SMS 轰炸)
- 结合登录接口完成无密码登录
4.2 手机号登录接口
POST /prod-api/phone-pc-login
Body: {"username":"138xxxx8000","code":"000000"}
→ 200 {"token":"eyJhbGciOiJIUzUxMiJ9..."}
这个接口同样不需要任何认证。API 文档上标注了需要 @Security Authorization,但实际后端并没有强制执行。这是一个典型的"文档写了安全控制,代码没实现"的案例。
如果短信服务正常,攻击链非常清晰:
枚举手机号 → 获取短信验证码 → 调用登录接口 → 获取 JWT Token → 访问全量 API
4.3 微信登录接口
POST /prod-api/login-wx
Body: {"jsCode":"test"}
→ 200 {"msg":"操作成功","code":200}
微信小程序登录接口也完全未授权。虽然需要一个有效的微信 jscode 才能拿到真正的 Token,但接口的暴露本身就给了攻击者利用微信 OAuth 流程的空间。
4.4 地图 API Key 硬编码
在前端源码中发现了硬编码的地图 API Key:
curl https://target:8090/ | grep map_api
→ 32位十六进制 Key
这类问题虽不致命,但可能导致第三方 API 配额被盗用。
五、防不胜防:Vue 路由鉴权绕过
这是整场演练中最有意思的发现之一。
RuoYi-Vue 的前端路由配置中有一些路由的 hasAuth: false,意味着它们不需要登录就能访问:
| 路由 | 说明 |
|---|---|
/data-large-screen |
数据大屏 |
/ceshi |
测试页面 |
我们尝试访问:
GET /data-large-screen
→ 200 OK(返回了页面 HTML!)
更关键的是,数据大屏页面中很可能嵌入了后端 API 调用。如果这些后端 API 也"像前端一样"相信了大屏页面不需要鉴权,那就是一个新的突破口。
这种前端路由鉴权与后端 API 鉴权的割裂是一个常见但容易被忽视的问题。Vue Router 的 beforeEnter 守卫只是前端控制,真正的安全必须在后端实施。
六、WAF 对抗:创宇盾的攻防博弈
攻防演练中,我们遇到了创宇盾 CloudWAF(通过 CDN 接入)。这台 WAF 的特征识别相当精准:
- SQL 注入关键词(
and、or、union、select)→ 直接拦截 - 路径穿越(
../)→ 连接断开(RST) .git路径 → 规则 ID 40002 专门拦截- 单引号 → 403 拦截
我们尝试了多种绕过方式:
| 绕过方法 | 效果 |
|---|---|
| URL 编码 | 绕过 WAF,但路径本身 404 |
X-Forwarded-For: 127.0.0.1 |
部分路径 403 → 404(证明路径不存在) |
| HTTP 参数污染 (HPP) | WAF 拦截 |
| 大小写混淆 | WAF 拦截 |
一个重要发现:WAF 对 /druid/、/actuator/、/swagger-ui/ 等路径返回的 403,在添加 X-Forwarded-For 后变为 404。这告诉我们——之前的 403 是 WAF 的主动封锁,不是服务器上真有这些资源。这对判断目标实际情况很有帮助。
七、意外收获:其他高价值资产
在攻防演练中,我们还发现了几个意外的高价值目标:
Zabbix 5.0.18
某主机上的 Zabbix 5.0.18 存在多个已知漏洞(CVE-2022-23131 SAML SSRF、CVE-2023-32722 SQLi)。API 端点设置了 Access-Control-Allow-Origin: *,任何网站都可以跨域调用它。
KubeSphere v3.1.1
同一台机器上跑着 KubeSphere v3.1.1(Kubernetes v1.19.8),版本信息中的 "dirty" 标记暗示源码被定制修改过,可能引入额外风险。
GeoServer 默认密码
某 GeoServer 实例存在默认管理员登录:
URL: /geoserver/j_spring_security_check
凭证: admin/geoserver(默认)
用友 U8C
发现了用友 U8C 系统、增值税发票系统等多个 Spring Boot 应用,它们的 actuator、Druid、Swagger 端点均暴露在公网。
八、战绩汇总
政务服务平台
| 漏洞 | 类型 |
|---|---|
| Swagger 142 个 API 泄露 | 信息泄露 |
| 短信接口未授权 | 接口安全 |
| 手机登录接口未授权 | 未授权访问 |
| 微信登录接口未授权 | 信息泄露 |
| 地图 API Key 泄露 | 信息泄露 |
| Nginx 版本泄露 | 信息泄露 |
| 测试控制器暴露 | 信息泄露 |
| 安全配置缺失 | 安全配置 |
医院门户(12 项)
| 等级 | 数量 | 关键问题 |
|---|---|---|
| 高危 | 2 | 数据库端口公网暴露、大量端口开放 |
| 中危 | 4 | 源码目录泄露嫌疑、CSP 缺失、WAF 绕过 |
| 低危 | 3 | robots.txt 缺失、CDN 信息泄露 |
其他资产
- GeoServer 默认密码(直接获取系统权限)
- 多个 Spring Boot 敏感端点暴露
- Zabbix/KubeSphere 版本信息泄露
九、总结与感悟
给防守方的建议
Swagger / Knife4j 一定要关! 生产环境暴露 API 文档是安全界的常识,但 RuoYi 这类框架的项目中依然普遍存在。建议通过 Spring Profile 隔离环境,或通过 nginx 限制访问来源。
前后端鉴权要统一。前端路由加守卫不等于后端 API 安全。Vue 的
hasAuth: false只是前端的展示逻辑,后端必须独立鉴权。API 文档的 @Security 注解不是安全门。我们遇到的两个接口都在文档标注了需要 Authorization,但实际代码没实现。文档是文档,代码是代码,必须保证它们一致。
WAF 不是万能药。创宇盾虽然能拦截大部分注入攻击,但对 Swagger 泄露、API Key 硬编码这类信息泄露问题无能为力。安全需要多层防御。
CDN ≠ 绝对安全。通过子域名枚举找到了真实源 IP,虽然配置了白名单,但公网端口扫描仍然可以获取大量信息。
给攻击方的参考
- Swagger 永远值得先试。先试
/doc.html,再试/v2/api-docs、/v3/api-docs、/swagger-resources,低成本高回报。 - 关注框架的"默认配置"。RuoYi-Vue、Spring Boot 都有很多默认行为,了解它们能在渗透中事半功倍。
- WAF 绕过的重点是信息收集。搞清楚 WAF 到底在保护什么(真的存在还是假的 403),能避免浪费时间。
- 攻击链要完整。每个阶段都要为下一阶段做准备:信息收集 → 识别突破口 → 获取凭证 → 横向移动。
这次演练让我深刻体会到:安全不是一个点的加固,而是一条链的防护。防守方可能在某个点上做得很强(比如 WAF 拦截了所有注入),但只要链条上有一环薄弱(比如 Swagger 泄露、接口未授权),整个防线就会被攻破。
共勉。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发。也欢迎在评论区交流你的攻防实战经验!
温馨提示:本文内容仅用于合法授权的安全学习与研究交流,严禁用于未授权渗透测试、漏洞利用或任何违法行为。
涉及企业或平台的未公开漏洞信息,请遵循负责任披露原则,勿公开传播可直接复现的敏感细节。
如存在侵权、错误信息或不当内容,请联系站方处理,我们将及时核实并删除。邮箱:admin@baimaojianghu.com。
