CVE-2024-22243与Java中常见获取host的方式

admin 2024年3月19日00:45:37评论4 views字数 4959阅读16分31秒阅读模式

Spring官方近期披露了CVE-2024-22243,在受影响版本中,由于 UriComponentsBuilder 处理URL时未正确处理用户信息中的方括号,攻击者可构造包含方括号的恶意URL绕过主机名验证。如果应用程序依赖UriComponentsBuilder.fromUriString()等方法对URL进行解析和校验,则可能导致验证绕过,出现开放重定向或SSRF漏洞。本质上还是安全检查的工具类与组件库解析host发起请求的解析逻辑导致的绕过问题。

0x00 前言

在实际业务场景中,Open Redirect以及SSRF是比较常见的安全问题。通常情况下会通过解析请求URL中的host,并检查在不在可允许的域名范围或者ip内,来避免相关的安全风险。例如通过相关的工具类(例如java.net.URL的getHost方法)获取URL中的host进行检查,然后再调用HTTP组件库(Apache Httpclient、okhttp等)进行请求。

这里存在着一个解析差异的问题,如果检查的工具类与组件库解析host发起请求的解析逻辑不一样的话,可能会存在绕过安全防护的问题。

0x01 CVE-2024-22243

开发中我们经常会操作 URL,比如提取端口、提取路径以及最常用的提取参数等等。很多时候需要借助于一些第三方类库或者自己编写工具类来实现。在Spring Web中提供了一个用于构建和操作URI的工具类UriComponentsBuilder。

1.1 漏洞描述

