Skip to content

SSRF via unauthenticated instance registration with arbitrary managementUrl #5452

@geo-chen

Description

@geo-chen

Summary

Spring Boot Admin Server allows any unauthenticated network caller to register an arbitrary application instance by sending a POST /instances request with a user-controlled healthUrl and managementUrl. The server immediately sends outbound HTTP requests to those URLs (health polling) and exposes a full HTTP proxy at /instances/{id}/actuator/** that forwards requests to the registered managementUrl. Because no authentication is required by default and no network-layer or IP-address validation is applied to the registered URLs, an attacker can force the SBA server to make HTTP requests to any address reachable from the server, including cloud metadata endpoints, intranet services, and the server itself.

Details

Spring Boot Admin (SBA) provides an admin UI for monitoring Spring Boot applications. Applications register themselves by sending POST /instances with a JSON body containing name, healthUrl, managementUrl, and serviceUrl.

No authentication by default. The spring-boot-admin-starter-server artifact does not include Spring Security. The official documentation states that SBA "doesn't ship a default" security configuration. This means POST /instances and GET /instances/{id}/actuator/** accept requests from any unauthenticated caller.

No URL validation. Registration.checkUrl() (Registration.java) only checks that the URL is syntactically valid and isAbsolute(). There is no check for private IP ranges (10.x, 172.16-31.x, 192.168.x, 169.254.x, 127.x, or IPv6 equivalents), hostnames that resolve to internal addresses, or scheme restrictions beyond HTTP/HTTPS.

Automatic outbound polling. After registration, StatusUpdater immediately sends GET {healthUrl} to determine the instance status, and does so repeatedly on a 10-second interval. EndpointDetector then sends GET {managementUrl} to discover actuator endpoints.

Actuator proxy. The InstancesProxyController (both servlet and reactive variants) exposes /instances/{id}/actuator/**. Every request to this path is forwarded verbatim to the registered instance's resolved endpoint URL with full response body returned to the caller.

Attack path:

  1. Attacker sends POST /instances with healthUrl: http://169.254.169.254/latest/meta-data/ and managementUrl: http://169.254.169.254/latest/meta-data
  2. SBA registers the instance (HTTP 201) and immediately sends GET http://169.254.169.254/latest/meta-data/ (health poll). On EC2 with IMDSv1, this returns instance metadata including IAM credentials.
  3. Attacker retrieves the response body via GET /instances/{id}/actuator/ which the proxy forwards to http://169.254.169.254/latest/meta-data/ and returns the cloud metadata.

Even when Spring Security is added (as recommended in the docs), the official sample configuration CSRF-exempts POST /instances so that client applications can auto-register. This means a cross-origin forged registration is possible against logged-in administrators, and any authenticated low-privilege user can register arbitrary management URLs that the SBA server will subsequently poll.

Key code locations:

  • Registration.java: checkUrl() -- validates only isAbsolute(), no IP check
  • AdminServerAutoConfiguration.java: instanceFilter() returns (instance) -> true (allow all)
  • StatusUpdater.java: polls Endpoint.HEALTH immediately after registration
  • InstancesProxyController.java (servlet + reactive): forwards all {instanceId}/actuator/** requests to the registered URL without re-validating the target

PoC

(available on request)

Impact

An unauthenticated remote attacker can:

  1. Force the SBA server to send HTTP GET requests to any URL reachable from the server, including cloud instance metadata services (AWS IMDSv1, GCP metadata, Azure IMDS), internal APIs, intranet hosts, and loopback interfaces.
  2. Retrieve full HTTP response bodies from those internal endpoints via the actuator proxy at /instances/{id}/actuator/**.
  3. Enumerate open ports by comparing HTTP 200 (open) vs HTTP 502 (closed) responses from the proxy.
  4. In environments where the SBA server has network access to sensitive internal services (database admin consoles, Kubernetes API, other microservices), pivot to those services.

On AWS EC2 with IMDSv1 enabled, the attacker can retrieve http://169.254.169.254/latest/meta-data/iam/security-credentials/ to obtain temporary IAM credentials. The vulnerability requires no authentication, no special permissions, and no user interaction beyond a single HTTP POST.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions