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头合法性:
- 编写过滤器类:
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() {} }
- 在
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
相关产品推荐
相关产品推荐

