# 如何识别和利用HTTP Host头的漏洞

在本节中，我们将更详细地了解如何识别一个网站是否容易受到HTTP Host标头攻击。然后我们将提供一些攻击示例，以及一些交互式实验，供你在一个故意易受攻击的网站上练习这些攻击方法。

## 如何使用HTTP Host标头测试漏洞

要测试一个网站是否容易受到HTTP Host标头攻击，你需要一个截断代理，如Burp Proxy，以及手动测试工具，如Burp Repeater和Burp Intruder。

简而言之，你需要确定你是否能够修改Host标头，并且使你的请求到达目标应用程序。如果可以，你可以使用此标头探测应用程序并观察其对响应的影响。

### **提供一个任意Host标头**

在探测Host标头注入漏洞时，第一步是测试当你通过Host标头提供一个任意的、无法识别的域名时会发生什么。

某些截断代理直接从Host标头获取目标IP地址，这使得这种测试几乎不可能；你对标头所做的任何更改都会导致请求被发送到一个完全不同的IP地址。不过，Burp Suite准确地保持了Host标头与目标IP地址之间的分离。这种分离允许你提供任意或格式错误的Host标头，同时确保请求被发送到预期的目标。

> **Tip**
>
> 目标URL显示在面板顶部（对于Burp Repeater和Proxy拦截）或Burp Intruder的“Target”选项卡上。你可以通过点击铅笔图标手动编辑目标。

有时，即使你提供了一个意想不到的Host标头，仍然可以访问目标网站。这可能是出于多种原因。例如，服务器有时会配置一个默认或后备选项，以防它们收到不认识的域名的请求。如果你的目标网站恰好是默认设置，那么你就很幸运。在这种情况下，你可以开始研究应用程序如何处理Host标头以及，这种行为是否可被利用。

另一方面，由于Host标头是网站工作的一个基本部分，篡改它通常意味着你将无法完全访问目标应用程序。接收到你请求的前端服务器或负载均衡器可能根本不知道该如何转发它，从而导致某种“`Invalid Host header`”的错误。如果你的目标是通过CDN访问的，那么这种情况尤其可能发生。在这种情况下，应该尝试以下概述的一些技术。

### **检查有缺陷的验证**

你可能会发现，由于某种安全措施，你的请求被阻止，而不是收到“`Invalid Host header`”的响应。例如，有些网站会验证Host标头是否与TLS握手中的SNI匹配。这并不一定意味着它们对Host标头攻击是免疫的。

你应该尝试了解网站如何解析Host标头。有时可以揭示出可用于绕过验证的漏洞。例如，一些解析算法会省略Host标头中的端口，这意味着只有域名被验证。如果你还能够提供一个非数字端口，你就可以保持域名不变以确保到达目标应用程序，同时可能通过端口注入payload。

```http
GET /example HTTP/1.1
Host: vulnerable-website.com:bad-stuff-here
```

其他网站会尝试应用匹配逻辑以允许任意子域。在这种情况下，你可以通过注册一个以与白名单域名相同的字符序列结尾的任意域名来完全绕过验证：

```http
GET /example HTTP/1.1
Host: notvulnerable-website.com
```

或者，你可以利用你已经入侵的不安全子域：

```http
GET /example HTTP/1.1
Host: hacked-subdomain.vulnerable-website.com
```

要了解更多关于常见域验证漏洞的示例，请查看我们的关于绕过常见SSRF防御和Origin标头解析错误的内容。

### **发送模棱两可的请求**

验证主机和执行易受攻击操作的代码通常位于不同的应用程序组件，甚至在不同的服务器上。通过识别和利用它们在检索Host标头方面的差异，你可能可以发出一个模棱两可的请求，根据查看它的系统，请求似乎具有不同的主机。

以下仅仅是一些可能创建模棱两可请求的示例。

#### **注入重复的Host标头**

一种可能的方法是尝试添加重复的Host标头。无可否认，这通常只会导致你的请求被阻止。然而，因为浏览器不太可能发送这样的请求，你可能偶尔会发现开发人员没有预料到这种情况。在这种情况下，可能会暴露出一些有趣的行为特性。

不同的系统和技术会以不同的方式处理这种情况，但通常其中一个标头会优先于另一个，有效地覆盖其值。当系统在哪个标头是正确的上存在分歧时，这可能导致你可以利用这种差异。考虑以下请求：

```http
GET /example HTTP/1.1
Host: vulnerable-website.com
Host: bad-stuff-here
```

假设前端优先考虑标头的第一个实例，但后端更倾向于最后一个实例。在这种情况下，你可以使用第一个标头确保你的请求被路由到预期的目标，并使用第二个标头将payload传递到服务器端代码中。

#### **提供一个绝对URL**

尽管请求行通常在请求域中指定相对路径，但许多服务器还配置为理解绝对URL的请求。

通过同时提供绝对URL和Host标头引起的歧义也可能导致不同系统之间的差异。从官方角度说，请求行应在路由请求时被优先考虑，但在实践中，情况并非总是如此。你可以像处理重复Host标头一样来利用这些差异。

