如何识别和利用HTTP主机头漏洞
翻译
原文:https://portswigger.net/web-security/host-header/exploiting
- name: 翻译
desc: 原文:https://portswigger.net/web-security/host-header/exploiting
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 1如何识别和利用HTTP主机头漏洞
在本节中,我们将更仔细地研究,如何识别网站是否容易受到 HTTP 主机头攻击 (opens new window)。然后,我们将提供如何利用此漏洞的示例,以及多个交互式实验室,你可以在故意易受攻击的网站上练习这些漏洞。
# 2如何使用HTTP Host标头测试漏洞
要测试网站是否容易受到 HTTP Host 标头的攻击,你需要一个拦截代理(例如 Burp Proxy)和手动测试工具(例如 Burp Repeater 和 Burp Intruder)。
简而言之,你需要确定Host
标头是否能够修改,并且在修改之后,你的请求仍然可以到达目标应用程序。如果确实是这样,你可以使用此标头来探测应用程序,并观察这对响应的影响。
# 2.1提供任意Host标头
在探测主机头注入漏洞时,第一步,测试当通过Host
标头提供任意的、无法识别的域名时会发生什么。
一些拦截代理直接从Host
标头中获取目标 IP 地址,这使得这种测试几乎是不可能的;你对标头所做的任何更改,都只会导致请求被发送到完全不同的 IP 地址。但是,Burp Suite 准确地保持了Host
标头和目标 IP 地址之间的分离。这种分离允许你提供所需的任意Host
标头(即使是故意格式不正确的),同时仍确保将请求发送到预期目标。
提示
目标 URL 显示在面板的顶部(用于 Burp Repeater 和 Proxy 拦截)或 Burp Intruder 中的 “Target” 选项卡上。你可以通过单击 铅笔图标 来手动编辑目标。
有时,即使你提供了意外的Host
标头,你仍然可以访问目标网站。这可能出于多种原因。例如,服务器有时会配置一个默认或回退选项,以防它们收到了无法识别的域名请求。如果你的目标网站恰好使用了默认设置,你是幸运的。在这种情况下,你可以开始研究应用程序是如何处理Host
标头的,以及此行为是否可被利用。
另一方面,由于Host
标头是网站工作方式的基本组成部分,因此篡改它通常意味着,你可能会无法访问目标应用程序。收到请求的前端服务器 或 负载均衡器,可能只是不知道将请求转发到何处,从而导致某种类型的 “Invalid Host header
” 错误。如果你是通过 CDN 去访问目标的,则尤其可能出现这种情况。在这种情况下,你应该继续尝试下面概述的一些技术。
# 2.2检查有缺陷的验证
你可能会发现,由于某种安全措施,你没有收到 “Invalid Host header
” 响应,你的请求直接被阻止了。例如,某些网站会验证Host
标头是否与 TLS 握手中的 SNI 匹配。但这并不一定意味着它们对主机头攻击免疫。
你应该尝试了解网站如何解析Host
标头。这有时会暴露出可用于绕过验证的漏洞。例如,某些解析算法会省略Host
标头中的端口,这意味着只验证域名。如果你能够提供一个非数字端口,则可以保持域名不变,以确保到达目标应用程序,同时通过该端口注入有效载荷。
GET /example HTTP/1.1
Host: vulnerable-website.com:这里有坏东西
2
某些网站会尝试应用匹配逻辑,以允许任意子域。在这种情况下,你可以注册一个与白名单匹配的任意域名,只需要以相同的字符序列 结尾 即可,从而完全绕过验证:
GET /example HTTP/1.1
Host: notvulnerable-website.com
2
或者,你可以利用安全性较低 且 已经受你控制的子域:
GET /example HTTP/1.1
Host: hacked-subdomain.vulnerable-website.com
2
有关常见的 域名验证缺陷 的更多示例,请查看我们关于规避常规 SSRF 防御 (opens new window)和 Origin 标头解析错误 (opens new window)的内容。
# 2.3发送模糊请求
验证主机的代码 和 对其执行易受攻击操作的代码,通常位于不同的应用程序组件中,甚至位于不同的服务器上。通过识别和利用它们在检索Host
标头时的差异,你可以发出一个模糊的请求,该请求似乎携带不同的主机名,具体取决于哪个系统正在查看它。
以下是如何创建模糊请求的几个示例。
# 2.3.1重复注入Host标头
一种可能的方法是,尝试重复添加Host
标头。不可否认的是,这通常只会导致你的请求被阻止。但是,由于浏览器不太可能发送此类请求,因此你可能偶尔会发现,一些开发人员没有预料到这种情况。在这种场景下,你可能会发现一些有趣的行为差异。
不同的系统和技术,会以不同的方式处理这种情况,但通常两个标头中的一个会 优先于 另一个,从而有效地覆盖其值。当系统不确定哪一个标头是正确的标头时,这可能会产生你可以利用的差异。考虑以下请求:
GET /example HTTP/1.1
Host: vulnerable-website.com
Host: 这里有坏东西
2
3
假设前端优先考虑标头的第一个实例,但后端优先考虑最后一个实例。在这种情况下,你可以使用第一个标头,来确保该请求被路由到预期目标。然后使用第二个标头,将有效载荷传递到服务端代码中。
# 2.3.2提供绝对URL
尽管请求行通常用于指定 所请求域上的相对路径,但许多服务器也配置为兼容绝对 URL 的请求。
同时提供绝对 URL 和Host
标头导致的差异,也可能导致不同系统之间的差异。正式地说,在路由某个请求时,应该优先考虑请求行,但实际上并非总是如此。你可以利用这些差异,其方式与重复添加Host
标头大致相同。
GET https://vulnerable-website.com/ HTTP/1.1
Host: 这里有坏东西
2
请注意,你可能还需要尝试不同的协议。服务器有时会根据请求行中的 URL 是否包含 HTTP 或 HTTPS 而表现不同。
# 2.3.3添加换行
你还可以使用空格字符来缩进 HTTP 标头,从而发现古怪的行为。一些服务器会将缩进的标头解释为换行,因此将其视为前一个标头值的一部分。而其他服务器将完全忽略缩进标头。
由于对这种情况的处理高度不一致,因此在处理你的请求时,不同的系统之间经常会出现差异。例如,考虑以下请求:
GET /example HTTP/1.1
Host: 这里有坏东西
Host: vulnerable-website.com
2
3
如果按照前面的方法,网站可能会阻止具有多个Host
标头的请求,但你可以像这样缩进其中一个标头,来绕过此验证,如上所示。如果前端忽略了缩进的标头,则该请求将被作为一个普通请求进行处理(vulnerable-website.com
)。现在,假设后端忽略前导空格,并在重复的情况下优先考虑第一个标头。这种差异可能允许你 “包装” Host
标头来传递任意值。
# 2.3.4其他技术
以上可用于发出有害、模糊请求的方式,这只是众多可行方法中的一小部分。例如,你还可以采用 HTTP 请求走私技术来构建主机头攻击。我们将在专门的 请求走私主题 中更详细地介绍这一点。
# 2.4注入Host覆盖标头
即使你无法使用模糊的请求来覆盖Host
标头,也有其他覆盖主机值的可能性,同时保持其效果不变。这包括通过其他几个 HTTP 标头之一来注入你的有效负载,这些标头就是为了这个目的而设计的,尽管用于更无辜的用例。
正如我们已经讨论过的,网站一般是通过某种中间系统访问的,例如负载均衡器或反向代理。在这种体系结构中,后端服务器接收的Host
标头中,可能会包含某个中间系统的域名。这通常与所请求的功能无关。
为了解决这个问题,前端可能会注入X-Forwarded-Host
标头,其中包含来自客户端初始请求的Host
标头原始值。因此,当存在X-Forwarded-Host
标头时,许多框架都会引用它。即使前端没有使用此标头,也可能会观察到此行为。
你有时可以使用X-Forwarded-Host
来注入恶意输入,同时绕过Host
标头本身的任何验证。
GET /example HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-Host: 这里有坏东西
2
3
尽管X-Forwarded-Host
是这种行为的事实标准,但你可能会遇到其他具有类似用途的标头,包括:
X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
提示
在 Burp Suite 中,你可以使用 Param Miner (opens new window) 扩展的 “Guess header”(猜测标头) 功能,通过其广泛的内置单词列表,来自动探测目标所支持的标头。
从安全的角度来看,请务必注意,某些网站(甚至可能是你自己的网站)会无意中支持这种行为。这通常是因为它们使用了某些第三方技术,这些技术默认情况下 启用了这些标头中的一个或多个。
# 3如何利用HTTP Host标头
一旦你确定了,可以将任意主机名传递给目标应用程序,就可以开始寻找利用它的方法。
在本节中,我们将提供一些常见的 HTTP 主机头攻击示例,你可以试着构建这些攻击。我们还创建了一些故意易受攻击的网站,以便你可以了解这些漏洞是如何工作的,并测试你所学到的知识。
我们将介绍以下示例:
- 密码重置投毒 (opens new window)LABS
- Web缓存投毒 (opens new window)LABS
- 利用经典的服务端漏洞 (opens new window)
- 身份验证绕过 (opens new window)LABS
- 虚拟主机暴力破解 (opens new window)
- 基于路由的 SSRF (opens new window)LABS
# 3.1密码重置投毒
攻击者有时可以使用Host
标头进行密码重置投毒攻击。
# 3.2通过Host标头实现的Web缓存投毒
在探测潜在的主机头攻击时,你经常会遇到看似易受攻击的行为,但这些行为无法直接利用。例如,你可能会发现Host
标头反映在响应标记中,而没有 HTML 编码,甚至直接用于脚本导入。由Host
标头引起的反射型客户端漏洞(如 XSS)通常不可利用。攻击者无法以有效的方式,强制受害者的浏览器发出错误的主机名。
但是,如果目标使用 Web 缓存,则有可能毒害缓存,然后向其他用户提供毒化响应,将这种无用的反射型漏洞 转换成 危险的存储漏洞。
要构建 Web 缓存投毒攻击,你需要从服务器引出 包含有效载荷的响应。难点在于,在执行此操作的同时保留缓存键,使载荷仍然映射到其他用户的请求。如果成功,下一步就是缓存此恶意响应。随后,恶意响应将提供给 试图访问受影响页面 的任何用户。
独立缓存通常在缓存键中包含Host
标头,因此这种方法一般最适合用在 集成的应用程序级缓存 身上。也就是说,前面所讨论的技术,有时甚至可以使你毒害独立的 Web 缓存。
- name: 实验室-从业者
desc: 模糊请求导致的Web缓存投毒 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/host-header/exploiting/lab-host-header-web-cache-poisoning-via-ambiguous-requests
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
Web 缓存投毒在安全学院的一个专门主题中得到了充分的介绍。
# 3.3利用经典的服务端漏洞
每个 HTTP 标头都是经典服务端漏洞的潜在利用载体,Host
标头也不例外。例如,你应该通过Host
标头来尝试通用的 SQL 注入 (opens new window)探测技术。如果标头的值被传递到 SQL 语句中,则可能发起攻击。
# 3.4访问受限功能
出于相当明显的原因,网站通常会 限制用户访问某些内部功能。但是,一些网站的访问控制 (opens new window)功能会做出有缺陷的假设,从而允许你对Host
标头进行简单修改,来绕过这些限制。这可能会增加其他漏洞的攻击面。
- name: 实验室-学徒
desc: Host标头身份验证绕过 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/host-header/exploiting/lab-host-header-authentication-bypass
bgColor: '#001350'
textColor: '#39d50c'
2
3
4
5
6
# 3.5虚拟主机暴力破解并访问内部站点
企业有时会犯这样一个错误,某台服务器同时具有公共 IP 地址和私有 IP 地址,然后在同一台服务器上托管可公开访问的网站 和 私人内部网站。由于内部主机名可能会解析为私有 IP 地址,因此无法通过查看 DNS 记录来检测这种情况:
www.example.com: 12.34.56.78
intranet.example.com: 10.0.0.132
2
在某些情况下,内部站点甚至可能没有与之关联的公共 DNS 记录。尽管如此,攻击者通常可以在他们有权访问的任何服务器上,访问其上的任何虚拟主机,前提是他们能够猜测主机名。如果他们通过其他方式(例如信息泄露 (opens new window))发现了隐藏的域名,他们可以直接发出请求。否则,他们可以使用 Burp Intruder 等工具,使用候选子域的简单单词列表,来暴力破解虚拟主机。
# 3.6基于路由的SSRF
有时,也可以使用Host
标头发起高影响的、基于路由的 SSRF 攻击。这些攻击有时被称为 “主机头 SSRF 攻击”,PortSwigger 研究团队在《打破透明化-定位HTTP的隐藏攻击面》 (opens new window)一文中进行了深入探讨。
经典的 SSRF 漏洞通常基于 XXE (opens new window) 或可利用的业务逻辑,这些业务逻辑将 HTTP 请求发送到派生自用户可控输入的 URL。另一方面,利用基于路由的 SSRF 依赖于许多云架构中普遍存在的中间组件。这包括内部负载均衡器和反向代理。
尽管这些组件是出于不同需求而部署的,但从根本上说,它们都会接收请求 并 将其转发到适当的后端。如果它们被不安全地配置,从而基于未经验证的Host
标头来转发请求,则可以操纵它们将请求错误地 路由到攻击者选择的任意系统。
这些系统是绝佳的目标。它们位于特权网络位置,允许他们直接从公共网络接收请求,同时还可以访问大部分(如果不是全部)内部网络。这使得Host
标头成为 SSRF 攻击的强大载体,这也许会将简单的负载均衡器 转换为 整个内部网络的网关。
你可以使用 Burp Collaborator 来帮助识别这些漏洞。如果在Host
标头中提供 Collaborator 服务器的域,随后从目标服务器或其他系统接收 DNS 查找,则表明你可以将请求路由到任意域。
在确认你可以成功地操纵中间系统,并将请求路由到任意公共服务器之后,下一步是查看 是否可以利用此行为来访问仅限内部的系统。为此,你需要识别目标内部网络上正在使用哪些私有 IP 地址。除了应用程序泄露的任何 IP 地址外,你还可以扫描属于该公司的主机名,以查看是否有任何解析到私有 IP 地址的主机名。如果所有其他方法都失败,你仍然可以通过简单地暴力破解标准私有 IP 范围(例如192.168.0.0/16
)来识别有效的 IP 地址。
CIDR表示法
IP 地址范围通常使用 CIDR 表示法来表达,例如192.168.0.0/16
。
IPv4 地址由四个 8 位十进制值组成,称为 “八位字节”,每个十进制值之间有一个点分隔。每个八位字节的值范围由 0 到 255,这意味着最低可能的 IPv4 地址为0.0.0.0
,最高为255.255.255.255
。
在 CIDR 表示法中,应该显式写入范围中最低的 IP 地址,后面跟另一个数字,表示从给定地址开始的整个范围内固定了多少位。例如,10.0.0.0/8
表示前 8 位是固定的(第一个八位字节)。换句话说,此范围包括从10.0.0.0
到10.255.255.255
的所有 IP 地址。
- name: 实验室-从业者
desc: 基于路由的SSRF >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/host-header/exploiting/lab-host-header-routing-based-ssrf
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
- name: 实验室-从业者
desc: 通过请求解析缺陷实现SSRF >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/host-header/exploiting/lab-host-header-ssrf-via-flawed-request-parsing
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 3.7连接状态攻击
出于性能原因,许多网站在与同一客户端的 多个请求/响应周期 中重用连接。有时,实现不当的 HTTP 服务会基于一个危险的假设,即对于某些属性(如Host
标头)通过同一连接发送的所有 HTTP/1.1 请求都是相同的。对于浏览器发送的请求,这可能是正确的,但对于从 Burp Repeater 发送的一系列请求,情况不一定如此。这可能会导致许多潜在问题。
例如,你可能偶尔会遇到这种情况,建立新连接后,服务器仅对收到的第一个请求执行彻底验证。在这种情况下,你可以发送一个看似无辜的初始请求,然后在同一连接之中,继续发送你的恶意请求来绕过此验证。
- name: 实验室-从业者
desc: 通过连接状态攻击绕过Host验证 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/host-header/exploiting/lab-host-header-host-validation-bypass-via-connection-state-attack
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
许多反向代理使用Host
标头来将请求路由到正确的后端。如果他们假定,连接上的所有请求 都 与初始请求发往同一主机,则可以为许多主机头攻击提供有用的媒介,包括基于路由的 SSRF、密码重置投毒和缓存投毒。
# 3.8通过格式错误的请求行造成SSRF
自定义代理有时无法正确验证请求行,这可能会允许你提供异常、格式错误的输入,从而导致不幸的结果。
例如,反向代理可能会从请求行获取路径,为该路径加上前缀http://backend-server
,然后将请求路由到该上游 URL。如果路径以/
字符开头,这很好,但如果以@
字符开头呢?
GET @private-intranet/example HTTP/1.1
生成的上游 URL 将会是http://backend-server@private-intranet/example
,大多数 HTTP 库将其解析为使用用户名backend-server
访问private-intranet
的请求。
Research
我们的研究总监 James Kettle 也推广了这些技术。有关该技术、工具以及他如何在野外利用这些漏洞的更详细描述,请查看我们研究页面上的完整白皮书和视频演示。