攻防实录:从 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 方法、请求参数格式
  • 数据模型的字段定义(包含 passwordphoneNoidCard 等敏感字段名)
  • 用户管理、角色管理、部门管理、文件上传/下载等核心接口
  • 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 注入关键词(andorunionselect)→ 直接拦截
  • 路径穿越(../)→ 连接断开(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 版本信息泄露

九、总结与感悟

给防守方的建议

  1. Swagger / Knife4j 一定要关! 生产环境暴露 API 文档是安全界的常识,但 RuoYi 这类框架的项目中依然普遍存在。建议通过 Spring Profile 隔离环境,或通过 nginx 限制访问来源。

  2. 前后端鉴权要统一。前端路由加守卫不等于后端 API 安全。Vue 的 hasAuth: false 只是前端的展示逻辑,后端必须独立鉴权。

  3. API 文档的 @Security 注解不是安全门。我们遇到的两个接口都在文档标注了需要 Authorization,但实际代码没实现。文档是文档,代码是代码,必须保证它们一致。

  4. WAF 不是万能药。创宇盾虽然能拦截大部分注入攻击,但对 Swagger 泄露、API Key 硬编码这类信息泄露问题无能为力。安全需要多层防御。

  5. 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。