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

Java应用安全扫描告警:HTTP头注入致外部服务交互,该如何处理?

回答:

需要添加Filter来校验Host和X-Forwarded-Host头,这是修复这类HTTP头注入引发的外部服务交互风险的直接有效方案,完全匹配安全扫描给出的整改建议。

具体操作可以按以下步骤来:

1. 定义安全FQDN白名单

先整理业务允许的合法域名列表,比如你的应用域名、信任的代理域名等,把这些作为白名单。可以硬编码在代码里(适合固定场景),或者放在配置文件中(方便动态更新):

private static final Set<String> ALLOWED_HOSTS = new HashSet<>(Arrays.asList(
    "your-app.com",
    "trusted-proxy.your-company.com",
    "api.your-app.com"
));

2. 实现校验Filter

根据你的应用类型选择对应的Filter实现:

普通Java Web应用(Servlet Filter)

public class HostValidationFilter implements Filter {
    private static final Set<String> ALLOWED_HOSTS = new HashSet<>(Arrays.asList(
        "your-app.com",
        "trusted-proxy.your-company.com"
    ));

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 校验Host头
        String hostHeader = httpRequest.getHeader("Host");
        if (!isValidHost(hostHeader)) {
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid Host header");
            return;
        }

        // 校验X-Forwarded-Host头(如果使用反向代理)
        String forwardedHostHeader = httpRequest.getHeader("X-Forwarded-Host");
        if (forwardedHostHeader != null && !isValidHost(forwardedHostHeader)) {
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid X-Forwarded-Host header");
            return;
        }

        chain.doFilter(request, response);
    }

    private boolean isValidHost(String host) {
        if (host == null || host.trim().isEmpty()) {
            return false;
        }
        // 去掉端口号(如果有的话),只校验域名部分
        String hostWithoutPort = host.split(":")[0].toLowerCase();
        return ALLOWED_HOSTS.contains(hostWithoutPort);
    }

    @Override
    public void destroy() {}
}

然后在web.xml中配置Filter:

<filter>
    <filter-name>HostValidationFilter</filter-name>
    <filter-class>com.yourcompany.filter.HostValidationFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HostValidationFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Spring Boot应用(用OncePerRequestFilter)

如果是Spring Boot项目,推荐用OncePerRequestFilter,避免重复执行:

@Component
public class HostValidationFilter extends OncePerRequestFilter {
    private static final Set<String> ALLOWED_HOSTS = new HashSet<>(Arrays.asList(
        "your-app.com",
        "trusted-proxy.your-company.com"
    ));

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 校验Host头
        String hostHeader = request.getHeader("Host");
        if (!isValidHost(hostHeader)) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid Host header");
            return;
        }

        // 校验X-Forwarded-Host头
        String forwardedHost = request.getHeader("X-Forwarded-Host");
        if (forwardedHost != null) {
            // 处理多个逗号分隔的Host值
            String[] hosts = forwardedHost.split(",");
            for (String h : hosts) {
                String trimmedHost = h.trim();
                if (!isValidHost(trimmedHost)) {
                    response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid X-Forwarded-Host header");
                    return;
                }
            }
        }

        filterChain.doFilter(request, response);
    }

    private boolean isValidHost(String host) {
        if (host == null || host.trim().isEmpty()) {
            return false;
        }
        String hostWithoutPort = host.split(":")[0].toLowerCase();
        return ALLOWED_HOSTS.contains(hostWithoutPort);
    }
}

3. 额外注意事项

  • 如果你的应用部署在反向代理(如Nginx)之后,要确保只有代理服务器能设置X-Forwarded-Host头,禁止客户端直接发送这个头。比如在Nginx配置中覆盖该头的值,而不是传递客户端的:
    proxy_set_header X-Forwarded-Host $host;
    
  • 白名单要根据业务实际情况定期更新,不要遗漏合法的域名,也不要包含不必要的域名。
  • 除了头校验,还要确保应用中所有依赖外部服务的逻辑都做了输入验证,避免其他渠道的SSRF风险。

内容的提问来源于stack exchange,提问作者gene b.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:22:58