CVE-2024-22243与Java中常见获取host的方式
字数 1239 2025-08-18 11:35:32
CVE-2024-22243漏洞分析与Java中Host获取方式安全研究
漏洞概述
CVE-2024-22243是Spring框架中UriComponentsBuilder组件在处理URL时存在的一个安全漏洞。该漏洞源于对用户信息(userinfo)部分中方括号([])字符的不当处理,导致攻击者可以构造特殊URL绕过主机名验证机制。
受影响版本
- Spring Framework 6.0.0 - 6.0.16
- Spring Framework 5.3.0 - 5.3.31
漏洞原理分析
问题根源
UriComponentsBuilder.fromUriString()方法在解析URL时,对用户信息部分中的方括号处理不当。当URL包含如下格式时:
http://user[attacker.com@legitimate.com/
解析器会错误地将attacker.com识别为host的一部分,而实际上legitimate.com才是真正的host。
解析过程对比
正常URL解析:
http://user@legitimate.com/path
→ 解析结果:
- Scheme: http
- Host: legitimate.com
- User: user
恶意URL解析:
http://user[attacker.com@legitimate.com/path
→ 错误解析结果:
- Scheme: http
- Host: attacker.com
- User: user
- 实际请求发送至: legitimate.com
Java中常见的Host获取方式
1. java.net.URL
URL url = new URL("http://example.com");
String host = url.getHost();
安全问题:
- 不验证主机名是否可信
- 不防止DNS重绑定攻击
- 对特殊字符处理可能不一致
2. java.net.URI
URI uri = new URI("http://example.com");
String host = uri.getHost();
优点:
- 比URL类更严格遵循RFC规范
- 对特殊字符处理更规范
3. Spring的UriComponentsBuilder
UriComponentsBuilder.fromUriString("http://example.com").build().getHost();
问题:
- 在受影响版本中存在CVE-2024-22243漏洞
- 用户信息部分处理不当
4. Apache HttpClient
URIBuilder uriBuilder = new URIBuilder("http://example.com");
String host = uriBuilder.getHost();
特点:
- 通常有更严格的验证
- 可配置主机名验证策略
安全防护建议
1. 输入验证
// 使用白名单验证合法域名
private static final Pattern DOMAIN_PATTERN = Pattern.compile("^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$");
public boolean isValidHost(String host) {
return DOMAIN_PATTERN.matcher(host).matches();
}
2. 使用安全的解析方式
// 优先使用URI而非URL
URI uri = new URI(inputUrl);
String host = uri.getHost();
// 验证host是否在允许列表中
if (!ALLOWED_DOMAINS.contains(host)) {
throw new SecurityException("Domain not allowed");
}
3. 防御DNS重绑定
// 解析后立即获取IP并缓存
InetAddress address = InetAddress.getByName(host);
String ip = address.getHostAddress();
// 后续请求中直接使用IP而非host
// 并验证IP是否在允许范围内
4. 升级Spring框架
对于使用Spring的项目:
- 升级到Spring Framework 6.0.17+ 或 5.3.32+
- 或应用相关补丁
漏洞利用场景
开放重定向攻击
攻击者可构造恶意链接:
https://victim.com/redirect?url=http://user[evil.com@legitimate.com/
若服务端仅检查evil.com而实际重定向到legitimate.com,则可能绕过检查。
SSRF攻击
当应用使用UriComponentsBuilder解析用户提供的URL并访问时:
UriComponents uri = UriComponentsBuilder.fromUriString(userInput).build();
// 错误地认为host是evil.com,实际请求发送到internal-server
测试用例
验证漏洞存在
@Test
void testMalformedHost() {
String maliciousUrl = "http://user[evil.com@legitimate.com/path";
UriComponents components = UriComponentsBuilder.fromUriString(maliciousUrl).build();
// 在受影响版本中,getHost()返回evil.com,但实际请求发送到legitimate.com
assertEquals("legitimate.com", components.getHost()); // 应失败
}
安全解析测试
@Test
void testSafeHostExtraction() throws URISyntaxException {
String url = "http://user[evil.com@legitimate.com/path";
URI uri = new URI(url);
// java.net.URI正确处理这种情况
assertEquals("legitimate.com", uri.getHost()); // 通过
}
修复方案
Spring官方修复
Spring团队在修复版本中改进了UriComponentsBuilder的实现:
- 严格处理用户信息部分中的特殊字符
- 确保
getHost()返回实际请求发送到的host
自定义防护
若无法立即升级,可实现自定义验证:
public static String getVerifiedHost(String url) throws MalformedURLException {
URI uri;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
throw new MalformedURLException("Invalid URL");
}
String host = uri.getHost();
if (host == null) {
throw new MalformedURLException("No host found");
}
// 额外的host验证
if (!isAllowedHost(host)) {
throw new SecurityException("Host not allowed");
}
return host;
}
总结
CVE-2024-22243揭示了URL解析过程中边缘情况处理的重要性。在Java开发中,应注意:
- 谨慎选择URL解析工具,了解其行为差异
- 永远不要信任用户提供的URL,必须进行严格验证
- 使用白名单而非黑名单进行host验证
- 保持框架和库的最新版本
- 对于安全关键操作,考虑多层验证机制
通过深入理解这些解析细节和安全实践,可以有效预防此类漏洞的发生。