转自:https://blog.csdn.net/ahuyangdong/article/details/79091699
背景
项目上线之后使用绿盟或Acunetix安全扫描工具扫描后发现了头攻击漏洞。截图如下:
漏洞提示
检测工具在检测出漏洞后给予的提示为:
大意为不要使用request中的serverName,也就是说host header可能会在攻击时被篡改,依赖request的方法是不可靠的,形如JSP头部中的:
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
这样的使用方法就会被漏洞检测工具查出来,认定有头攻击漏洞。
解决办法
提示中说,如果是php的话不要用SERVER_NAME,apache和Nginx通过设置虚拟机来纪要非法header,而web开发中常见的运行容器就是tomcat,网络查找出的解决方案大多不适用,最后,我们找到了一个折中的办法。
主要解决办法,就是在请求拦截上面做host合法性校验,拦截掉非法请求。在方法开始的地方做host判定,如果不在白名单内,则返回403状态码。漏洞工具收到403后认为访问请求已被终止,就不会报错了。
package com.cssweb.common.admin.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HostCleanFilter implements Filter {
/**
* 自定义实现host白名单添加
* @param filterConfig
* @throws ServletException
*/
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String host=request.getHeader("Host");
System.out.println("Host-debug:"+host);
if(!isEmpty(host)){
if(checkBlankList(host)){
filterChain.doFilter(servletRequest,servletResponse);
}else{
// System.out.println("[host deny access tips]->"+host);
response.getWriter().print("host deny");
response.flushBuffer();
}
}else{
filterChain.doFilter(servletRequest,servletResponse);
}
}
public void destroy() {
}
/**
* 校验当前host是否在白名单中
* @param host
* @return
*/
private boolean checkBlankList(String host){
// 访问白名单
if(host.contains("localhost:8080") || host.contains("192.168.40.245:8080")) {
// 127.0.0.1:8080就不能访问
return true;
}
return false;
}
public boolean isEmpty(Object str) {
return str == null || "".equals(str);
}
}
在web.xml中配置(放在web.xml的最前面):
<!-- 检测到目标URL存在http host头攻击漏洞( 中危)开始 -->
<filter>
<filter-name>HostCleanFilter</filter-name>
<filter-class>com.cssweb.common.admin.filter.HostCleanFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HostCleanFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 检测到目标URL存在http host头攻击漏洞( 中危)结束 -->