Spring WebMvc.fn路由解析与权限绕过浅析
字数 2638 2025-08-20 18:18:10
Spring WebMvc.fn路由解析与权限绕过分析
0x00 前言
Spring WebMvc.fn是Spring Web MVC的一部分,提供了一种轻量级的函数式编程模型,允许开发者使用函数来定义路由和处理HTTP请求。这种模型是注解编程模型的替代方案。
在WebMvc.fn中:
- HTTP请求由
HandlerFunction处理 - 这是一个接收
ServerRequest并返回ServerResponse的函数 - 一般通过
RouterFunctions.route()方法进行处理
示例代码:
@Configuration
public class PersonHandlerConfiguration {
@Bean
public RouterFunction<ServerResponse> person() {
return route().GET("/person", request -> {
return ServerResponse.status(HttpStatus.OK).body("Hello World");
}).build();
}
}
0x01 WebMvc.fn路由解析过程
核心解析流程
-
DispatcherServlet处理:Spring MVC接收到请求时,Servlet容器调用
DispatcherServlet的service方法 -
请求方法分发:根据请求方法调用对应的
processRequest方法(如GET请求调用doGet方法) -
HandlerMapping查找:在
doDispatch方法中循环调用HandlerMapping的getHandler方法- WebMvc.fn使用
RouterFunctionMapping
- WebMvc.fn使用
-
RouterFunctionMapping处理:
- 检查
this.routerFunction是否不为null - 使用
HttpServletRequest创建ServerRequest对象 - 使用
routerFunction.route(request)路由请求 - 尝试匹配
ServerRequest与RouterFunction中定义的路由规则
- 检查
-
路由匹配:
- 调用
org.springframework.web.servlet.function.RouterFunctionBuilder#route方法 - 遍历路由函数
routerFunctions的route方法 - 找到第一个与当前请求匹配的路由,返回相应的
HandlerFunction
- 调用
-
请求规则检查:
RequestPredicates定义请求规则(请求参数、请求方式等)- 调用
DefaultRouterFunction#route方法 - 通过
this.predicate.test(request)检查路由函数的Predicate是否匹配
-
路径匹配:
- 检查请求方法是否在路由函数的方法集合中
- 通过
PathPattern的matchAndExtract方法进行请求路径匹配
多RouterFunction处理
当容器中有多个RouterFunction类型的bean时:
DifferentComposedRouterFunction会逐层包装所有RouterFunction- 调用
DifferentComposedRouterFunction#route方法 - 递归调用最终到达配置类中定义的
BuiltRouterFunction#route
静态资源解析
RouterFunctions可以通过PathResourceLookupFunction处理静态资源请求,将请求路径映射到文件系统中的资源。
解析流程:
- 调用
ResourcesRouterFunction#route方法 - 实际调用
org.springframework.web.servlet.function.PathResourceLookupFunction#apply方法 - 检查请求路径是否与定义的路由模式匹配
- 提取模式内的路径部分
- 对路径进行处理(若包含
%则进行URL解码) - 检查路径合法性
- 创建
Resource对象并检查可读性和位置安全性
路径安全检查:
- 检查是否包含
WEB-INF或META-INF - 检查是否是有效的URL(如
classpath:) - 检查是否包含
..(路径遍历尝试) - 使用
StringUtils.cleanPath(path)处理路径
0x02 RouterFunctionMapping权限绕过分析
基本绕过思路
-
路径解析特性:
- 使用
request.requestPath().pathWithinApplication获取请求路径 - 移除URL路径中的分号
- 对URL编码进行解码操作
- 识别请求path尾部额外的
/
- 使用
-
变形路径示例:
/person/person//person%2f/person%252f(双重编码)
静态资源访问控制绕过
案例场景:通过RouterFunction定义路由,使用filter对特定路径下特定后缀文件进行权限控制。
示例配置:
@Configuration
public class LogRouter {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
@Bean
RouterFunction staticResourceLocator(){
return RouterFunctions.resources("/log/**", resolver.getResource("file:///usr/local/tomcat/logs/"));
}
}
绕过分析:
-
URL解码过程:
- 原始请求路径包含
%时,会进行一次URL解码 - 在
ResourceUtils#getFile方法中,通过URI对象的getSchemeSpecificPart方法再做一层解码 - 实际请求时会对路径解码两次
- 原始请求路径包含
-
安全检查限制:
#会被替换为URL编码,无法使用file:///path/file.log#png方式绕过后缀匹配- 路径中不能包含
../等穿越符
-
双重编码绕过:
- 通过双重URL编码可以绕过权限控制
- 示例:读取
catalina.out文件- 原始路径:
/log/catalina.out - 双重编码:
/log/catalina%252eout
- 原始路径:
通用鉴权措施绕过
对于使用类似Shiro/Spring Security等通用鉴权措施:
- 利用不同场景下的解析差异
- 结合路径变形和编码方式
0x03 安全建议
-
使用内置安全机制:
- 使用路由函数生成器上的
before、after或filter方法 - 示例:
return route() .GET("/person", request -> {...}) .before(request -> { // 认证逻辑 return request; }) .build();
- 使用路由函数生成器上的
-
路径处理建议:
- 严格校验请求路径
- 避免依赖单一的安全检查
- 对资源访问实施多层验证
-
静态资源控制:
- 限制文件系统访问范围
- 实施严格的路径规范化检查
- 考虑使用白名单机制
-
编码处理:
- 统一编码解码处理流程
- 避免多次解码导致的安全问题
-
版本更新:
- 保持Spring框架最新版本
- 关注安全公告和补丁
总结
Spring WebMvc.fn提供了灵活的路由定义方式,但在路径处理和权限控制方面存在潜在风险。开发者需要充分理解其路由解析机制,特别注意路径变形和编码带来的安全问题,实施多层次的安全防护措施。