portswigger_AdvancedTopics

Advanced topics

JWT attacks

JWT攻击 In this section, we’ll look at how design issues and flawed handling of JSON web tokens (JWTs) can leave websites vulnerable to a variety of high-severity attacks. As JWTs are most commonly used in authentication, session management, and access control mechanisms, these vulnerabilities can potentially compromise the entire website and its users.

1
这部分,我们将专注于研究设计问题与jwt处理不当是如何导致网站受到高危攻击的。JWT普遍用于授权、会话管理与权限控制机制,这些漏洞能潜移默化地使整个网站与其用户被入侵。

image.png

Tip:From Burp Suite Professional 2022.5.1, Burp Scanner can automatically detect a number of vulnerabilities in JWT mechanisms on your behalf. For more information, see the related issue definitions on the Target > Issued definitions tab.

Burp Suite Professional 2022.5.1开始,Burp扫描器能自动检测一定量的JWT机制漏洞。

What are JWTs?

什么是JWT? JSON web tokens (JWTs) are a standardized format for sending cryptographically signed JSON data between systems. They can theoretically contain any kind of data, but are most commonly used to send information (“claims”) about users as part of authentication, session handling, and access control mechanisms.

1
JWT是一种标准格式,用于系统间发送加密且带签名的JSON数据。它们理论上包含各种类型数据,但它们是最普遍用于发送与用户相关的授权、会话处理与访问控制机制的信息(声明)。

Unlike with classic session tokens, all of the data that a server needs is stored client-side within the JWT itself. This makes JWTs a popular choice for highly distributed websites where users need to interact seamlessly with multiple back-end servers.

1
与传统session的值不同,所有服务器需要的数据都被存储在客户端的JWT自身当中。这使JWT成为当用户需要与多个后端服务器无缝交互的高分布式架构网站的首选。

That is, JWT is stateless for the server. The server does not need to save session information related to the user identity in memory or database as in the traditional way. Each token value of JWT contains all the necessary data. When verifying, the server only needs to check whether the signature is correct and whether the token is expired. 即JWT对于服务器来说是无状态类型的,服务器不需要像传统方式在内存或数据库里保存用户身份相关的session信息,JWT的每个token值自包含所有必要的数据,服务器验证时只需要检查签名是否正确,以及token是否过期等。

JWT format

JWT格式 A JWT consists of 3 parts: a header, a payload, and a signature. These are each separated by a dot, as shown in the following example:

1
一个JWT由三部分组成:header,payload,signature。它们由.隔开,正如下面的例子:

eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA

The header and payload parts of a JWT are just base64url-encoded JSON objects. The header contains metadata about the token itself, while the payload contains the actual “claims” about the user. For example, you can decode the payload from the token above to reveal the following claims:

1
header与payload部分是base64+url编码的JSON对象。header包含JWT自身的元数据,同时payload包含用户相关的“声明”(理解为用户相关的属性信息)。例如,你可以对来自上面JWT的payload进行解码从而揭示这些声明:

{ "iss": "portswigger", "exp": 1648037164, "name": "Carlos Montoya", "sub": "carlos", "role": "blog_author", "email": "carlos@carlos-montoya.net", "iat": 1516239022 }

In most cases, this data can be easily read or modified by anyone with access to the token. Therefore, the security of any JWT-based mechanism is heavily reliant on the cryptographic signature.

1
多数情况下,这些数据很容易就能被任何拥有该token的人读取并修改它。因此,任何基于JWT机制的安全严重依赖于加密签名。

JWT signature

JWT签名 The server that issues the token typically generates the signature by hashing the header and payload. In some cases, they also encrypt the resulting hash. Either way, this process involves a secret signing key. This mechanism provides a way for servers to verify that none of the data within the token has been tampered with since it was issued:

1
发布token的服务器,通常给header与payload进行hash加密生成签名。在某些情况下,它们也加密hash后的结果。无论如何,这个过程涉及到一个签名私钥。这个机制为服务器提供一种验证token内部数据自发布以来是否被篡改的方法。

This is similar to the mechanism of using a specific hash value generated by a file to identify whether a file has been changed. 这和用文件生成的特定hash值来识别文件是否发生变更的机制有点像。

  • As the signature is directly derived from the rest of the token, changing a single byte of the header or payload results in a mismatched signature.
1
因为签名是直接由JWT其他部分而衍生来的,改变一个字节的header或payload会使其变成无法匹配的签名。
  • Without knowing the server’s secret signing key, it shouldn’t be possible to generate the correct signature for a given header or payload.