```http
GET https://vulnerable-website.com/ HTTP/1.1
Host: bad-stuff-here
```

请注意，你可能还需要尝试不同的协议。根据请求行中包含的是HTTP还是HTTPS URL，服务器的行为有时会有所不同。

#### **添加换行**

通过使用空格字符缩进HTTP标头，你还可以发现奇特的行为。有些服务器会将缩进的标头解释为换行符，因此将其视为前一个标头值的一部分。其他服务器将完全忽略缩进的标头。

由于对这种情况的处理非常不一致，处理你的请求的不同系统之间通常会存在差异。例如，考虑以下请求：

```http
GET /example HTTP/1.1
    Host: bad-stuff-here
Host: vulnerable-website.com
```

网站可能会阻止带有多个Host标头的请求，但你可以通过像这样缩进其中一个来绕过此验证。如果前端忽略了缩进的标头，改请求将被作为`vulnerable-website.com`的普通请求处理。现在假设后端忽略了前面的空格，并在出现重复的情况下优先考虑第一个标头。这种差异可能会让你通过“包装”的Host标头传递任意值。

#### **其他技术**

这只是众多可能发出有害、模棱两可请求的方法中的一小部分。例如，你还可以调整许多HTTP请求走私技术来构造Host标头攻击。我们将在我们专用的请求走私主题中更详细地介绍这个问题。

