docs/src/nice-article/weixin/jwtjsonwebtokengjmxj.md
星球一位球友问:面试的时候遇到一个问题,如果有人通过抓包获取jwt,应该如何应对?
本来想亲自写一篇,但刚好在货拉拉技术公众号上看到了这篇帖子,写得竟然很详细,于是就直接收录了进来,简单进行了一些细节调整,大家可以好好看一下,干货啊
JSON Web Token (JWT) 是一种紧凑的、基于 JSON 的开放标准 (RFC 7519),常用于不同主体(客户端和服务器)之间安全地传递信息。JWT 通常由三部分组成:
{"alg": "HS256", "typ": "JWT"}一个示例的 JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT 被广泛用于身份认证,授权场景。服务端验证 JWT 时,可以通过解密签名来判断消息是否被篡改。
技术要点:
示例:
原始 Header:
{"alg": "HS256","typ": "JWT"}
攻击后被篡改为:
{"alg": "none","typ": "JWT"}
此时 JWT 将不再进行签名验证,攻击者可以伪造任意 Payload。例如:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VySWQiOiIxMjMifQ.
解决方案:
payload = jwt.decode(token, self.secret, algorithms=["HS256", "HS512"])
userId = payload['userId']
username = self.db_lookup(userId, "username")
技术要点:
示例: 如果密钥过于简单,攻击者可以使用工具如 jwtcrack 破解签名:
jwtcrack your_jwt_token
破解后,攻击者可以使用这个密钥生成伪造的 JWT。
解决方案:
payload = jwt.decode(token, self.secret, algorithms="RS256")
技术要点:
示例: 假设攻击者捕获了一个合法的 JWT,在其有效期内不断重放该请求以执行未授权操作。
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
解决方案:
lifetime = datetime.datetime.now() + datetime.timedelta(minutes=5)
payload = {
'username' : username,
'admin' : 0,
'exp' : lifetime
}
access_token = jwt.encode(payload, self.secret, algorithm="HS256")
技术要点:
如果 JWT 在不安全的传输渠道中传递,如使用 HTTP 而非 HTTPS,攻击者可以通过中间人攻击拦截并获取 JWT。
解决方案:
JSON Web Signature (JWS) RFC 中定义的 Header 参数,最基本的 JWT header 是以下 JSON。
{
"typ": "JWT",
"alg": "HS256"
}
其他在 RFC 中注册的 Header 参数包括:jwk、jku、kid 等:
jwk(JSON Web Key):提供一个代表密钥的嵌入式 JSON 对象jku(JSON Web Key Set URL):提供一个 URL,服务器可以从这个 URL 获取一组包含正确密钥的密钥kid(Key ID):提供一个 ID,在有多个密钥可供选择的情况下服务器可以用它来识别正确的密钥,根据键的格式这可能有一个匹配的 kid 参数这些用户可控制的 Header 参数每个都告诉服务端在验证签名时应该使用哪个密钥,如果服务端配置存在缺陷,通过这些参数的注入可伪造合法的自签名 JWT。
通过 jwk 参数注入自签名 JWT:
示例:
{
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
}
}
技术要点:
理想情况下,服务端应仅使用有限的公钥白名单来验证 JWT 签名。但是,配置错误的服务端有时会使用 jwk 参数中嵌入的任何密钥。使用自己的 RSA 私钥对修改后的 JWT 进行签名,然后在 jwk 中嵌入匹配的公钥,服务端会使用 jwk 中嵌入的公钥验证 JWT 签名,导致伪造的自签名 JWT 通过验证。
解决方案:
服务端正确配置公钥白名单验证 JWT 签名
通过 jku 参数注入自签名 JWT
示例:
{"typ":"JWT","alg":"RS256", "jku":"https://hacker.com/jwks.json", "kid":"id_of_jwks"}.
{"login":"admin"}.
[Signed with new Private key; Public key exported]
技术要点:
与 jwk 不同的是,jku 参数是指向 jwk 集合文件的 URL。攻击者将 jku URL 替换为包含恶意公钥的 URL,再用配对的私钥对伪造的 Token 签名,服务端获取恶意公钥并验证伪造的 Token 为合法。
解决方案:
服务端使用白名单验证 jku 参数值,仅允许指定来源的 URL
通过 kid 参数注入自签名 JWT
示例:
{
"kid": "../../path/to/file",
"typ": "JWT",
"alg": "HS256",
"k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}
技术要点:
服务端可能使用多个密钥对不同种类的数据签名,因此 JWT 的 Header 参数可能包含 kid(Key ID)参数,让服务端在验证签名时确定使用哪个密钥,验证的密钥通常存储为一个 JWK 集合,在这种情况下服务端可能简单地查找与 Token 具有相同 kid 的 JWK,然而 JWS 规范没有为 kid 定义具体的结构——它只是开发人员选择的任意字符串,例如:它们可能使用 kid 参数指向数据库中的特定条目,甚至是文件的名称,如果这个参数也存在目录遍历漏洞,则攻击者可能会强制服务端使用其文件系统中的任意文件作为验证密钥,例如 ../../../../../../../dev/null,由于这是一个空文件,读取它会返回一个空字符串。因此,使用空字符串对 Token 进行签名将得到能通过服务端验证的合法签名。
解决方案:
服务端使用白名单验证 kid 参数值。
技术要点:
JWT 的 Payload 是 Base64 编码,而非加密,因此内容可以被轻易解析。如果在 Payload 中包含敏感信息(如用户的身份、邮箱等),可能会造成信息泄露。
示例:
{"SSN": "123-45-6789","email": "[email protected]","role": "admin"}
攻击者可以轻易解码 Base64 部分,得到这些敏感数据。
解决方案:
payload = jwt.decode(token, self.secret, algorithms="HS256")
userId = payload['userId']
password = self.db_lookup(userId, "password")
技术要点:
在某些场景中,如果不同身份类型的 JWT(如管理员和普通用户的 Token)没有严格区分,可能导致权限提升等问题。
示例: 某服务允许用户使用普通用户的 JWT 访问管理员接口,攻击者可以利用此漏洞提升权限:
POST /admin/manage/add HTTP/2
Authorization: Bearer user_token_with_low_permissions
解决方案:
技术要点:
在多服务场景中,如果未指定 audience 限制 Token 仅能访问指定的应用程序,可能导致 A 应用程序的 Token 能在 B 应用程序中合法使用,可能导致权限提升。
示例: A 服务允许用户使用 B 服务生成的 JWT 访问,攻击者可以利用此漏洞扩展访问权限:
Host:appA
Authorization: Bearer user_token_made_by_appB
解决方案:
payload = jwt.decode(token, self.secret, audience=["appB"], algorithms="HS256")
技术要点:
攻击者可能试图构造恶意的 JWT,以绕过权限检查或注入恶意数据,造成越权操作。
示例: 攻击者构造如下 Payload,试图绕过权限检查:
{"userId": "123","role": "admin"}
{"userId": "123","username": "admin' or 1=1#","password": "null"}
如果服务端没有严格验证 Token 的合法性,攻击者可能获得管理员权限。
解决方案:
针对 JWT 的完整测试流程
https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
开始:
简单的检查:
测试已知漏洞:
测试其他漏洞:
额外检查:
更进一步:
JWT.io
JWT Tool
jwtcrack
CyberChef
JWS 库
Burp Suite 插件
参考链接:https://mp.weixin.qq.com/s/O8Er8UmlFrER2LAkdcXCjA,整理:沉默王二