You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat 9.0.71任意Host头操纵重定向漏洞解决问询

Tomcat 9.0.71 任意Host头操纵重定向漏洞解决方法

问题场景

Tomcat 9.0.71已配置HSTS(web.xml中设置url-pattern为/*的security-constraint,server.xml配置80端口转443的Connector),运行数月后PCI扫描触发“通过任意Host头操纵实现重定向”漏洞,可复现:

  • 发送HTTP请求至http://example.com,Host头设为google.com,会被Tomcat重定向至google.com
  • 发送HTTPS请求至https://example.com,Host头设为google.com,同样触发重定向,请求同时到达Tomcat与应用

allowHostHeaderMismatch默认值为false,但仅对带协议的Host头(如http://google.com)返回400错误,无法拦截不带协议的非法Host头。


解决方案

方法1:配置Host头白名单(服务器级拦截,推荐)

在server.xml的<Host>节点中添加allowedHosts属性,指定合法域名列表(多个用逗号分隔):

<Host name="example.com" appBase="webapps" unpackWARs="true" autoDeploy="true" allowedHosts="example.com,www.example.com">
    <!-- 现有Host节点配置 -->
</Host>

当请求的Host头不在白名单内时,Tomcat直接返回403 Forbidden,彻底阻断非法请求。该属性从Tomcat 9.0.17版本开始支持,你的9.0.71版本完全兼容。

方法2:添加应用级Host头校验过滤器

通过自定义Servlet过滤器拦截所有请求,校验Host头合法性:

  1. 编写过滤器类:
public class HostValidationFilter implements Filter {
    private Set<String> validHosts;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String allowedHosts = filterConfig.getInitParameter("validHosts");
        validHosts = new HashSet<>(Arrays.asList(allowedHosts.split(",")));
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpReq = (HttpServletRequest) request;
        String hostHeader = httpReq.getHeader("Host");
        
        // 去除Host头中的端口部分(若存在)
        if (hostHeader != null && hostHeader.contains(":")) {
            hostHeader = hostHeader.substring(0, hostHeader.indexOf(":"));
        }

        if (!validHosts.contains(hostHeader)) {
            HttpServletResponse httpRes = (HttpServletResponse) response;
            httpRes.sendError(HttpServletResponse.SC_FORBIDDEN, "非法Host头");
            return;
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {}
}
  1. 在web.xml中注册过滤器,拦截所有请求:
<filter>
    <filter-name>HostValidationFilter</filter-name>
    <filter-class>com.your.package.HostValidationFilter</filter-class>
    <init-param>
        <param-name>validHosts</param-name>
        <param-value>example.com,www.example.com</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>HostValidationFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

方法3:规范HTTP到HTTPS的重定向逻辑

确保80端口的HTTP Connector明确配置redirectPort="443",避免HSTS自动重定向时使用非法Host头生成跳转URL:

<Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="443" />

该配置能让Tomcat在重定向时使用自身配置的域名,而非请求中的Host头。

方法4:反向代理场景下的处理(若使用Nginx等代理)

如果Tomcat部署在反向代理后,配置RemoteIpValve强制使用代理传递的合法Host头:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
       internalProxies="192.168.1.0/24" <!-- 替换为你的代理服务器IP段 -->
       protocolHeader="X-Forwarded-Proto"
       hostHeader="X-Forwarded-Host" />

同时在反向代理中配置仅转发合法Host头的请求,拒绝篡改Host的非法请求。


内容的提问来源于stack exchange,提问作者T Woods

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:48:24