1
如果不知道服务器的签名私钥,不可能生成所给的header或payload相匹配的正确签名。

Tip:If you want to gain a better understanding of how JWTs are constructed, you can use the debugger on jwt.io to experiment with arbitrary tokens. 如果你想更好理解JWT的构成,你可以使用jwt.io中的调试器测试任何token值。

JWT vs JWS vs JWE

The JWT specification is actually very limited. It only defines a format for representing information (“claims”) as a JSON object that can be transferred between two parties. In practice, JWTs aren’t really used as a standalone entity. The JWT spec is extended by both the JSON Web Signature (JWS) and JSON Web Encryption (JWE) specifications, which define concrete ways of actually implementing JWTs.

1
JWT规范事实上非常有限。它只定义了一种用于表示信息(“声明”)的格式,作为一个能在双方之间传输的json对象。事实上,JWT不被用作为一个标准实体。JWT被JWS和JWE规范扩展,这定义了实际实现JWT的具体方式(理解为是一种接口)。

image.png

In other words, a JWT is usually either a JWS or JWE token. When people use the term “JWT”, they almost always mean a JWS token. JWEs are very similar, except that the actual contents of the token are encrypted rather than just encoded.

1
换句话说,JWT通常指的是JWS或JWE token。当人们用“JWT”专业术语,几乎总是指JWS token。JWE非常相似,只是token的实际内容是加密的,而不是仅仅编码。

Note:For simplicity, throughout these materials, “JWT” refers primarily to JWS tokens, although some of the vulnerabilities described may also apply to JWE tokens. 为了简化,在这些材料中,“JWT”主要指代 JWS 令牌,尽管描述的一些漏洞也可能适用于 JWE 令牌。

What are JWT attacks?

什么是JWT攻击? JWT attacks involve a user sending modified JWTs to the server in order to achieve a malicious goal. Typically, this goal is to bypass authentication and access controls by impersonating another user who has already been authenticated.

1
JWT攻击指用户为了实现恶意目的,发送修改的JWT到服务器。通常这个目的是绕过身份认证与访问控制,通过冒充其他已经通过身份认证的用户来实现。

What is the impact of JWT attacks?

JWT攻击的影响是什么? The impact of JWT attacks is usually severe. If an attacker is able to create their own valid tokens with arbitrary values, they may be able to escalate their own privileges or impersonate other users, taking full control of their accounts.

1
JWT攻击的影响通常很严重。如果黑客能用任意值创建他们自己的有效token,他们能够提升自身权限或冒充其他用户,完全掌控其账户。

How do vulnerabilities to JWT attacks arise?

JWT攻击漏洞是如何产生的? JWT vulnerabilities typically arise due to flawed JWT handling within the application itself. The various specifications related to JWTs are relatively flexible by design, allowing website developers to decide many implementation details for themselves. This can result in them accidentally introducing vulnerabilities even when using battle-hardened libraries.

1
JWT漏洞通常由于应用内部的JWT处理缺陷而产生。各种与JWT相关的规范在设计上来说相对灵活,允许网站开发者自己决定许多实现细节。这可能导致意外地引入漏洞,即使使用的是经过(各种漏洞)锤炼过(修复过很多次)的库。

These implementation flaws usually mean that the signature of the JWT is not verified properly. This enables an attacker to tamper with the values passed to the application via the token’s payload. Even if the signature is robustly verified, whether it can truly be trusted relies heavily on the server’s secret key remaining a secret. If this key is leaked in some way, or can be guessed or brute-forced, an attacker can generate a valid signature for any arbitrary token, compromising the entire mechanism.

1
这些实现缺陷通常意味着JWT签名没有经过合适地验证。这使黑客能够通过篡改payload的值来传递给应用。即使签名被稳固地验证,但它是否能真正被信任强烈依赖于服务器的密钥(是否)依然保密。如果它的key因为某种方式被泄露了,或者能够猜出、暴力破解,黑客就能用任意token生成一个有效签名,让整个机制瓦解。

How to work with JWTs in Burp Suite

如何在Burp中运用JWT? In case you haven’t worked with JWTs in the past, we recommend familiarizing yourself with the relevant features of Burp Suite before attempting the labs in this topic.

1
如果曾经你没使用过JWT,尝试实验室之前,我们推荐你自己先去试下相关的Burp功能。

Read more

Working with JWTs in Burp Suite

