HTTP 主机头攻击
什么是 HTTP 主机标头?
从 HTTP/1.1 开始,HTTP Host 标头是强制性的请求标头。它指定客户端要访问的域名。例如,当用户访问 时https://portswigger.net/web-security,他们的浏览器将编写一个包含 Host 标头的请求,如下所示:
GET /web-security HTTP/1.1 Host: portswigger.net
在某些情况下,例如当请求已由中间系统转发时,Host 值可能会在它到达预期的后端组件之前被更改。我们将在下面更详细地讨论这种情况。
HTTP Host 标头的目的是什么?
HTTP Host 标头的目的是帮助识别客户端想要与之通信的后端组件。如果请求不包含 Host 标头,或者 Host 标头以某种方式格式错误,这可能会导致将传入请求路由到预期应用程序时出现问题。
从历史上看,这种歧义并不存在,因为每个 IP 地址只会托管单个域的内容。如今,主要是由于基于云的解决方案和外包大部分相关架构的不断增长的趋势,多个网站和应用程序可以在同一个 IP 地址上访问是很常见的。这种方法也越来越流行,部分原因是 IPv4 地址耗尽。
当多个应用程序可通过同一 IP 地址访问时,这通常是以下情况之一的结果。
虚拟主机
一种可能的情况是单个 Web 服务器托管多个网站或应用程序。这可能是一个所有者的多个网站,但也可以将拥有不同所有者的网站托管在一个共享平台上。这不像以前那么常见,但仍然会出现在一些基于云的 SaaS 解决方案中。
在任何一种情况下,虽然这些不同的网站中的每一个都有不同的域名,但它们都与服务器共享一个公共 IP 地址。在单个服务器上以这种方式托管的网站被称为“虚拟主机”。
对于访问网站的普通用户来说,虚拟主机通常与托管在其自己的专用服务器上的网站无法区分。
通过中介路由流量
另一种常见情况是网站托管在不同的后端服务器上,但客户端和服务器之间的所有流量都通过中间系统路由。这可能是一个简单的负载平衡器或某种反向代理服务器。这种设置在客户端通过内容交付网络 (CDN) 访问网站的情况下尤为普遍。
在这种情况下,即使网站托管在单独的后端服务器上,它们的所有域名也解析为中间组件的单个 IP 地址。这带来了一些与虚拟主机相同的挑战,因为反向代理或负载平衡器需要知道它应该将每个请求路由到的适当后端。
HTTP Host 头是如何解决这个问题的?
在这两种情况下,都依赖 Host 标头来指定预期的收件人。一个常见的类比是给住在公寓楼的人寄一封信的过程。整栋建筑都有相同的街道地址,但在这个街道地址后面有许多不同的公寓,每个公寓都需要以某种方式接收正确的邮件。解决此问题的一种方法是简单地在地址中包含公寓号或收件人姓名。在 HTTP 消息的情况下,Host 头用于类似的目的。
当浏览器发送请求时,目标 URL 将解析为特定服务器的 IP 地址。当此服务器收到请求时,它会参考 Host 标头来确定预期的后端并相应地转发请求。
什么是 HTTP 主机标头攻击?
HTTP Host 标头攻击利用易受攻击的网站,这些网站以不安全的方式处理 Host 标头的值。如果服务器隐式信任 Host 标头,并且未能正确验证或转义它,则攻击者可能能够使用此输入注入操纵服务器端行为的有害负载。涉及将有效负载直接注入主机标头的攻击通常称为“主机标头注入”攻击。
除非在安装过程中在配置文件中手动指定,否则现成的 Web 应用程序通常不知道它们部署在哪个域上。当他们需要知道当前域时,例如,要生成包含在电子邮件中的绝对 URL,他们可能会求助于从 Host 标头中检索域:
Contact support
标头值还可用于网站基础设施的不同系统之间的各种交互。
由于 Host 标头实际上是用户可控制的,因此这种做法可能会导致许多问题。如果输入未正确转义或验证,则 Host 标头是利用一系列其他漏洞的潜在载体,最显着的是:
- 网页缓存中毒
- 特定功能中的 业务逻辑缺陷
- 基于路由的SSRF
- 经典的服务器端漏洞,例如 SQL 注入
HTTP 主机头漏洞是如何产生的?
HTTP Host 标头漏洞通常是由于用户无法控制标头的错误假设而出现的。这会在 Host 标头中创建隐式信任并导致验证不充分或对其值进行转义,即使攻击者可以使用 Burp Proxy 等工具轻松修改它。
即使 Host 标头本身被更安全地处理,根据处理传入请求的服务器的配置,Host 可能会通过注入其他标头而被覆盖。有时网站所有者不知道默认情况下支持这些标头,因此,它们可能不会受到相同级别的审查。
事实上,许多这些漏洞的出现并不是因为不安全的编码,而是因为相关基础设施中一个或多个组件的不安全配置。之所以会出现这些配置问题,是因为网站将第三方技术集成到其架构中,而不必了解配置选项及其安全含义。
如何验证http主机头漏洞?
通过修改 Host 标头,利用burp发送请求看是否到达目标应用程序。具体 step1: 将Host 标头修改成任意的、无法识别的域名时观察会发生什么。(返回指定网站存在http主机头漏洞) sep2:step1更大可能返回的结果是报Invalid Host header。可能是因为以下中原因导致的:
- 网站存在CDN,CDN无法识别解析
- 某些网站会验证 Host 标头是否与来自 TLS 握手的 SNI 匹配
这时候需要继续验证:
- 某些解析算法会从 Host 标头中省略端口,这意味着仅验证域名。如果您还能够提供非数字端口,则可以保持域名不变以确保到达目标应用程序,同时可能通过端口注入有效负载,类似于:
GET /example HTTP/1.1 Host: vulnerable-website.com:bad-stuff-here
其他站点将尝试应用匹配逻辑以允许任意子域。在这种情况下,您可以通过注册一个以与列入白名单的字符序列相同的字符序列结尾的任意域名来完全绕过验证:
GET /example HTTP/1.1 Host: notvulnerable-website.com
或者,您可以利用您已经攻陷的安全性较低的子域:
GET /example HTTP/1.1 Host: hacked-subdomain.vulnerable-website.com
如何利用http主机头漏洞?
注入重复的主机标头 一种可能的方法是尝试添加重复的 Host 标头。诚然,这通常只会导致您的请求被阻止。但是,由于浏览器不太可能发送这样的请求,您可能偶尔会发现开发人员没有预料到这种情况。在这种情况下,您可能会暴露一些有趣的行为怪癖。
不同的系统和技术会以不同的方式处理这种情况,但通常两个标头之一优先于另一个标头,从而有效地覆盖其值。当系统不同意哪个标头是正确的标头时,这可能会导致您可以利用的差异。考虑以下请求: GET /example HTTP/1.1 Host: vulnerable-website.com Host: bad-stuff-here 假设前端优先于标头的第一个实例,但后端更喜欢最后一个实例。在这种情况下,您可以使用第一个标头来确保您的请求被路由到预期目标,并使用第二个标头将您的有效负载传递到服务器端代码中。
如何防止HTTP Host头攻击
如何防止HTTP Host头攻击 为了防止 HTTP Host 标头攻击,最简单的方法是避免在服务器端代码中完全使用 Host 标头。仔细检查每个 URL 是否真的需要是绝对的。您经常会发现,您可以只使用相对 URL。这种简单的更改可以帮助您特别防止Web 缓存中毒漏洞。
其他防止 HTTP Host 标头攻击的方法包括:
保护绝对 URL 当您必须使用绝对 URL 时,您应该要求在配置文件中手动指定当前域并引用此值而不是 Host 标头。例如,这种方法将消除密码重置中毒的威胁。
验证主机标头 如果您必须使用 Host 标头,请确保正确验证它。这应该涉及根据允许域的白名单进行检查,并拒绝或重定向对无法识别的主机的任何请求。您应该查阅框架的文档以获取有关如何执行此操作的指导。例如,Django 框架ALLOWED_HOSTS在设置文件中提供了该选项。这种方法将减少您遭受 Host 标头注入攻击的风险。
不支持主机覆盖标头 检查您是否不支持可用于构建这些攻击的其他标头也很重要,尤其是X-Forwarded-Host. 请记住,默认情况下可能支持这些。
白名单允许的域 为了防止对内部基础设施的基于路由的攻击,您应该配置您的负载平衡器或任何反向代理,以仅将请求转发到允许域的白名单。
小心使用仅限内部的虚拟主机 使用虚拟主机时,您应该避免在与面向公众的内容相同的服务器上托管仅供内部使用的网站和应用程序。否则,攻击者可能能够通过主机头操作访问内部域。
|