SpringWeb中获取路径前缀的方式与潜在的权限绕过风险
字数 1019 2025-08-18 11:35:44
Spring Web 中路径前缀获取方式与权限绕过风险分析
1. 背景与问题概述
在 Spring Web 应用中,路径前缀(Context Path)是 Web 应用部署时的基础路径,通常用于区分同一服务器上部署的不同应用。在权限控制场景中,路径前缀的正确处理至关重要,因为:
- 权限系统通常基于完整路径进行访问控制
- 路径前缀处理不当可能导致权限绕过风险
- 不同环境下(开发/测试/生产)路径前缀可能不同
2. Spring Web 中获取路径前缀的方式
2.1 通过 HttpServletRequest 获取
// 获取 context path (包含结尾斜杠)
String contextPath = request.getContextPath();
// 获取 servlet path (不包含 context path)
String servletPath = request.getServletPath();
// 获取 path info (位于 servlet path 之后)
String pathInfo = request.getPathInfo();
// 获取完整请求 URI (包含 context path)
String requestURI = request.getRequestURI();
2.2 通过 Spring 工具类获取
import org.springframework.web.util.WebUtils;
// 获取相对于 context path 的路径
String pathWithinApplication = WebUtils.getPathWithinApplication(request);
2.3 通过 Spring MVC 的 HandlerMapping 常量
// 获取原始路径(包含 context path)
String lookupPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
2.4 通过 UrlPathHelper 工具类
import org.springframework.web.util.UrlPathHelper;
UrlPathHelper pathHelper = new UrlPathHelper();
// 获取 context path
String ctxPath = pathHelper.getContextPath(request);
// 获取 lookup path (不包含 context path)
String lookupPath = pathHelper.getLookupPathForRequest(request);
3. 路径处理中的常见问题
3.1 路径拼接问题
错误示例:
String fullPath = request.getContextPath() + "/api/resource";
// 当 contextPath 为 "/app" 时,会得到 "/app//api/resource" (双斜杠)
正确做法:
String fullPath = request.getContextPath() + "api/resource";
// 或者使用 UriComponentsBuilder
3.2 路径标准化问题
Spring 默认会对路径进行标准化处理(移除多余的斜杠、路径遍历符等),但某些情况下需要手动处理:
import org.springframework.web.util.UriUtils;
String normalizedPath = UriUtils.encodePath(path, "UTF-8");
4. 权限绕过风险分析
4.1 风险场景
- 路径前缀不一致:开发环境使用空前缀,生产环境使用非空前缀
- 路径解析差异:权限系统与应用系统解析路径方式不同
- 路径标准化差异:不同组件对路径标准化的处理不一致
4.2 典型漏洞模式
-
双斜杠绕过:
/app//admin/ → 可能被解析为 /admin/ -
路径遍历绕过:
/app/../admin/ → 可能被标准化为 /admin/ -
大小写混淆:
/App/admin/ 与 /app/admin/ 可能被视为不同路径 -
URL 编码混淆:
/app/%61dmin/ → 解码后为 /app/admin/
5. 安全防护建议
5.1 统一路径获取方式
在整个应用中统一使用一种路径获取方式,避免混合使用不同方法。
5.2 显式配置 Context Path
在 application.properties 中明确配置:
server.servlet.context-path=/myapp
5.3 权限校验实现建议
// 获取标准化后的完整路径
String requestPath = new UrlPathHelper().getPathWithinApplication(request);
// 或者使用 Spring Security 的 AntPathMatcher
AntPathMatcher pathMatcher = new AntPathMatcher();
boolean match = pathMatcher.match("/admin/**", requestPath);
5.4 防御性编程
// 路径标准化处理
private String normalizePath(String path) {
path = StringUtils.trimWhitespace(path);
path = StringUtils.cleanPath(path); // 处理路径遍历
if (!path.startsWith("/")) {
path = "/" + path;
}
return path.toLowerCase(); // 可选:统一小写处理
}
6. 测试验证方法
- 双斜杠测试:
/app//admin/ - 路径遍历测试:
/app/../admin/ - 大小写测试:
/App/admin/ - URL 编码测试:
/app/%61dmin/ - 后缀测试:
/app/admin.jsp - 空路径测试:
/app//
7. 总结
正确处理 Spring Web 中的路径前缀对于应用安全至关重要,特别是在权限控制场景中。开发者应当:
- 理解并统一使用一种路径获取方式
- 对路径进行标准化处理
- 在权限校验时考虑各种路径变形情况
- 在不同环境中测试路径处理逻辑
通过规范化的路径处理和严格的权限校验,可以有效避免因路径前缀处理不当导致的权限绕过风险。