You can use Burp Inspector to view and decode JWTs. You can then use the JWT Editor extension to:

1
您可以使用 Burp Inspector 查看和解码 JWT。然后您可以使用 JWT 编辑器扩展来:
  1. Generate cryptographic signing keys.
  2. Edit the JWT.  
  3. Resign the token with a valid signature that corresponds to the edited JWT.
1
2
3
1. 生成加密签名keys
2. 编辑JWT
3. 用一个与所编辑JWT有关的有效签名重新签署token

You can follow along with the process below using our JWT authentication bypass via unverified signature lab.

Before you start

Install the JWT Editor extension. For more information, see Installing extensions from the BApp Store.

Viewing JWTs

查看JWT

  1. Identify a request with a JWT that you want to investigate further. Look for the highlighted requests in Proxy > HTTP history, these are automatically flagged by the JWT Editor extension.
1
1.识别出一个你想进一步调查的JWT请求。在Proxy > HTTP history查看高亮请求,这些已经由该拓展自动标注出来了。

image.png 2. To view the JWT contents, highlight sections of the token in turn. Notice that the content is automatically decoded in the Inspector panel.

1
2.为了查看JWT内容,转到高亮的token部分。注意到内容在Inspector中被自动解码了。

image.png 3. Review the contents of the JWT in the Inspector panel, to identify interesting information and determine any modifications that you want to make.

1
3. 在该面板中预览JWT内容,识别有趣的信息,确定任何你想对其做的更改。

Editing JWTs

编辑JWT To edit a JWT using the JWT Editor extension:
为了使用该拓展编辑JWT:

  1. Right-click the request with the JWT and select Send to Repeater.
  2. In the request panel, go to the JSON Web Token tab.
  3. Edit the JSON data as required in the Header and Payload fields.
  4. Click Sign. A new dialog opens.
  5. In the dialog, select the appropriate signing key, then click OK. The JWT is re-signed to correspond with the new values in the header and payload. If you haven’t added a signing key, follow the instructions below.
1
2
3
4
5
1. 右键JWT请求,选择发送至重放器
2. request面板中,前往JSON Web Token标签
3. 根据需要编辑header与payload区域中的JSON数据
4. 点Sign,打开一个新的窗口
5. 在窗口中,选中合适的签名key,点ok。接着JWT被和header与payload相关的新值重新签名。如果你已经添加了签名key,接着下面的步骤。

This process is actually to simulate the server to generate a specific secret key, then encrypt and re-sign the header and payload, as mentioned above: 这个过程实际上就是在模拟服务器生成特定密钥key,然后对header与payload进行加密并重新签名,如上面说的: image.png

Adding a JWT signing key

添加JWT签名密钥 To add a signing key to Burp using the JWT Editor extension:
为了使用该拓展添加签名key到Burp:

  1. Go to the JWT Editor Keys tab.
  2. Click the button for the type of key that you want to add. For example, New Symmetric Key. A new dialog opens.
  3. In the dialog, add the new key:
    • Click Generate to create a new key.
    • Alternatively, paste an existing key into the dialog.
  4. Edit the key as required.
  5. Click OK to save the key.
1
2
3
4
5
6
7
1. 前往JWT Editor Keys标签
2. 点击你想添加的key类型。例如,New Symmetric Key。然后新窗口弹出。
3. 在该窗口,添加新key:
- 点击Generate创建新key
- 或者粘贴存在的key到其中
4. 根据需要编辑key
5. 点击ok保存key

The signing key type of the JWT added here should be consistent with the type selected in the above editing step, mainly to prepare for the subsequent forgery of JWT. But please note that, looking back at the previous content, all the signing keys mentioned here must be valid, that is, they must be consistent with the key generated by the target server, mainly through Leak/Brute, etc. Otherwise, the fabricated key cannot be used. 这里添加JWT的签名密钥类型,和上面编辑步骤时选择的类型要一致,主要就是为后续伪造JWT做准备。但注意,回顾前面内容,这里提到的所有signing key,必须是有效的,即必须与目标服务器生成该key时是一致的,主要通过泄露/爆破等方式。否则,凭空捏造的key是无法利用的。

Exploiting flawed JWT signature verification

利用冒充的JWT签名认证 By design, servers don’t usually store any information about the JWTs that they issue. Instead, each token is an entirely self-contained entity. This has several advantages, but also introduces a fundamental problem - the server doesn’t actually know anything about the original contents of the token, or even what the original signature was. Therefore, if the server doesn’t verify the signature properly, there’s nothing to stop an attacker from making arbitrary changes to the rest of the token.

