前言
今天来看一个比较有意思的漏洞-HTTP报头攻击,也就是host头攻击。在我们的印象中host头是我们所要访问的域名,默认是不可控的,因为一旦改变我们就不能正确访问目标地址。其实不然,在某些情况下,改变了host头依然可以访问目标。那么host头在某些情况下也是我们可以控制的输入,这也就为host头攻击提供了可能。
什么是 HTTP Host 头?
重新再来认识一下什么是host头。
从 HTTP/1.1 开始,HTTP Host 头是一个必需的请求头,其指定了客户端想要访问的域名。例如我们访问百度,发送的请求如下,会包含一个host头。
HTTP头的作用
当我们在浏览器中输入一个网址时,首先会根据网址进行DNS解析,找到对应的IP地址,然后将请求发送到对应的IP地址。
我理解的域名与host头其实并不是一个概念,域名是我们在浏览器中输入要访问的地址,而host头是数据包中的一个值。
那么什么地方会用到http头呢?
1)虚拟主机根据HTTP头访问具体的业务。目前由于IPV4的地址已经耗尽,所以越来越多的应用对应同一个公网IP,这种情况下,就需要根据HTTP头来判断具体需要访问那个业务。
2)通过代理访问后端组件。域名的IP解析到代理的公网IP,然后代理在根据HTTP头来分配到具体的后端组件。我们经常使用的CDN也可以认为是这种情况。
HTTP头是否可以修改
答案当然是可以修改的,如下面在burp里面可以直接修改host头,修改host头以后还可以正常访问应用。
如下图,修改以后还可以正常访问
HTTP头攻击
HTTP Host 头攻击会利用以不安全的方式处理 Host 头的漏洞网站。如果服务器隐式信任 Host 标头,且未能正确验证或转义它,则攻击者可能会使用此输入来注入有害的有效负载,以操纵服务器端的行为。将有害负载直接注入到 Host 头的攻击通常称为 "Host header injection"(主机头注入攻击)。
上面我们已经了解到就算改变了HTTP报头也是可以正常访问到应用的,那么如果后端使用HTTP报头,并且没有做过滤,那么就有可能造成危害。
HTTP报头可能得攻击场景
HTTP报头攻击可能存在以下的利用场景
1)重置密码或者注册用户登场景发送重置链接取HTTP报头的值
2)根据host头限制一些资源的访问
3)系统启用了web缓存功能,可以利用web缓存投毒
4)根据host头进行路由(基于路由的SSRF)
在portswigger上有关于http host攻击的专题,如下:
链接:https://portswigger.net/web-security/all-labs#http-request-smuggling
类似密码重置场景攻击
几乎所有需要登录的网站都实现了下面的场景。下面以密码重置来简要概述这个场景
-
用户输入用户名或电子邮件地址,然后提交密码重置请求。
-
网站检查该用户是否存在,然后生成一个临时的、唯一的、高熵的 token 令牌,并在后端将该令牌与用户的帐户相关联。
-
网站向用户发送一封包含重置密码链接的电子邮件。用户的 token 令牌作为 query 参数包含在相应的 URL 中,如 https://normal-website.com/reset?token=0a1b2c3d4e5f6g7h8i9j。
-
当用户访问此 URL 时,网站会检查所提供的 token 令牌是否有效,并使用它来确定要重置的帐户。如果一切正常,用户就可以设置新密码了。最后,token 令牌被销毁。
与其他一些方法相比,这个过程足够简单并且相对安全。然而,它的安全性依赖于这样一个前提:只有目标用户才能访问他们的电子邮件收件箱,从而使用他们的 token 令牌。而密码重置中毒就是一种窃取此 token 令牌以更改其他用户密码的方法。
这里有一个问题,如果我们拿到这个链接就可以修改用户的密码,而token是动态生成的,我们一般是无法获取的。如果这个链接是根据host生成的,则给我们拿到这个链接提供了一种可能。如下:
如何构造一个密码重置中毒攻击
如果发送给用户的 URL 是基于可控制的输入(例如 Host 头)动态生成的,则可以构造如下所示的密码重置中毒攻击:
-
攻击者根据需要获取受害者的电子邮件地址或用户名,并代表受害者提交密码重置请求,但是这个请求被修改了 Host 头,以指向他们控制的域。我们假设使用的是 evil-user.net 。
-
受害者收到了网站发送的真实的密码重置电子邮件,其中包含一个重置密码的链接,以及与他们的帐户相关联的 token 令牌。但是,URL 中的域名指向了攻击者的服务器:https://evil-user.net/reset?token=0a1b2c3d4e5f6g7h8i9j 。
-
如果受害者点击了此链接,则密码重置的 token 令牌将被传递到攻击者的服务器。
-
攻击者现在可以访问网站的真实 URL ,并使用盗取的受害者的 token 令牌,将用户的密码重置为自己的密码,然后就可以登录到用户的帐户了。
在真正的攻击中,攻击者可能会伪造一个假的警告通知来提高受害者点击链接的概率。
即使不能控制密码重置的链接,有时也可以使用 Host 头将 HTML 注入到敏感的电子邮件中。请注意,电子邮件客户端通常不执行 JavaScript ,但其他 HTML 注入技术如悬挂标记攻击可能仍然适用。
PortSwigger靶场测试
在这里添加用户名,然后拦截数据包,将数据包改成你的exploit server。
然后当用户访问了这个链接以后,你就可以去查看你的exploit server的log日志,可以发现重启密码的链接。
在浏览器中用原来的域名访问这个重置密码链接
跳出重置密码的页面
根据host限制资源的访问
有时处于安全的考虑,会把某些功能限制成只能特定的IP或者host头访问,那么通过修改host头就可能绕过这个限制。
portswigger靶场:https://portswigger.net/web-security/host-header/exploiting/lab-host-header-authentication-bypass
访问robots.txt发现存在admin页面,直接访问显示拒绝
将host头改成localhost可能正常访问
在实际的利用中,往往需要fuzz host头的内容。
web缓存投毒
当存在Host头攻击的web站点不存在密码重置的功能等场景时,由于不可能驱使用户去抓包修改Host头,该漏洞就显得没有什么作用。
但是,如果目标站点使用Web缓存,则可以通过缓存投毒给其他用户提供带有病毒的缓存响应。此时的Host头攻击漏洞转变为类似XSS存储型类的漏洞。要构造Web缓存投毒攻击:
-
需要寻找映射到其他用户请求的缓存键;
-
下一步则是缓存此恶意响应;
-
然后,此恶意缓存将提供给尝试访问受影响页面的所有用户。
下面结合portswigger上的实验来看一下
链接:https://portswigger.net/web-security/host-header/exploiting/lab-host-header-web-cache-poisoning-via-ambiguous-requests
打开这个实验,可以看到,添加一个host头,会返回在响应中,而且启用了web缓存功能,那么我们可以将host头替换成我们服务上同名的文件:/resources/js/tracking.js
如下
多请求几次,使此请求被缓存下来
此时,其它用户再去访问该链接,就会访问到这个已经缓存的页面,也就是可以造成类似于xss的漏洞。
基于host头进行路由
有的应用会根据host头进行路由,那么在这种情况下,我们可以通过改变host头来访问内网的应用,也就是常说的SSRF。
这可能需要知道内部系统的IP地址(私有地址),一般可以通过信息收集或者Fuzz来判断有效的私有IP地址(如枚举192.168.1.1/16)
接下来还是看一下portswigger上面的实验
链接:https://portswigger.net/web-security/host-header/exploiting/lab-host-header-routing-based-ssrf
该实验已知内网中存在admin页面并且通过host头进行路由
直接访问显示404
爆破内网IP尝试访问
成功访问到内网应用
在portswigger还有一个实验,校验了host头的值,只要修改host的值就会拒绝服务,此时可以将host头放到path中,如下面这种
GET http://evil.web-security-academy.net/ HTTP/1.1
HTTP host头绕过
有时我们发现修改host头时会受到限制,可以通过下面的方式进行绕过
1)检查限制是否有缺陷,例如没有限制端口号,只会验证是否以允许的子域结尾等等
2)注入多个host头
如果服务器端会将第二个Host头优先于第一个Host头,就会覆盖掉它的值,然后中转组件会因为第一个Host头指定了正确的目标而照常转发这个请求包,这样就能保证它可以顺利到达服务器。
GET /example HTTP/1.1
Host: vulnerable.com
Host: evil.com
3)提供绝对URL
GET https://evil.com/ HTTP/1.1
Host: vulnerable.com
4)注入覆盖Host头的字段
与Host头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。
GET /example HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-Host: attack-stuff
诸如此类,还有其他的字段:
-
X-Host
-
X-Forwarded-Server
-
X-HTTP-Host-Override
-
Forwarded
5)添加缩进或者换行
当一些站点block带有多个Host头的请求时,可以通过添加缩进字符的HTTP头来绕过
GET /example HTTP/1.1
Host: attack-stuff
Host: vulnerable-website.com
HTTP Host头攻击防护
最简单的方法是避免在服务器端代码中使用前端获取的host头。
其他方法包括:
正确配置绝对域名URL
当必须使用绝对域名URL时,应在配置文件中手动指定当前域的URL,并引用配置的值,而不是从HTTP的Host头中获取。这种方法可防止密码重置的缓存投毒。白名单校验Host头的域
如果必须使用Host头,需要正确校验它的合法性。这包括允许的域,并使用白名单校验它,以及拒绝或重定向对无法识别的主机请求。这包括但不仅限于单个web应用程序、负载均衡以及反向代理设备上。
不支持主机头覆盖
确保不适用与Host头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。
总结
上面简要介绍了一下HTTP报头攻击以及实际可能存在的场景,在实际的测试中遇到的比较少,常规漏洞已经不多见的情况下,可以多测一下这方面的漏洞。
原文始发于微信公众号(疯猫网络):渗透测试之HTTP报头攻击
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论