CVE-2024-22262(CVE-2024-22259绕过)浅析
朋友们现在只对常读和星标的公众号才展示大图推送,建议大家把“亿人安全“设为星标”,否则可能就看不到了啦
原文由作者授权,首发在奇安信攻防社区
https://forum.butian.net/share/2932
Spring官方近期披露了CVE-2024-22262,在受影响版本中,由于此前CVE-2024-22243、CVE-2024-22259的修复黑名单校验不充分,攻击者可能构造在协议、主机名、用户名、端口部分包含\\的url,使得通过UriComponentsBuilder类解析得到错误的值,绕过业务应用中的主机地址验证。
0x00 前言
UriComponentsBuilder是Spring Web中用于构建和操作URI的工具类。Spring官方近期披露了CVE-2024-22262,在受影响版本中,由于此前CVE-2024-22243、CVE-2024-22259的修复黑名单校验不充分,攻击者可能构造在协议、主机名、用户名、端口部分包含\
的url,使得通过UriComponentsBuilder类解析得到错误的值,绕过业务应用中的主机地址验证。
0x01 CVE-2024-22262
1.1 漏洞描述
UriComponentsBuilder是Spring Web中用于构建和操作URI的工具类。在受影响版本中,由于此前CVE-2024-22243、CVE-2024-22259的修复不充分,攻击者在特定的场景下可构造绕过主机名验证,导致开放重定向或SSRF漏洞。
1.2 影响版本
Spring Framework
-
6.1.0 - 6.1.5
-
6.0.0 - 6.0.18
-
5.3.0 - 5.3.33
-
Older, unsupported versions are also affected
1.3 漏洞分析及复现
问题主要还是在URI的工具类UriComponentsBuilder中,对CVE-2024-22243、CVE-2024-22259的修复不充分进行了补充。之前的具体分析可以参考https://forum.butian.net/share/2810 。
在具体漏洞版本中,以org.springframework.web.util.UriComponentsBuilder#fromUriString方法为例,整个逻辑比较简单,主要是通过正则匹配URI中各个部分的内容,然后完成对应的封装:
通过相关的commit记录https://github.com/spring-projects/spring-framework/commit/402246df28048504a709b5c277dfd49116ff5df1 查看具体的修复方式:
主要是对正则进行了调整。针对\\
的匹配进行了调整。结合实际的例子看看具体调整的内容。以漏洞版本org.springframework:spring-web:5.3.33为例,查看host的处理方式:
可以看到,host的匹配方式是任意数量的不包含 /
、?
和#
以及:
的字符:
5.3.34版本增加了\\
的处理,在host的匹配时候会排除掉额外的\\
:
也就是说,类似http://127.0.0.1\
的请求,会因为匹配正则的区别得到如下的host:
UriComponents uri =UriComponentsBuilder.fromUriString("http://127,0.0.1\\").build();
-
5.3.33(漏洞版本)
-
5.3.34(修复版本)
可以看到漏洞版本获取到的host为127.0.0.1\
,会把\
也当成host的一部分。
0x02 实际缺陷场景
由于漏洞版本的UriComponentsBuilder解析时会在host引入额外的\
,在特定情况下可能会绕过对应的安全限制,下面看一些实际的缺陷场景。
2.1 URL Redirect
在业务场景中,在实际浏览器解析访问时中反斜线\
会被纠正为正斜线/
。也就是说类似http://127.0.0.1``\mange
在浏览器访问时依旧可以访问到对应的host路径资源。
结合前面的解析差异,例如下面的例子,只有以whiteDomain结尾的host才可以通过校验完成URL Redirect的操作:
由于漏洞版本的UriComponentsBuilder解析时会在host引入额外的\
,那么只要以http://attack.com``\白名单域名.com
方式进行访问即可绕过对应的限制,跳转到恶意的网站。
除了host以外,在修复时也考虑到了schema还有port匹配额外\
的问题,避免在类似通过UriComponentsBuilder限制某个协议访问时,结合浏览器解析的特性,引入额外\
绕过的问题。
不过若使用的是fromHttpUrl进行解析时,会额外调用checkSchemeAndHost方法进行检查:
类似http:\\127.0.0.1
的请求获取到的host为null,会抛出not a valid HTTP URL的异常:
UriComponents uri =UriComponentsBuilder.fromHttpUrl("http:\\\\127.0.0.1").build();
但是类似http://127.0.0.1\
的请求还是会获取到预期以外的host,在特定情况下仍会存在绕过的风险,所以在实际审计的过程中需要额外的注意。
2.2 SSRF
相比URL Redirect,SSRF的利用场景在绕过了结合UriComponentsBuilder工具类实现的安全检查后,对应的host还必须能被http组件成功解析,攻击者才能达到利用的目的。
对一些常见的http请求组件进行了枚举,以okhttp3为例:
在实际url解析时主要是通过okhttp3.HttpUrl的构造方法进行封装,核心的解析主要是在parse方法,在parse方法中,首先获取对应的索引信息,例如首先在skipLeadingAsciiWhitespace方法中会对一系列ASCII空白字符(例如制表符、换行、空格等)进行处理,然后在schemeDelimiterOffset方法中,实际上就是查找 URI 中第一个出现的:
:
在获取到对应的协议后,会调用slashCount方法计算协议分隔符的坐标:
查看slashCount的具体实现,可以看到除了/
以外,还考虑了反斜线\
的情况:
然后会计算componentDelimiterOffset的值,这里会调用delimiterOffset方法在input参数中查找指定范围内的第一个出现在给定分隔符集合中的字符的索引(给定字符是@/\?#
):
然后会计算portColonOffset,这里主要是检查当前字符是否是:
。如果找到了表示端口号的位置已经找到,然后返回该位置的索引:
之后会调用canonicalizeHost方法,基于前面portColonOffset的偏移量获取当前请求的host:
因为okhttp3在实际解析时,不论在协议还是在path分隔时均覆盖了/
的情况,那么也就是说,类似http:\\127.0.0.1\\
的请求,okhttp3会经过一系列的处理最终host解析结果为127.0.0.1:
Request request = new Request.Builder()
.url("http:\\\\127.0.0.1\\")
.build();
结合漏洞版本的UriComponentsBuilder解析时会在host引入额外的\
,例如实际场景中限制了部分内网ip的访问,利用类似http:\\127.0.0.1\\
的请求,在okhttp3的请求背景下即可绕过对应的安全限制。
0x03 其他
类似httpclient组件在解析时,若包含某些特殊字符就会抛出URISyntaxException异常,例如上面okhttp3的例子:
本质原因还是因为具体解析时使用了java.net.URI进行了对应的封装。其在实际解析时限制了合法字符范围。而\\
明显不在对应的范围内,所以即使绕过了对应的安全检查,也没办法进一步进行利用。
- 点赞
- 收藏
- 关注作者
评论(0)