1
根据设计,服务器通常不存储任何JWT相关的发布信息。反而,每个token是一个完整的自包含式实体(不需要服务器存储其信息)。这有一些好处,但会引起一种根本问题 - 服务器事实上不知道任何关于该token的原本内容,甚至原来的签名也不知道。因此,如果服务器没有适当地校验签名,没有什么能够阻止黑客构造任意变更,从而对token的剩余部分造成影响。

In other words, the ability for hackers to impersonate JWT signatures is closely related to the entity characteristics of the token value in JWT and the server’s processing mechanism for JWT, which is a natural condition. But please note that portswigger’s description here is easy to cause misunderstanding. In fact, when the JWT is first generated, the server must know the content of its token. It’s just that the subsequent JWT is stateless for the server. The server will not save the source JWT after the first signature. After receiving the JWT, it needs to re-parse and verify its signature(There is no way to compare with the source token in the traditional way). Therefore, if the server is not rigorous in verification (for example, using the unsafe algorithm none, or not doing JWT identity matching, etc.), when the hacker tampers with the JWT to bypass it, it is equivalent to taking advantage of the server’s verification flaws, that is, the integrity of the JWT cannot be guaranteed (as defined in CIA). 也就是说,能够让黑客实现冒充JWT签名,和JWT中token值自身的实体特点与服务器对JWT的处理机制是脱不开关系的,是天然条件。但注意portswigger这里的描述容易让人产生误解,实际上刚开始生成JWT时,服务器肯定是知道其token内容的,只是由于后续JWT对于服务器是无状态的,服务器第一次签名之后就不会保存该源JWT,后续接收到JWT后需要重新解析和验证其签名(没办法像传统方式和源token进行比对),所以如果服务器校验时不严谨(比如使用不安全算法none,或者没有做JWT的身份匹配等),当黑客篡改JWT后实现绕过,就相当于利用了服务器的校验缺陷,即无法保证JWT的完整性(CIA中的定义)。

For example, consider a JWT containing the following claims:

1
例如,考虑一个包含下面声明的JWT:

{ "username": "carlos", "isAdmin": false }

If the server identifies the session based on this username, modifying its value might enable an attacker to impersonate other logged-in users. Similarly, if the isAdmin value is used for access control, this could provide a simple vector for privilege escalation.

1
如果服务器基于这个username做鉴别,修改该值可能使黑客冒充已登录用户。类似地,如果isAdmin值被用于权限控制,这可能为权限提升提供了简单的攻击向量(即攻击条件,这是常见的专业术语)。

In the first couple of labs, you’ll see some examples of how these vulnerabilities might look in real-world applications.

Analogy Understanding: JWT can be compared to a security check: 1. Issuing a check: When the bank (server) issues a check, it will record the amount, the payee and affix an anti-counterfeiting seal (signature). 2. Verify the check: When the payee goes to the bank to cash it, the bank does not compare the original check in the database, but checks whether the security seal is valid. 3. Vulnerability risk: If the bank does not check the security seal (signature), the attacker can modify the amount of the check at will, and the bank will accept it unconditionally. 类比理解: 可以将JWT类比为​​防伪支票​​: ​​1. 签发支票​​:银行(服务器)签发支票时,会记录金额、收款人并加盖防伪印章(签名)。 ​​2. 验证支票​​:收款人去银行兑现时,银行不会对比数据库中的原始支票,而是检查防伪印章是否有效。 ​​3. 漏洞风险​​:如果银行不检查防伪印章(签名),攻击者可以随意修改支票金额,银行会无条件接受。

Therefore, the core contradiction of the JWT vulnerability problem is that the convenience brought by statelessness vs the security of complete dependence on signature verification. If the validation logic is not perfect, the server will not be able to perceive whether the JWT has been tampered with or not, because there is no stored “truth” to compare to. Rigor of the validation phase determines the reliability of the JWT 所以,JWT漏洞问题的**​核心矛盾​在于​:无状态性带来的便利性 vs 完全依赖签名验证的安全性。若验证逻辑不完善,服务器将无法感知JWT是否被篡改,因为没有任何存储的“真相”可供比对。​​验证阶段的严格性决定了JWT的可靠性​**

Accepting arbitrary signatures

接收任意签名 JWT libraries typically provide one method for verifying tokens and another that just decodes them. For example, the Node.js library jsonwebtoken has verify() and decode().