Spring官方近期披露了CVE-2024-22243,在受影响版本中,由于 UriComponentsBuilder 处理URL时未正确处理用户信息中的方括号 [ ,攻击者可构造包含方括号的恶意URL绕过主机名验证。如果应用程序依赖UriComponentsBuilder.fromUriString()等方法对URL进行解析和校验,则可能导致验证绕过,出现开放重定向或SSRF漏洞。

CVE-2024-22243与Java中常见获取host的方式

1.2 影响版本

Spring Framework

  • 6.1.0 - 6.1.3

  • 6.0.0 - 6.0.16

  • 5.3.0 - 5.3.31

  • Older, unsupported versions are also affected

1.3 漏洞分析及复现

根据对应的漏洞描述,问题主要在URI的工具类UriComponentsBuilder中。

UriComponentsBuilder 提供了一种简单而强大的方式来构建和处理 URI,避免了手动拼接字符串的繁琐和容易出错的问题。通过添加路径、查询参数、片段等组件来构建完整的 URI:

UriComponents uri =UriComponentsBuilder.fromHttpUrl(url).build();

除了上面的fromHttpUrl方法以外,比较常用的有:

  • fromUri

  • fromHttpUrl

  • fromUriString

通过返回的UriComponents可以轻松的获取URI中类似协议、端口、host等各部分内容。例如可以通过getHost方法获取当前请求的host,结合实际的业务场景检查在不在可允许的域名范围或者ip内,来避免类似SSRF/Open Redirect等安全风险:

CVE-2024-22243与Java中常见获取host的方式

以org.springframework.web.util.UriComponentsBuilder#fromUriString方法为例,查看具体的解析过程,整个逻辑比较简单,主要是通过正则匹配URI中各个部分的内容,然后完成对应的封装:

CVE-2024-22243与Java中常见获取host的方式

具体的正则如下,具体定义了匹配URI的每一个部分内容:

CVE-2024-22243与Java中常见获取host的方式

若未匹配相关信息,会抛出throw new IllegalArgumentException("[" + uri + "] is not a valid URI");异常,否则进行进一步的封装,同时这里对scheme和host进行了一定的合法性检查:

CVE-2024-22243与Java中常见获取host的方式

其他方法也是类似的,org.springframework.web.util.UriComponentsBuilder#fromHttpUrl方法的类型也是类似的但是使用的是HTTP_URL_PATTERN正则:

CVE-2024-22243与Java中常见获取host的方式

org.springframework.web.util.UriComponentsBuilder#fromUri则是直接使用的java.net.URI进行封装:

CVE-2024-22243与Java中常见获取host的方式

简单了解了具体的使用以后,通过相关的commit记录https://github.com/spring-projects/spring-framework/commit/7ec5c994c147f0e168149498b1c9d4a249d69e87 可以看到,官方提供的修复方式主要是移除了USERINFO中对方括号 [的匹配:

CVE-2024-22243与Java中常见获取host的方式

在此之前,可选的USERINFO信息由一个或多个非@、[、斜杠、问号和#号的字符组成。那么实际利用起来就很简单了,举个例子:

UriComponents uri =UriComponentsBuilder.fromHttpUrl("http://forum.butian.net[@risk.com").build();

解析完成后USERINFO为null,对应的host并不是预期的risk.com,而是forum.butian.net:

CVE-2024-22243与Java中常见获取host的方式

此时若发起请求的http组件能解析上述的URL,且获取到的host存在解析差异的话,以java.net.URL为例,通过HttpURLConnection进行请求,可以看到这里实际获取到的host是risk.com:

CVE-2024-22243与Java中常见获取host的方式

以Open Redirect的防护为例,一般会检查请求host是否在白名单范围内来进行拦截,通过上述请求,即可绕过对应的白名单host检查,访问到risk.com,造成对应的风险。

实际上除了[以外,通过多个@、问号和#号的字符也能在使用UriComponentsBuilder获取到意料之外的host:

CVE-2024-22243与Java中常见获取host的方式

但是前提是发起请求的http组件能解析上述的URL,且获取到的host存在解析差异,才可能导致对应的绕过风险,可以看到通过java.net.URL解析的host是一致的:

CVE-2024-22243与Java中常见获取host的方式

所以这也是为什么官方最终仅调整了[的原因吧?:

CVE-2024-22243与Java中常见获取host的方式

0x02 Java中常见获取host的方式

前面对SpringWeb提供的工具类UriComponentsBuilder获取host的方式进行了简单的分析,除此之外,在Java中其他的一些获取host方式可能也会存在类似的解析差异导致的绕过问题。下面简单看看Java中常见的获取host的方式:

2.1 java.net

最常见的可以基于URI或者URL对象的getHost方法进行获取。很多组件库也是对其进行封装进行二次处理的:

URL url = new URL(input);
String host = url.getHost();

以URL为例,通过其构造器可以知道,最终调用的是URL(URL context, String spec, URLStreamHandler handler):

CVE-2024-22243与Java中常见获取host的方式

首先会解析出来请求的协议,并根据protocol去相应的包里面去加载Handler类,然后调用parseURL方法进行解析:

CVE-2024-22243与Java中常见获取host的方式

在parseURL方法中,主要是解析出URL中的字符串信息,最后将这些字符串结果再回设置给URL类中去。可以看到关于host的解析并不是基于正则的,会直接根据@字符的坐标进行切割:

CVE-2024-22243与Java中常见获取host的方式

2.2 hutool工具类

Hutool是一个功能强大的Java工具类库,它提供了一系列方便实用的工具类,其中包括解析URL的工具类cn.hutool.core.util.URLUtil,其提供了一系列的方法用于解析URL。

可以看到其获取host的方式是基于java.net.URL上进行处理的:

CVE-2024-22243与Java中常见获取host的方式

2.3 常用HTTP组件库

Apache Httpclient是一个可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包。相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http协议的),提高了开发的效率,也方便提高代码的健壮性。是Java中比较常用的HTTP组件库。

其中其不同版本解析获取host方法方式会有一些区别,下面举例说明:

  • HttpClient3

以Get请求为例,可以通过如下方法获取请求的host:

HttpClient httpclient = new HttpClient();
HttpMethod method = new GetMethod("http://127.0.0.1%23.baidu.com/");
String host = method.getURI().getHost();

这里主要通过自实现的 URI 类org.apache.commons.httpclient.HttpMethodBase进行解析:

CVE-2024-22243与Java中常见获取host的方式

查看URI的具体实现,主要通过org.apache.commons.httpclient.URI#parseUriReference方法进行一些简单的处理:

CVE-2024-22243与Java中常见获取host的方式

parseUriReference方法会对不合理的host头进行处理。这里有个关键是会对#进行截断,重新组装后赋值给_query,将处理后的_query生成新的URI:

CVE-2024-22243与Java中常见获取host的方式

最后调用HttpMethodBase自身的setURI方法进行处理:

CVE-2024-22243与Java中常见获取host的方式

这里新建了HttpHost对象,查看其实例化方法,调用了自定义的uri.getHost方法,这里还会进行一次URL解码:

CVE-2024-22243与Java中常见获取host的方式

CVE-2024-22243与Java中常见获取host的方式

也就是说类似127.0.0.1#的host会经过二次处理变成127.0.0.1,以解析http://127.0.0.1#forum.butian.net/ 为例(将#进行URL变成成%23也是可以的):

CVE-2024-22243与Java中常见获取host的方式

  • HttpClient4(<=4.5.12版本)

可以通过内嵌的URIUtils#extractHost方法获取当前请求的host。

在解析时候先使用自带的 URL 函数获取 port 和 host,如果通过getHost()获取失败的话,会调用getAuthority()方法来进行调整。然后如果不为null,则进行进一步的处理,首先对@进行截断,获取@后的内容。然后获取:做拆分,一直获取相关的整数,直到为非数字为止:

CVE-2024-22243与Java中常见获取host的方式

CVE-2024-22243与Java中常见获取host的方式

也就是说,类似:80.forum.butian.net最后获取到的值应该为80,作为相关的端口。然后host的内容以:进行substring切割:

 host = host.substring(0, colon);

那么若相关的请求为127.0.0.1:80.forum.butian.net,最终处理的结果为127.0.0.1:80。

除此以外,还可以通过org.apache.http.client.utils.URIBuilder解析url来获取host,本质上解析还是是基于java.net.URL上进行处理的:

URIBuilder uriBuilder = new URIBuilder("http://127.0.0.1:80.baidu.com");
String host = uriBuilder.build().getHost();

CVE-2024-22243与Java中常见获取host的方式

相比自定义的工具类,当使用组件库进行处理时,一般情况下检查的方法与组件库解析的方式是一致的,从一定程度上能避免解析差异导致的绕过问题。

除了Httpclient以外,okhttp也是比较常用的HTTP组件库,具体的解析过程可以参考https://forum.butian.net/share/2427 。

2.4 自定义正则匹配

实际上UriComponentsBuilder也是一种自定义正则匹配的场景,因为在实际调用时不清楚发起请求的解析库/工具类的解析模式,当安全检查的工具类存在解析差异的便导致了绕过的风险。

转载:作者:欢迎大家去关注作者

欢迎师傅加入安全交流群(qq群:611901335),或者后台回复加群

如果想和我一起讨论,欢迎加入我的知识星球!!!

CVE-2024-22243与Java中常见获取host的方式

扫描下图加入freebuf知识大陆

CVE-2024-22243与Java中常见获取host的方式

师傅们点赞、转发、在看就是最大的支持

后台回复知识星球或者知识大陆也可获取加入链接(两个加其一即可)

原文始发于微信公众号(星冥安全):CVE-2024-22243与Java中常见获取host的方式

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月19日00:45:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2024-22243与Java中常见获取host的方式http://cn-sec.com/archives/2587155.html

发表评论

匿名网友 填写信息