Spring框架路由解析过程及安全绕过手法分析
前言
Spring框架作为Java生态中最流行的Web应用框架之一,其路由处理机制一直是安全研究的重点。历史上许多绕过漏洞都源于对路由解析机制的深入理解,特别是不同框架(如Shiro和Spring)对路由解析的差异。本文将从Spring框架的路由解析过程入手,分析其内部处理逻辑,并探讨可能的绕过手法。
Spring路由解析核心过程
1. 路由分发入口
Spring MVC模式中,路由分发由doDispatch方法处理,其中关键步骤是通过getHandler方法从handlerMappings中获取处理器。
2. getPathWithinApplication方法
这是Spring处理路径的核心方法之一,返回的path由contextPath和requestUri组成。
处理流程:
- getContextPath方法:对路由进行初步处理,通常会进行URL解码,但一般返回null
- getRequestUri方法:获取URI后进行进一步处理
- decodeAndCleanUriString方法:关键处理点,包含两个主要功能:
- URL解码
- 处理分号(
;)内容
removeSemicolonContent方法详解
该方法负责删除分号(;)和斜杠(/)之间的内容。处理逻辑如下:
- 寻找第一个
;的位置 - 从
;位置开始寻找下一个/ - 删除
;和/之间的内容 - 循环处理直到字符串结束
示例:
输入字符串:/example;param=value/test;id=123
-
第一次循环:
- 找到第一个
;(位于"/example;") - 找到下一个
/("/test") - 删除
;param=value,结果为/example/test;id=123
- 找到第一个
-
第二次循环:
- 找到第二个
;(位于"/test;") - 找到字符串结束
- 删除
;id=123,结果为/example/test
- 找到第二个
getSanitizedPath方法
该方法负责路径的"净化"处理,主要功能包括:
- 替换连续的斜杠(
//)为单斜杠(/) - 其他路径标准化处理
3. usesPathPatterns为true时的处理
当usesPathPatterns为true时,主要处理逻辑仍在removeSemicolonContent方法,但存在以下差异:
- 缺少对URL解码的处理
- 缺少对
//的替换处理
4. getPathWithinServletMapping方法
当alwaysUseFullPath不为真时,会调用此方法。在Spring 2.3.0.RELEASE及以下版本中,会进行标准化处理,包括对../这类路径的处理。
绕过手法分析
1. URL编码绕过
适用场景:鉴权逻辑不能处理URL编码
原理:Spring的decodeRequestString方法会进行URL解码,而如果鉴权逻辑不能识别编码后的路径,会导致绕过。
示例:
- 原始路径:
/test - 绕过路径:
/%74%65%73%74(test的URL编码)
Spring能正确解析为/test,但鉴权逻辑可能只匹配原始字符串/test而无法识别/%74%65%73%74。
2. 分号(;)绕过
适用场景:鉴权逻辑不能删除;和/之间的内容
示例:
- 原始路径:
/test/aaa - 绕过路径:
/test;x=aaa/bbb
处理后会变为/test/bbb,如果鉴权只检查原始路径/test/aaa,可能被绕过。
3. 双斜杠(//)绕过
适用场景:鉴权逻辑不能把//转换为/
示例:
- 原始路径:
/test/aaa - 绕过路径:
/test//aaa
Spring会将其规范化为/test/aaa,但鉴权逻辑可能无法识别这种变体。
4. 路径遍历绕过(仅限特定版本)
适用场景:使用getPathWithinServletMapping且版本≤2.3.0.RELEASE
示例:
- 原始路径:
/secure/data - 绕过路径:
/secure/../public/data
在受影响版本中会被规范化为/public/data,可能绕过对/secure/路径的检查。
5. 无法绕过的情况
当usesPathPatterns为true时,由于缺少对URL解码和//替换的处理,以下绕过手法可能失效:
- URL编码绕过
- 双斜杠绕过
版本差异与防御建议
-
版本差异:
- 较新版本(
usesPathPatterns为true)对路径处理更严格 - 旧版本存在更多路径处理变体
- 较新版本(
-
防御建议:
- 鉴权逻辑应与Spring框架使用相同的路径解析方法
- 对所有可能的路径表示形式进行测试
- 保持框架版本更新
总结
理解Spring框架的路由解析机制对于发现和预防安全漏洞至关重要。不同的绕过手法适用于不同的场景和版本,安全人员需要根据实际环境选择适当的测试方法。同时,开发人员应确保权限检查与框架的路由解析保持一致,避免因解析差异导致的安全问题。