1
JWT库通常提供一种方法来验证token,另一种方法只是将它们解码。例如,Node.js库 jsonwebtoken 有 verify() 和 decode()

Occasionally, developers confuse these two methods and only pass incoming tokens to the decode() method. This effectively means that the application doesn’t verify the signature at all.

1
开发者偶尔会混淆这两种方法,仅将传入的token传递给decode()方法。这事实上意味着应用完全不会校验签名。

【LAB1 - 】

登录给定用户,查看自己的jwt,并通过jwt.io网站做分析,发现需要公钥和私钥: image.png

image.png

【LAB2 - 】

Brute-forcing secret keys

暴力破解密钥 Some signing algorithms, such as HS256 (HMAC + SHA-256), use an arbitrary, standalone string as the secret key. Just like a password, it’s crucial that this secret can’t be easily guessed or brute-forced by an attacker. Otherwise, they may be able to create JWTs with any header and payload values they like, then use the key to re-sign the token with a valid signature.

1
一些签名算法,例如 HS256 (HMAC + SHA-256),使用任意独立的字符串作为密钥。与密码类似,密钥无法被黑客轻易猜出或暴力破解是至关重要的。否则,攻击者可能能够创建包含任意header与payload值的JWT,然后使用该密钥来重新签名包含有效签名的JWT。 

When implementing JWT applications, developers sometimes make mistakes like forgetting to change default or placeholder secrets. They may even copy and paste code snippets they find online, then forget to change a hardcoded secret that’s provided as an example. In this case, it can be trivial for an attacker to brute-force a server’s secret using a wordlist of well-known secrets.

1
在实现JWT应用时,开发者有时候会犯错误,忘记更改默认或作为占位符的密钥。他们可能甚至直接把从互联网找到的代码片段复制粘贴,却忘记替换仅作为示例的硬编码密钥。在这种情况下,攻击者利用常见的密钥字典来暴力破解服务器的密钥简直易如反掌。

Brute-forcing secret keys using hashcat

使用hashcat暴力破解密钥 We recommend using hashcat to brute-force secret keys. You can install hashcat manually, but it also comes pre-installed and ready to use on Kali Linux.

1
我们推荐使用hashcat来暴力破解密钥。你可以手动安装它,但Kali Linux已经预安装了它并能够直接使用。

If you’re using the pre-built VirtualBox image for Kali rather than the bare metal installer version, this may not have enough memory allocated to run hashcat.
若您使用的是预构建的 Kali VirtualBox 镜像而非裸机安装版本,可能分配的内存不足以运行 hashcat。

You just need a valid, signed JWT from the target server and a wordlist of well-known secrets. You can then run the following command, passing in the JWT and wordlist as arguments:

1
你只需要一个来自于目标服务器的有效且已签名的JWT,以及一份常见密钥字典。然后你运行下面的命令,把JWT和字典作为参数传递:
1
hashcat -a 0 -m 16500 <jwt> <wordlist>

Hashcat signs the header and payload from the JWT using each secret in the wordlist, then compares the resulting signature with the original one from the server. If any of the signatures match, hashcat outputs the identified secret in the following format, along with various other details:

1
Hashcat会使用每一个在字典中的密钥尝试对来自JWT的header与payload签名,然后把生成的签名与来自服务器的原始签名做比对。如果任一签名匹配上,hashcat会以如下格式输出被识别的密钥,并伴随其他各种详细信息:

<jwt>:<identified-secret>

If you run the command more than once, you need to include the --show flag to output the results.
如果多次运行该命令,需包含 --show 标志以输出结果。

As hashcat runs locally on your machine and doesn’t rely on sending requests to the server, this process is extremely quick, even when using a huge wordlist.

1
由于hashcat运行在你本机上,不依赖于向服务器发送请求,即使使用大型字典,此过程也极快。

Once you have identified the secret key, you can use it to generate a valid signature for any JWT header and payload that you like. For details on how to re-sign a modified JWT in Burp Suite, see Editing JWTs.

1
一旦识别出密钥,就可以使用它为任意自定义的JWT header与payload生成有效签名。关于如何在Burp为修改后的JWT重新签名,请查看...

If the server uses an extremely weak secret, it may even be possible to brute-force this character-by-character rather than using a wordlist.

1
若服务器采用极其简单的密钥,甚至可能逐字符暴力破解,而无需借助字典攻击。

【LAB3 - 】

