免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任
目录
一:JWT原理
JWT(JSON Web Token)是一种用于在网络应用间安全传递信息的开放标准(RFC 7519)。它通常用于身份验证和信息交换,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。尽管JWT设计上是安全的,但在实际应用中,如果配置不当或实现有误,可能会导致安全漏洞。以下是一些常见的JWT漏洞及其介绍:
签名是为了验证消息在传递过程中没有被篡改。它是通过将头部和载荷部分的内容,使用头部中指定的签名算法,再结合一个密钥(secret key)来生成的。
例如,如果头部的算法是 HS256,密钥是一个保密的字符串,那么签名就是通过将 Base64Url 编码后的头部和载荷以及密钥,按照 HS256 算法进行计算得到的。这个签名是 JWT 的第三部分,它确保了 JWT 的完整性和真实性。
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间安全地传递信息。它通常用于身份验证和信息交换,具有紧凑、自包含和可验证的特点。JWT的工作原理可以分为三个主要部分:结构、生成和验证。
1. JWT的结构
JWT由三部分组成,用点(.
)分隔:
-
Header(头部)
-
Payload(载荷)
-
Signature(签名)
格式如下:
Header.Payload.Signature
(1)Header(头部)
头部通常包含两部分信息:
-
算法(alg):用于生成签名的算法,如HMAC SHA256(HS256)或RSA SHA256(RS256)。
-
类型(typ):令牌类型,通常是
JWT
。
示例:
{ "alg": "HS256", "typ": "JWT" }
头部经过Base64Url编码后形成JWT的第一部分。
(2)Payload(载荷)
载荷包含需要传递的声明(claims)。声明分为三类:
-
注册声明(Registered Claims):预定义的声明,如:
-
iss
(Issuer):签发者。 -
sub
(Subject):主题。 -
aud
(Audience):接收者。 -
exp
(Expiration Time):过期时间。 -
nbf
(Not Before):生效时间。 -
iat
(Issued At):签发时间。
-
-
公共声明(Public Claims):可以自定义的声明,但为了避免冲突,应使用IANA注册的声明名称。
-
私有声明(Private Claims):自定义的声明,用于在双方之间传递信息。
示例:
{ "sub": "1234567890", "name": "John Doe", "admin": true, "iat": 1516239022 }
载荷经过Base64Url编码后形成JWT的第二部分。
(3)Signature(签名)
签名用于验证JWT的真实性和完整性。签名的生成方式如下:
-
将编码后的头部和载荷用点(
.
)连接起来。 -
使用头部中指定的算法(如HS256)和密钥对连接后的字符串进行签名。
示例(使用HMAC SHA256算法):
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
签名经过Base64Url编码后形成JWT的第三部分。
2. JWT的生成
JWT的生成过程如下:
-
定义头部和载荷。
-
将头部和载荷分别进行Base64Url编码。
-
使用指定的算法和密钥对编码后的头部和载荷进行签名。
-
将编码后的头部、载荷和签名用点(
.
)连接起来,形成最终的JWT。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
3. JWT的验证
JWT的验证过程如下:
-
解码头部和载荷:将JWT的头部和载荷部分解码,获取原始信息。
-
验证签名:
-
使用头部中指定的算法和密钥对头部和载荷重新生成签名。
-
将生成的签名与JWT中的签名部分进行比较,确保一致。
-
-
验证声明:
-
检查
exp
(过期时间)和nbf
(生效时间)是否有效。 -
检查
iss
(签发者)和aud
(接收者)是否符合预期。 -
检查其他自定义声明是否满足业务需求。
-
如果签名验证通过且声明有效,则JWT被认为是合法的。
4. JWT的工作流程
JWT通常用于身份验证和信息交换,其典型工作流程如下:
-
用户登录:
-
用户提供凭据(如用户名和密码)。
-
服务器验证凭据,生成JWT并返回给客户端。
-
-
客户端存储JWT:
-
客户端将JWT存储在本地(如LocalStorage、Cookie或内存中)。
-
-
客户端发送JWT:
-
客户端在后续请求中将JWT放在
Authorization
头中发送给服务器。 -
示例:
Authorization: Bearer <JWT>
-
-
服务器验证JWT:
-
服务器接收到JWT后,验证其签名和声明。
-
如果验证通过,服务器处理请求并返回响应。
-
5. JWT的优点
-
无状态:JWT是自包含的,服务器无需存储会话信息。
-
跨域支持:JWT可以轻松用于跨域场景。
-
灵活性:可以在JWT中存储任意信息,适用于多种场景。
-
安全性:通过签名和加密机制,确保信息的完整性和保密性。
6. JWT的缺点
-
无法撤销:一旦签发,JWT在有效期内无法被撤销(除非使用黑名单机制)。
-
信息泄露风险:如果未加密,JWT的载荷可以被解码,泄露敏感信息。
-
存储问题:JWT存储在客户端,可能被XSS攻击窃取。
二.JWT漏洞攻防
1. 弱签名算法(案例三)
-
问题描述:JWT支持多种签名算法,如HMAC、RSA、ECDSA等。如果使用弱签名算法(如
none
算法),攻击者可以篡改JWT内容而不被检测到。 -
漏洞利用:攻击者可以将JWT的签名算法改为
none
,并删除签名部分,从而绕过验证。 -
防御措施:确保使用强签名算法(如HS256、RS256),并在验证JWT时明确拒绝
none
算法。
2. 弱密钥(案例二)
-
示例: 使用
HS256
(HMAC SHA-256)以外的弱算法,如HS1
或none
(无签名)。 -
问题: 弱加密算法容易被破解,尤其是
none
算法,它根本不进行签名验证,攻击者可以轻松篡改JWT
3. 未验证签名(案例一)
-
问题描述:某些应用在接收到JWT后,未验证其签名或验证不严格,导致攻击者可以篡改JWT内容。
-
漏洞利用:攻击者可以修改JWT的载荷部分(如用户ID、角色等),提升权限或冒充其他用户。
-
防御措施:在接收到JWT后,必须严格验证其签名,确保其未被篡改。
4. 信息泄露
-
问题描述:JWT的载荷部分通常包含用户信息,如果未加密,攻击者可以解码JWT并获取敏感信息。
-
漏洞利用:攻击者可以解码JWT,获取用户的身份信息、权限等。
-
防御措施:对于敏感信息,建议使用JWE(JSON Web Encryption)对JWT进行加密,或避免在JWT中存储敏感信息。
5. 重放攻击
-
问题描述:如果JWT没有设置有效期或有效期过长,攻击者可以捕获并重复使用旧的JWT进行身份验证。
-
漏洞利用:攻击者捕获有效的JWT,并在其过期前重复使用。
-
防御措施:为JWT设置合理的有效期(
exp
字段),并使用一次性令牌或会话管理机制防止重放攻击。
6. 跨服务攻击
-
问题描述:如果多个服务使用相同的JWT密钥,攻击者在一个服务上获取的JWT可以在其他服务上使用。
-
漏洞利用:攻击者在一个服务上获取JWT后,可以在其他服务上冒充用户。
-
防御措施:为不同的服务使用不同的JWT密钥,或使用服务特定的声明(如
aud
字段)来限制JWT的使用范围。
7. 密钥混淆攻击
-
问题描述:如果应用支持多种签名算法(如HS256和RS256),攻击者可能通过混淆算法来绕过验证。
-
漏洞利用:攻击者将JWT的签名算法从RS256改为HS256,并使用公钥作为HMAC密钥来伪造签名。
-
防御措施:在验证JWT时,确保使用预期的签名算法,并避免支持多种算法。
8. 未设置exp
或nbf
-
问题描述:如果JWT未设置过期时间(
exp
)或生效时间(nbf
),攻击者可以长期使用该JWT。 -
漏洞利用:攻击者可以无限期使用未过期的JWT。
-
防御措施:为JWT设置合理的
exp
和nbf
字段,确保其在一定时间内有效。
9. JWT注入
-
问题描述:如果应用在处理JWT时未进行严格的输入验证,攻击者可能通过注入恶意内容来破坏应用逻辑。
-
漏洞利用:攻击者在JWT中注入恶意数据,导致应用行为异常。
-
防御措施:在处理JWT时,进行严格的输入验证和过滤,确保其内容符合预期。
10. JWT存储不当
-
问题描述:如果JWT存储在客户端不安全的位置(如LocalStorage),攻击者可能通过XSS攻击窃取JWT。
-
漏洞利用:攻击者通过XSS漏洞获取JWT,并冒充用户。
-
防御措施:将JWT存储在安全的HttpOnly Cookie中,并启用Secure和SameSite属性,防止XSS攻击。
案例一:CTFhub题目---无签名
打开发现提示只有管理员可以获取flag
所以我们可以利用kali虚拟机中的jwt_tool(安装方法至于后文)
encoded=jwt.encode({"username":"admin","password":"admin","role":"admin"},'',algorithm='none')
Encoded
来修改token
然后将新token粘贴后就可以得到pyload,替换原有token就可以
或使用拼接法
案例二:CTFhub--弱秘钥
根据题目信息我们采用爆破秘钥获取flag
我们需要获取秘钥,通过jwtcrack获取到秘钥(c-jwt-crack安装方法在后文!!)
通过下面网站获取新的token
可到flag
案例三:CTFhub--修改签名算法
点开页面发现源代码和公钥
利用bp抓包对其token解密
发现其加密算法为非对称加密算法
我们根据题目提示“有些JWT库支持多种密码算法进行签名、验签。若目标使用非对称密码算法时,有时攻击者可以获取到公钥,此时可通过修改JWT头部的签名算法,将非对称密码算法改为对称密码算法,从而达到攻击者目的”得知可以通过公钥修改签名算法,但如何修改呢?我们审计源代码,从源代码得知如果想输出flag就的为get请求且token正确,role字段为admin。在源代码中有
JWTHelper::decode($_COOKIE['token'], $PUBLIC_KEY) != false
我们发现在 JWTHelper类中,decode()、encode()默认的加密解密方式都为“HS256”,所以我们可以这样修改其签名算法。首先利用公钥对token解码,然后修改role为admin,将公钥放置于token后在利用HS256对其加密
通过脚本实现(与公钥放于同一目录下运行)
# coding=GBK
import hmac
import hashlib
import base64
file = open('publickey.pem') #需要将文中的publickey下载 与脚本同目录
key = file.read()
# Paste your header and payload here
header = '{"typ": "JWT", "alg": "HS256"}'
payload = '{"username": "admin", "role": "admin"}'
# Creating encoded header
encodeHBytes = base64.urlsafe_b64encode(header.encode("utf-8"))
encodeHeader = str(encodeHBytes, "utf-8").rstrip("=")
# Creating encoded payload
encodePBytes = base64.urlsafe_b64encode(payload.encode("utf-8"))
encodePayload = str(encodePBytes, "utf-8").rstrip("=")
# Concatenating header and payload
token = (encodeHeader + "." + encodePayload)
# Creating signature
sig = base64.urlsafe_b64encode(hmac.new(bytes(key, "UTF-8"), token.encode("utf-8"), hashlib.sha256).digest()).decode("UTF-8").rstrip("=")
print(token + "." + sig)
利用脚本运行后替换原有token
修改成功
成功找到flag
一.jwt_tool安装
下载
git clone https://github.com/ticarpi/jwt_tool
安装 pycryptodomex
库的命令
pip install pycryptodomex
cd到安装目录
启动
python3 jwt_tool.py
二.c-jwt-cracker安装
下载安装包放到kali中
GitHub - brendan-rius/c-jwt-cracker: JWT brute force cracker written in C
解压安装包
unzip c-jwt-cracker-master.zip
安装gcc编译器
sudo apt install gcc
安装make
sudo apt install make
启动成功
总结
JWT(JSON Web Token)是一种用于安全传输信息的开放标准,通常用于身份验证和授权。它将用户信息编码为JSON格式,并通过签名确保数据的完整性和安全性。JWT由三部分组成:头部、载荷和签名。头部包含算法信息,载荷存储用户数据,签名用于验证令牌的真实性。JWT的优点包括无状态、跨域支持和易于扩展,广泛应用于Web应用和API中。然而,开发者需注意其安全性,避免敏感信息泄露和令牌劫持,本文案例有限,还需经过各种靶场和实战才能真正掌握JWT。
(需要源代码联系博主免费领取!!还希望多多关注点赞支持,你的支持就是我的最大动力!!!)