漏洞描述:
详细描述 | 为了方便的获得网站域名,开发人员一般依赖于HTTP Host header。 例如,在php里用_SERVER["HTTP_HOST"]。但是这个header是不可信赖的,如果应用程序没有对host header值进行处理,就有可能造成恶意代码的传入。 |
解决办法 | web应用程序应该使用SERVER_NAME而不是host header。 在Apache和Nginx里可以通过设置一个虚拟机来记录所有的非法host header。在Nginx里还可以通过指定一个SERVER_NAME名单,Apache也可以通过指定一个SERVER_NAME名单并开启UseCanonicalName选项。 |
采用的解决办法如下:在请求拦截上面做host合法性校验,拦截掉非法请求。
【基于Filter的修复方案】
修复方式:将合法的host加入白名单中,过滤时不在白名单中的host则会报错不允许访问,在白名单中的host可以正常访问。
在工程的web.xml中配置下面代码中的拦截器,注意该拦截器一定要放在第一个执行。
web.xml中配置如下:
<!--http host header过滤 -->
<filter>
<filter-name>HostCleanFilter</filter-name>
<filter-class>com.zfsoft.filter.HostCleanFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HostCleanFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在HostCleanFilter.java文件中进行处理:
/**
* HTTP Host header过滤
* @author dyq
* @date 20180627
*
*/
public class HostCleanFilter implements Filter{
private static StringBuffer whiteStr = new StringBuffer();
static{
try {
// 读取白名单列表
//白名单文件serverWhiteList.txt放在tomcat工程目录的classes下
String path=HostCleanFilter.class.getResource("/").getPath();
File serverWhiteListFile = new File(path+"serverWhiteList.txt");
if(serverWhiteListFile.exists()){
InputStreamReader inStream = new InputStreamReader(HostCleanFilter.class.getResourceAsStream("/serverWhiteList.txt"));// 文件的存放路径
int c=0;
while((c=inStream.read())!=-1){
whiteStr.append((char)c);
}
inStream.close();
}
System.out.println("白名单:"+whiteStr.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest Hrequest = (HttpServletRequest)request;
HttpServletResponse Hresponse = (HttpServletResponse) response;
//http host头攻击检测,若HostHeader不在白名单中 则无法访问
String requestHost=Hrequest.getHeader("Host");
if(requestHost !=null && !whiteStr.toString().contains("'"+requestHost+"'")){
Hresponse.setStatus(403);
Hresponse.sendError(403,"访问地址不在白名单中,无法访问!");
return;
}
chain.doFilter(Hrequest, Hresponse);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
serverWhiteList.txt的内容:
白名单文件放置目录可以根据具体要求自行设定。一般放置在src根目录或resource配置目录
'localhost:8091',
'127.0.0.1:8091'