- Web应用程序获取网站域名一般是依赖HTTP Host header(比如在JSP里通过request.getHeader()获取),这里的header很多情况下是不可靠的。
- 攻击者恶意利用HTTP Host header会导致HTTP Host头攻击发生。
1、 密码重置污染攻击,点击重置密码的链接时,url::abs_site 这一部分使用的Host header是来自用户重置密码的请求,那么可以通过一个受他控制的链接来污染密码重置的邮件,例如替换host:当然这种攻击方式一定要能骗取用户点击访问这个受污染的链接,如果用户警觉了没有点击,那么攻击就会失败
POST /password/reset HTTP/1.1
Host: evil.com
...
csrf=1e8d5c9bceb16667b1b330cc5fd48663&name=admin
2、 通过Host header来污染缓存的攻击方法: 因此为了能使缓存能将污染后的response返回给用户,我们还必须让缓存服务器看到的host header 和应用看到的host header 不一样, 比如说对于Varnish(一个很有名的缓存服务软件),可以使用一个复制的Host header。 Varnish是通过最先到达的请求的host header来辨别host的,而Apache则是看所有请求的host,Nginx则只是看最后一个请求的host。 这就意味着你可以通过下面这个请求来欺骗Varnish达到污染的目的
GET / HTTP/1.1
Host: example.com
Host: evil.com
- 利用web漏洞扫描工具进行检测。
大部分的Web应用程序未经html编码直接把header输出到了页面中。比如:。有些URL中还包含有secret key和token,如:
。 这样处理header一般会产生两种常见的攻击:缓存污染和密码重置。 缓存污染是指攻击者通过控制一个缓存系统来将一个恶意站点的页面返回给用户。 密码重置这种攻击主要是因为发送给用户的内容是被污染的,即间接的劫持邮件。
【中危】:请求数据包包中 host 值直接拼接到生成链接中。
修复方案:1、 服务器方面:
- 由于http请求的特点,host header的值其实是不可信的。 唯一可信的只有SERVER_NAME,这个在Apache和Nginx里可以通过设置一个虚拟机来记录所有的非法host header。 在Nginx里还可以通过指定一个SERVER_NAME名单,Apache也可以通过指定一个SERVER_NAME名单并开启UseCanonicalName选项。 建议两种方法同时使用。
- Varnish很快会发布一个补丁。在官方补丁出来前,可以通过在配置文件里加入:
import std;
sub vcl_recv {
std.collect(req.http.host);
}
2、应用方面: 在网站安装和初始化的时候,要求管理员提供一个可信任的域名白名单。 如果这个实现起来比较困难,那至少也要保证使用使用getServerName()代替getHeader(“Host”)。