HTTP Host header attacks

In this section, we’ll discuss how misconfigurations and flawed business logic can expose websites to a variety of attacks via the HTTP Host header. We’ll outline the high-level methodology for identifying websites that are vulnerable to HTTP Host header attacks and demonstrate how you can exploit this for the following kinds of attacks:

1
在这部分,我们将讨论误配置与缺陷业务逻辑如何通过HTTP Host头将网站暴露在各种攻击面下。我们将概述识别易受 HTTP Host 标头攻击的网站的高级方法,并演示如何利用它进行以下类型的攻击:
1
如果您已经熟悉 HTTP Host 标头漏洞背后的基本概念,并且只想在一些真实的、故意存在漏洞的目标上练习利用它们,您可以从下面的链接访问本主题中的所有实验。

What is the HTTP Host header?

The HTTP Host header is a mandatory request header as of HTTP/1.1. It specifies the domain name that the client wants to access. For example, when a user visits https://portswigger.net/web-security, their browser will compose a request containing a Host header as follows:

1
HTTP HOST头是HTTP/1.1.(标准)必须包含的请求头。它详细指出客户端想要访问的域名。例如,当一个用户访问https://portswigger.net/web-security,他们的浏览器将创建一个包含如下Host头的请求:

GET /web-security HTTP/1.1 Host: portswigger.net

In some cases, such as when the request has been forwarded by an intermediary system, the Host value may be altered before it reaches the intended back-end component. We will discuss this scenario in more detail below.

1
在一些情况下,例如当请求已经被一个中间人系统转发,这个Host值在到达预期的后端组件前可能被更改。我们将在下面更详细地讨论这种情况。

What is the purpose of the HTTP Host header?

The purpose of the HTTP Host header is to help identify which back-end component the client wants to communicate with. If requests didn’t contain Host headers, or if the Host header was malformed in some way, this could lead to issues when routing incoming requests to the intended application.

1
HTTP Host头的目的在于帮助识别客户端想要与哪个后端组件进行通信。如果请求不包含Host头,或者如果Host头通过某些方式导致格式不正确,这可能会导致在将传入请求路由到预期应用程序时出现问题。

Historically, this ambiguity didn’t exist because each IP address would only host content for a single domain. Nowadays, largely due to the ever-growing trend for cloud-based solutions and outsourcing much of the related architecture, it is common for multiple websites and applications to be accessible at the same IP address. This approach has also increased in popularity partly as a result of IPv4 address exhaustion.

1
历史上来说,这种模糊性不存在,因为每个IP地址只会为一个域名托管内容。今天,由于基于云的解决方案和外包相关架构的日益增长的趋势,使用相同IP地址来访问多网站和应用是常见的。这种方法日益流行,部分原因也是由于IPv4地址耗尽。

When multiple applications are accessible via the same IP address, this is most commonly a result of one of the following scenarios.

1
当通过相同IP地址访问多个应用,最常见的是以下场景之一导致的结果。

Virtual hosting

One possible scenario is when a single web server hosts multiple websites or applications. This could be multiple websites with a single owner, but it is also possible for websites with different owners to be hosted on a single, shared platform. This is less common than it used to be, but still occurs with some cloud-based SaaS solutions.

1
一个可能的场景是,当单一web服务器托管多个网站或应用。这可能是单一所有者拥有的多个网站,但也可能是不同所有者的网站托管在同一个共享平台上。相比过去这虽然并不常见,但仍然出现在一些基于云的SaaS解决方案。

In either case, although each of these distinct websites will have a different domain name, they all share a common IP address with the server. Websites hosted in this way on a single server are known as “virtual hosts”.

1
无论那种情况,即使每个不同的网站有不同的域名,他们都与服务器共享一个常见的IP地址。网站以这种方式托管在单独的服务器中,这被称为“虚拟主机”。

To a normal user accessing the website, a virtual host is often indistinguishable from a website being hosted on its own dedicated server.

1
对于一个正常用户访问网站来说,虚拟主机通常与托管在独立专用服务器上的网站难以区分。

Routing traffic via an intermediary

Another common scenario is when websites are hosted on distinct back-end servers, but all traffic between the client and servers is routed through an intermediary system. This could be a simple load balancer or a reverse proxy server of some kind. This setup is especially prevalent in cases where clients access the website via a content delivery network (CDN).