> **阅读更多**
>
> [HTTP请求走私](https://web-sec.gitbook.io/wsa/advanced/request-smuggling)

### **注入主机覆盖标头**

即使你无法使用一个模棱两可的请求来覆盖Host标头，也可以在保持其完整的同时通过其他方式覆盖其值。这包括通过设计用于此目的的几种HTTP标头之一注入你的payload，尽管是为了更无害的用例。

正如我们已经讨论过的，网站通常通过某种中间件系统进行访问，例如负载均衡器或反向代理。在这种架构中，后端服务器收到的Host标头可能包含这些中间件系统之一的域名。通常这与所请求的功能无关。

为了解决这个问题，前端可能会注入`X-Forwarded-Host`标头，其中包含客户端初始请求中Host标头的原始值。因此，当存在`X-Forwarded-Host`标头时，许多框架会引用这个头来代替。即使没有使用此标头的前端，也可能观察到这种行为。

有时可以使用`X-Forwarded-Host`在绕过Host标头本身的任何验证的同时，注入恶意输入。

```http
GET /example HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-Host: bad-stuff-here
```

尽管`X-Forwarded-Host`是此行为的事实标准，但你可能会遇到用途相似的其他标头，包括：

* `X-Host`
* `X-Forwarded-Server`
* `X-HTTP-Host-Override`
* `Forwarded`

> **Tip**
>
> 在Burp Suite中，你可以使用[Param Miner](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943)扩展的“Guess headers”功能，通过其广泛的内置字典自动探测支持的标头。

从安全角度来看，需要注意的是，一些网站（甚至可能包括你自己的网站）无意中支持这种行为。通常这是因为他们使用的某些第三方技术中默认启用了一个或多个这些标头。

## 如何利用HTTP Host标头

一旦确定可以将任意主机名传递给目标应用程序，你就可以开始寻找利用它的方法了。

在这一部分，我们将提供一些常见的HTTP Host标头攻击示例，以便你可以构造。我们还创建了一些故意易受攻击的网站，以便你了解这些漏洞是如何工作的，并将所学应用于实践。

我们将介绍以下示例：

* 密码重置投毒
* Web缓存投毒
* 利用经典的服务器端漏洞
* 绕过认证
* 虚拟主机暴破
* 基于路由的SSRF

### **密码重置投毒**

攻击者有时可以使用Host标头进行密码重置投毒攻击。

> **阅读更多**
>
> [密码重置投毒](https://web-sec.gitbook.io/wsa/advanced/host-header/password-reset-poisoning)

### **通过Host标头进行Web缓存投毒**

在探测潜在的Host标头攻击时，你经常会遇到看似容易受攻击的行为，但实际上无法直接利用。例如，你可能会发现Host标头在响应标记中没有经过HTML编码地反映出来，甚至直接用于脚本导入。通常情况下，由Host标头引起的客户端漏洞（如XSS）是无法利用的，因为攻击者无法以有用的方式迫使受害者的浏览器发出不正确的Host请求。

然而，如果目标使用Web缓存，那么通过说服缓存向其他用户提供毒化的响应，将这种无用的反射型漏洞转变为危险的存储型漏洞是可能的。

要构造一个Web缓存投毒攻击，你需要从服务器那里获得反射注入payload的响应。挑战在于，在保留仍然映射到其他用户请求的缓存键的同时完成此操作。成功后，下一步是让这个恶意响应被缓存。然后，任何试图访问受影响页面的用户都会收到这个响应。

独立的缓存通常将Host标头包含在缓存键中，因此这种方法通常在集成的应用程序级缓存上效果最好。话虽如此，前面讨论过的技术有时可以使你在独立的Web缓存中进行投毒。

> **LAB**
>
> [通过模棱两可的请求进行Web缓存投毒](https://portswigger.net/web-security/host-header/exploiting/lab-host-header-web-cache-poisoning-via-ambiguous-requests)

Web缓存投毒在Web安全学院的专题中有详细的介绍。

> **阅读更多**
>
> [Web缓存投毒](https://web-sec.gitbook.io/wsa/advanced/web-cache-poisoning)

### **利用经典的服务器端漏洞**

每个HTTP标头都是利用经典的服务器端漏洞的潜在载体，Host标头也不例外。例如，你应该尝试通过Host标头使用常见的SQL注入探测技术。如果标头值被传递到SQL语句中，这可能是可利用的。

### **访问受限制的功能**

出于显而易见的原因，网站通常仅向内部用户提供访问某些功能的权限。然而，一些网站的访问控制功能存在缺陷，允许你通过对Host标头进行简单修改来绕过这些限制。这可能会暴露更多的攻击面。

> **LAB**
>
> [Host标头认证绕过](https://portswigger.net/web-security/host-header/exploiting/lab-host-header-authentication-bypass)

### **通过虚拟主机暴破访问内部网站**

公司有时会犯一个错误，即在同一台服务器上托管公共可访问的网站和私有的内部网站。服务器通常既有公共IP地址，也有私有IP地址。由于内部主机名可能解析为私有IP地址，因此仅仅通过查看DNS记录并不能总是检测到这种情况：

```
www.example.com: 12.34.56.78
intranet.example.com: 10.0.0.132
```

在某些情况下，内部站点甚至可能没有与之关联的公共DNS记录。尽管如此，攻击者通常可以访问他们能够访问的任何服务器上的任何虚拟主机，只要他们能猜到主机名。如果通过其他途径（例如信息披露）发现了一个隐藏的域名，他们可以直接请求这个域名。否则，他们可以使用诸如Burp Intruder之类的工具，使用候选子域名的词典暴破虚拟主机。

### **基于路由的SSRF**

有时，还可以使用Host标头发起重大影响的、基于路由的SSRF攻击。这些攻击有时被称为“Host标头SSRF攻击”，PortSwigger Research在[《破解镜头：针对HTTP的隐藏攻击面》](https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface)一文中进行了深入探讨。

经典的SSRF漏洞通常基于XXE或可利用的业务逻辑，该逻辑将根据用户可控输入派生的URL发送HTTP请求。另一方面，基于路由的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位十进制值组成，这些值称为“octets”，每个八位字节之间用点分隔。每个八位字节的值可以从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地址。

> **LAB**
>
> [基于路由的SSRF](https://portswigger.net/web-security/host-header/exploiting/lab-host-header-routing-based-ssrf)

> **LAB**
>
> [通过有缺陷的请求解析进行SSRF](https://portswigger.net/web-security/host-header/exploiting/lab-host-header-ssrf-via-flawed-request-parsing)

### **连接状态攻击**

出于性能原因，许多网站在与同一客户端进行多个请求/响应周期时会重用连接。实现不佳的HTTP服务器有时会基于危险的假设来工作，即某些属性（如Host标头）在通过同一连接发送的所有HTTP/1.1请求中都是相同的。对于浏览器发送的请求，这可能是正确的，但对于从Burp Repeater发送的一系列请求来说，情况并非总是如此。这可能导致一些潜在问题。

例如，你可能偶尔会遇到一些服务器，它们只对通过新连接收到的第一个请求进行彻底验证。在这种情况下，你可以通过首先发送一个看似无害的请求，然后通过相同的连接发送恶意请求来绕过此验证。

> **LAB**
>
> [通过连接状态攻击绕过主机验证](https://portswigger.net/web-security/host-header/exploiting/lab-host-header-host-validation-bypass-via-connection-state-attack)

许多反向代理使用Host标头将请求路由到正确的后端。如果它们假设与初始请求相同的主机上的所有请求都在连接上，这可以为许多Host标头攻击提供有用的载体，包括基于路由的SSRF、密码重置投毒和缓存投毒。

### **通过一个异常请求行SSRF**

自定义代理有时未能正确验证请求行，这可能允许你提供不寻常的、格式错误的输入，造成不幸的结果。

例如，反向代理可能会从请求行中获取路径，用`http://backend-server`作为前缀，并将请求路由到该上游URL。如果路径以`/`字符开头，这没问题，但如果以`@`字符开头呢？

```http
GET @private-intranet/example HTTP/1.1
```

生成的上游URL将是`http://backend-server@private-intranet/example`，大多数HTTP库将其解释为以`backend-server`用户名访问`private-intranet`的请求。

> **研究**
>
> 这些技术还受到我们研究总监James Kettle的推广。有关技术、工具以及他如何在现实中利用这些漏洞的详细描述，请查看我们研究页面上的完整白皮书和视频演示。

> [破解镜头：针对HTTP的隐藏攻击面](https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface)
>
> [PortSwigger Research](https://portswigger.net/research)
