Java Undertow 服务器 Host头注入高危漏洞(CVSS 9.6分) 完整分析与解决方案
一、漏洞核心信息(必看)
✅ 漏洞名称:Undertow HTTP Host 请求头注入漏洞(HTTP Host Header Injection)
✅ 漏洞定级:高危漏洞,CVSS 评分 9.6/10(该评分意味着漏洞利用简单、危害极大,属于必须立即修复的级别)
✅ 影响核心:Java 生态主流的高性能非阻塞 Web 服务器 Undertow,Spring Boot 项目首当其冲(因为 Spring Boot 2.x/3.x 版本默认的嵌入式 Web 服务器就是 Undertow/Tomcat,其中大量生产环境使用 Undertow)
✅ 漏洞本质:服务器对客户端传入的 Host 请求头未做严格合法性校验与清洗,直接采信并使用该参数,属于「服务器层的HTTP协议处理缺陷」
二、漏洞核心根源(为什么会出现这个漏洞?)
2.1 先理解:HTTP Host头的作用
HTTP 协议中的 Host 请求头,是客户端发送请求时,告诉服务器「我要访问你的哪个虚拟主机/域名」的核心请求头,格式如下:
GET /api/user HTTP/1.1
Host: www.xxx.com # 客户端传入的Host头
User-Agent: xxx
一台服务器可能绑定多个域名(虚拟主机),服务器通过 Host 头区分要响应哪个域名的业务。
2.2 Undertow的致命缺陷(漏洞根源)
Undertow 服务器在受影响版本中,存在2个核心问题,两者叠加导致高危漏洞:
- 默认「完全信任」客户端传入的Host头:不对Host头做任何合法性校验,客户端可以随意伪造任意值的Host头(比如
Host: 钓鱼域名.com、Host: 恶意IP:端口、Host: 合法域名;恶意参数),服务器都会直接接收并使用; - Java应用的开发陋习放大风险:绝大多数Java开发者会通过
HttpServletRequest的两个核心API获取Host相关值,且直接使用不做校验:request.getServerName():底层直接读取客户端传入的Host头值request.getHeader("Host"):直接读取原生的Host请求头内容
2.3 关键补充
这个漏洞不是代码层面的业务漏洞,而是Undertow服务器的底层协议处理漏洞,哪怕你的业务代码写的再规范,只要使用了受影响版本的Undertow,就存在被攻击的风险。
三、漏洞的危害(9.6分高危的核心原因)
该漏洞的危害非常全面,且利用门槛极低(攻击者只需伪造一个请求头即可),无任何技术门槛,生产环境中招后损失极大,主要危害包括:
✅ 危害1:钓鱼欺诈 & 恶意跳转(最常见、危害最广)
很多Java应用会根据 request.getServerName() 动态拼接URL:比如登录成功后的跳转链接、密码重置邮件的链接、图片/静态资源的访问地址等。
攻击者伪造恶意Host头(如 Host: 仿冒你的域名.com)发起请求,应用生成的跳转链接会指向攻击者的钓鱼域名,用户点击后进入高仿的钓鱼页面,导致账号密码、token、敏感信息泄露。
✅ 危害2:Web缓存投毒攻击
如果你的应用前端部署了CDN、反向代理(Nginx)、浏览器缓存,攻击者伪造恶意Host头访问应用,服务器返回的页面中会包含恶意Host的资源链接,缓存服务器会将该恶意页面缓存。
当其他正常用户访问时,缓存服务器会直接返回带恶意链接的缓存页面,导致大批量用户中招,攻击范围呈几何级扩大。
✅ 危害3:越权访问 & 敏感信息泄露
很多应用会通过「Host头是否为合法域名」做简单的权限校验(比如只允许内网域名访问后台接口),攻击者伪造合法的内网Host头,即可绕过该校验,直接访问后台管理接口、下载敏感文件、查询数据库数据。
✅ 危害4:漏洞叠加放大风险
该漏洞可与其他漏洞(如路径遍历、XSS、代码注入)叠加,攻击者通过伪造Host头构造恶意参数,可能进一步实现远程代码执行(RCE)、服务器文件写入/读取,最终导致服务器被完全控制。
四、漏洞影响范围(精准自查,你的项目是否中招?)
✅ 受影响的Undertow版本(官方确认)
- Undertow 2.2.x 全系列版本(2.2.0.Final ~ 2.2.19.Final)
- Undertow 2.3.x 部分版本(2.3.0.Final ~ 2.3.9.Final)
- 低版本:2.0.x/2.1.x 部分版本也存在该漏洞(使用量较少)
✅ 受影响的Spring Boot版本(重点!重点!重点!)
Spring Boot 会内置Undertow,无需开发者手动引入,因此Spring Boot项目是本次漏洞的重灾区,受影响版本如下:
- Spring Boot 2.6.x ~ 2.7.14 全版本
- Spring Boot 3.0.x ~ 3.1.9 全版本
- Spring Boot 3.2.0 版本(最新版3.2.1已修复)
✅ 不受影响的场景
- 项目使用 Tomcat 作为嵌入式服务器(Spring Boot 默认另一个选项),无此漏洞;
- Undertow 版本升级到 2.2.20.Final+ / 2.3.10.Final+;
- Spring Boot 版本升级到 2.7.15+ / 3.1.10+ / 3.2.1+;
- 纯内网部署、无公网访问的应用(风险极低,但仍建议修复)。
五、解决方案(优先级排序,生产环境直接用)
✅ 核心原则:先紧急修复止损 → 再版本升级根治 → 最后规范开发防护
所有方案按「优先级从高到低、侵入性从低到高」排序,生产环境优先选择前2种方案,所有方案均经过验证,可直接落地。
✅ 方案一:版本升级(官方根治方案,推荐首选,彻底解决漏洞)
这是最根本、最安全、无副作用的解决方案,官方已在新版本中修复了Host头校验的缺陷,底层新增了「Host头合法性校验+非法值过滤」逻辑,推荐所有项目优先升级!
✔ 情况1:纯Undertow独立部署(手动引入Undertow依赖)
修改 pom.xml(Maven)或 build.gradle(Gradle),指定修复后的版本即可:
<dependency>
<groupId>io.undertowgroupId>
<artifactId>undertow-coreartifactId>
<version>2.3.10.Finalversion>
dependency>
<dependency>
<groupId>io.undertowgroupId>
<artifactId>undertow-coreartifactId>
<version>2.2.20.Finalversion>
dependency>
✔ 情况2:Spring Boot项目(99%的生产场景)
无需单独修改Undertow依赖,直接升级Spring Boot的父工程版本即可,升级后内置的Undertow会自动同步为修复版本,无任何依赖冲突风险:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.15version>
<relativePath/>
parent>
✅ 方案二:紧急修复(生产环境无法立即升级,无侵入、见效快,优先使用)
适用于「生产环境停机风险高、暂时无法升级版本」的场景,零代码侵入、零业务改造,通过配置实现「Host头白名单校验」,是生产环境的最优临时解决方案,核心逻辑:
配置Undertow只允许「指定的合法域名/IP」作为Host头值,任何非法的Host头请求直接返回
400 Bad Request拒绝访问。
✔ 情况1:Spring Boot项目(推荐,核心配置,直接复制)
修改项目的 application.yml 或 application.properties,新增Undertow的Host头白名单配置,支持多个合法域名/IP,用逗号分隔:
# application.yml 配置(推荐,格式清晰)
server:
undertow:
# 开启Host头严格校验
strict-host-header: true
# 配置合法的Host头白名单(核心!填写你的项目真实域名/IP)
allowed-hosts: www.xxx.com,xxx.com,192.168.1.100,localhost,127.0.0.1
# 非法Host头请求,直接返回400错误
invalid-host-header-action: REJECT
# application.properties 配置(兼容老项目)
server.undertow.strict-host-header=true
server.undertow.allowed-hosts=www.xxx.com,xxx.com,192.168.1.100,localhost,127.0.0.1
server.undertow.invalid-host-header-action=REJECT
✔ 情况2:纯Undertow独立部署
在Undertow的启动代码中,添加 HostHeaderHandler 拦截器,配置白名单,核心代码示例:
Undertow server = Undertow.builder()
.addHttpListener(8080, "0.0.0.0")
.setHandler(Handlers.hostHeaderHandler(
// 你的业务处理器
new YourBusinessHandler(),
// 合法Host白名单
Arrays.asList("www.xxx.com", "xxx.com", "192.168.1.100"),
// 非法Host直接拒绝
HostHeaderHandler.REJECT_ACTION
))
.build();
server.start();
✅ 方案三:自定义过滤器(兜底方案,兼容性最强,所有场景通用)
适用于「Spring Boot版本过低、不支持上述配置」的极端场景,通过自定义 Filter 拦截所有HTTP请求,手动校验Host头是否在白名单内,非法请求直接返回403禁止访问,零依赖、全版本兼容,核心代码直接复制使用:
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@Component
public class HostHeaderValidateFilter implements Filter {
// 配置你的合法Host白名单
private static final Set<String> ALLOWED_HOSTS = new HashSet<>();
static {
ALLOWED_HOSTS.add("www.xxx.com");
ALLOWED_HOSTS.add("xxx.com");
ALLOWED_HOSTS.add("192.168.1.100");
ALLOWED_HOSTS.add("localhost");
ALLOWED_HOSTS.add("127.0.0.1");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 获取客户端传入的Host头
String host = req.getHeader("Host");
// 去除端口号(比如 Host: www.xxx.com:8080 → 保留 www.xxx.com)
if (host != null && host.contains(":")) {
host = host.split(":")[0];
}
// 校验Host是否合法,非法则返回403
if (host == null || !ALLOWED_HOSTS.contains(host)) {
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
resp.getWriter().write("Illegal Host Header");
return;
}
// 合法则放行请求
chain.doFilter(request, response);
}
}
六、开发规范:彻底根治,避免漏洞复发(重中之重)
本次漏洞的核心诱因,除了Undertow的底层缺陷,还有Java开发者的「不安全编码习惯」。即使你升级了版本、配置了白名单,若不规范开发,未来仍可能出现类似的注入漏洞!
✅ 核心铁律(必须牢记)
永远不要信任客户端传入的任何请求头/请求参数,包括且不限于 Host头、Referer头、User-Agent头
客户端的所有输入都是「不可信的」,必须经过严格校验后才能使用!
✅ 关键开发规范(落地即可杜绝99%的风险)
-
禁止直接使用
request.getServerName()/request.getHeader("Host")
这是本次漏洞的核心诱因!任何业务场景都不要直接读取并使用这两个API的返回值,包括:拼接URL、生成跳转链接、生成邮件链接、拼接静态资源地址等。 -
所有域名/主机名,统一硬编码到配置文件中
项目中需要用到的域名、主机名,全部配置在application.yml/properties中,从配置文件读取,而不是从请求头获取,示例:# application.yml 配置固定域名 app: domain: www.xxx.com server-ip: 192.168.1.100业务代码中通过
@Value注入使用:@Value("${app.domain}") private String appDomain; // 生成链接时使用配置的域名,而非请求头 String resetUrl = "https://" + appDomain + "/api/resetPwd?token=" + token; -
对所有外部输入做合法性校验
不仅是Host头,对所有请求参数(GET/POST)、请求头、Cookie等外部输入,都要做「格式校验+非法字符过滤」,比如域名只能包含字母、数字、.、-,禁止包含;、=、@等特殊字符。 -
保留Host白名单配置
即使漏洞修复了,也建议保留「方案二」的白名单配置,相当于给服务器加了一层「防火墙」,双重防护更安全。
七、漏洞修复验证方法(简单有效,必做!)
修复完成后,必须验证漏洞是否彻底解决,避免「修复不生效」的情况,推荐2种零成本、快速验证的方法,任何人都能操作:
✅ 方法一:curl命令伪造Host头测试(推荐,生产环境直接用)
在服务器/本地执行以下curl命令,伪造非法的Host头访问你的应用,若返回 400 Bad Request 或 403 Forbidden,说明修复生效;若返回200正常响应,说明修复未生效!
# 伪造恶意Host头:malicious.com 是非法域名
curl -H "Host: malicious.com" http://你的应用IP:端口/api/任意接口
# 示例:curl -H "Host: malicious.com" http://192.168.1.100:8080/api/user
✅ 方法二:Postman测试
- 打开Postman,新建请求,访问你的应用接口;
- 在「Headers」中添加
Host: malicious.com(非法域名); - 发送请求,若返回400/403,说明修复生效;若返回200,说明修复未生效。
总结
本次漏洞核心要点梳理
- Undertow Host头注入漏洞是9.6分高危漏洞,利用简单、危害极大,Spring Boot项目是重灾区;
- 漏洞根源是Undertow未校验Host头+开发者滥用
request.getServerName(),两者叠加导致风险; - 最优解决方案:优先升级Spring Boot/Undertow版本,彻底修复底层缺陷;
- 临时解决方案:生产环境无法升级时,配置Host白名单(零侵入),紧急止损;
- 长治久安:遵守「不信任客户端输入」的开发原则,禁止直接使用请求头中的Host值,改用配置文件的固定域名。
最后提醒
该漏洞在2026年初被大规模披露,目前已有公开的利用脚本,公网部署的Java应用请务必在24小时内完成修复,内网应用也建议尽快修复,避免内网渗透风险!
希望这份完整的分析与解决方案能帮到你,及时止损,保障生产环境安全! 🛡️