1
另一个常见的情况就是当网站被托管在不同后端服务器上时,客户端与服务器之间的所有流量通过一个中间系统来路由。这可能是一种简单的负载均衡器或某种反向代理服务器。在客户端通过内容分发网络(CDN)来访问网站时,这种配置尤为常见。

In this case, even though the websites are hosted on separate back-end servers, all of their domain names resolve to a single IP address of the intermediary component. This presents some of the same challenges as virtual hosting because the reverse proxy or load balancer needs to know the appropriate back-end to which it should route each request.

1
在这种情况下,即使网站被托管在分开的后端服务器,他们所有的域名都会被中间组件解析为一个单独IP地址。这带来了一些与虚拟主机相同的挑战,因为反向代理或负载均衡器需要知道它应该把每个请求路由到哪个合适的后端。

How does the HTTP Host header solve this problem?

In both of these scenarios, the Host header is relied on to specify the intended recipient. A common analogy is the process of sending a letter to somebody who lives in an apartment building. The entire building has the same street address, but behind this street address there are many different apartments that each need to receive the correct mail somehow. One solution to this problem is simply to include the apartment number or the recipient’s name in the address. In the case of HTTP messages, the Host header serves a similar purpose.

1
在以上两种情况下,Host头被用于指向预期接收者。一个常见的类比是向住在公寓楼里的人发送信件的过程,整栋公寓楼有相同的街道地址,但在街道地址背后有许多不同的公寓,每间公寓都需要以某种方式收到正确的邮件。一种解决这个问题的简单办法是在地址中包含公寓号或接收人名字。对于HTTP消息而言,Host头起到了类似的作用。

When a browser sends the request, the target URL will resolve to the IP address of a particular server. When this server receives the request, it refers to the Host header to determine the intended back-end and forwards the request accordingly.

1
当一个浏览器发送请求,目标URL会解析为一个专用服务器的IP地址。当这个服务器接收到请求,它会参考Host头来确定预期的后端,并相应地转发请求。

What is an HTTP Host header attack?

HTTP Host header attacks exploit vulnerable websites that handle the value of the Host header in an unsafe way. If the server implicitly trusts the Host header, and fails to validate or escape it properly, an attacker may be able to use this input to inject harmful payloads that manipulate server-side behavior. Attacks that involve injecting a payload directly into the Host header are often known as “Host header injection” attacks.

1
HTTP头攻击利用了以不安全方式来处理值的脆弱网站。如果服务器隐式信任Host头,并且未能正确验证或转义它,一个攻击者就可能注入有害的payloads到Host头来操作服务端的行为。这种涉及将有效负载直接注入到Host头中的攻击通常被称为“Host header注入”攻击。

Off-the-shelf web applications typically don’t know what domain they are deployed on unless it is manually specified in a configuration file during setup. When they need to know the current domain, for example, to generate an absolute URL included in an email, they may resort to retrieving the domain from the Host header:

1
现成的web应用通常不知道他们被部署在什么域名下,除非安装时在配置文件中手动指定它。当他们需要知道当前域名时,比如生成包含在电子邮件中的绝对URL,他们可能会求助于从Host头中检索域名。

<a href="https://_SERVER['HOST']/support">Contact support</a>

The header value may also be used in a variety of interactions between different systems of the website’s infrastructure.

1
该头部值还可能用于网站基础设施中不同系统间的多种交互场景。

As the Host header is in fact user controllable, this practice can lead to a number of issues. If the input is not properly escaped or validated, the Host header is a potential vector for exploiting a range of other vulnerabilities, most notably:

1
因为这个Host头实际上是用户可控的,这种实践会导致大量问题。如果输入没有经过正确的转义或校验,Host头是其他多种漏洞潜在的攻击途径。尤其是:
  • Web cache poisoning
  • Business logic flaws in specific functionality
  • Routing-based SSRF
  • Classic server-side vulnerabilities, such as SQL injection
1
2
3
4
Web缓存投毒
特定功能的业务逻辑缺陷
基于SSRF的路由
传统服务端漏洞,例如SQL注入

How do HTTP Host header vulnerabilities arise?

HTTP Host header vulnerabilities typically arise due to the flawed assumption that the header is not user controllable. This creates implicit trust in the Host header and results in inadequate validation or escaping of its value, even though an attacker can easily modify this using tools like Burp Proxy.

1
HTTP Host头部的漏洞通常是由于存在一个错误的假设,即该头部不是用户可控的。(即想当然地认为头部是不可控的)。这会在 Host 头部创建隐式信任,并导致对其值的验证或转义不足,即使一名攻击者能使用像Burp Proxy这样的工具来轻易篡改它。(所以说本质上这种漏洞是一个“信任问题”)

Even if the Host header itself is handled more securely, depending on the configuration of the servers that deal with incoming requests, the Host can potentially be overridden by injecting other headers. Sometimes website owners are unaware that these headers are supported by default and, as a result, they may not be treated with the same level of scrutiny.

1
即使 Host 头部本身处理得更安全,根据处理传入请求的服务器的配置,通过注入其他头部仍可能覆盖 Host 值。有时网站所有者并未意识到这些头部默认被支持,因此可能未以同等严格程度对待。

In fact, many of these vulnerabilities arise not because of insecure coding but because of insecure configuration of one or more components in the related infrastructure. These configuration issues can occur because websites integrate third-party technologies into their architecture without necessarily understanding the configuration options and their security implications.

1
事实上,许多这样的漏洞能产生并不是由于不安全的代码,而是因为在网站基础设施中,一个或多个相关组件的不安全配置。这些配置问题的产生是因为网站将第三方技术结合到自身架构中,却没有理解清楚(这些第三方技术中的)配置选项和可能造成的安全影响。

Exploiting HTTP Host header vulnerabilities

By now, you should have a good understanding of what the HTTP Host header is. For pentesters and bug bounty hunters, we’ve created some additional guidance on how you can identify and exploit these kinds of vulnerabilities for yourself. We’ve also provided some deliberately vulnerable LABS so that you can practice some of these techniques.

1
至此,您应该对 HTTP Host 头部有了充分理解。针对渗透测试人员和漏洞赏金猎人,我们额外提供了一些指南,帮助您自行识别并利用此类漏洞。同时,我们还设置了一些刻意存在漏洞的实验环境(LABS),供您练习相关技术。

Testing for vulnerabilities

How to identify and exploit HTTP Host header vulnerabilities

In this section, we’ll look more closely at how you can identify whether a website is vulnerable to HTTP Host header attacks. We’ll then provide examples of how you can exploit this, along with several interactive labs that you can use to practice these exploits on a deliberately vulnerable website.

How to test for vulnerabilities using the HTTP Host header

To test whether a website is vulnerable to attack via the HTTP Host header, you will need an intercepting proxy, such as Burp Proxy, and manual testing tools like Burp Repeater and Burp Intruder.

In short, you need to identify whether you are able to modify the Host header and still reach the target application with your request. If so, you can use this header to probe the application and observe what effect this has on the response.

Supply an arbitrary Host header

When probing for Host header injection vulnerabilities, the first step is to test what happens when you supply an arbitrary, unrecognized domain name via the Host header.

Some intercepting proxies derive the target IP address from the Host header directly, which makes this kind of testing all but impossible; any changes you made to the header would just cause the request to be sent to a completely different IP address. However, Burp Suite accurately maintains the separation between the Host header and the target IP address. This separation allows you to supply any arbitrary or malformed Host header that you want, while still making sure that the request is sent to the intended target.

How to prevent HTTP Host header attacks

To prevent HTTP Host header attacks, the simplest approach is to avoid using the Host header altogether in server-side code. Double-check whether each URL really needs to be absolute. You will often find that you can just use a relative URL instead. This simple change can help you prevent web cache poisoning vulnerabilities in particular.

Other ways to prevent HTTP Host header attacks include:

Protect absolute URLs

When you have to use absolute URLs, you should require the current domain to be manually specified in a configuration file and refer to this value instead of the Host header. This approach would eliminate the threat of password reset poisoning, for example.

Validate the Host header

If you must use the Host header, make sure you validate it properly. This should involve checking it against a whitelist of permitted domains and rejecting or redirecting any requests for unrecognized hosts. You should consult the documentation of your framework for guidance on how to do this. For example, the Django framework provides the ALLOWED_HOSTS option in the settings file. This approach will reduce your exposure to Host header injection attacks.

Don’t support Host override headers

It is also important to check that you do not support additional headers that may be used to construct these attacks, in particular X-Forwarded-Host. Remember that these may be supported by default.

Whitelist permitted domains

To prevent routing-based attacks on internal infrastructure, you should configure your load balancer or any reverse proxies to forward requests only to a whitelist of permitted domains.

Be careful with internal-only virtual hosts

When using virtual hosting, you should avoid hosting internal-only websites and applications on the same server as public-facing content. Otherwise, attackers may be able to access internal domains via Host header manipulation.