这里考虑两种思路:1、爆破密钥,显然难度较大;2、尝试将加密算法置空,也就是 alg=none
同样,将 JWT 值发到 Decoder 模块,先 Base64 解码,将 HS256 替换为 none,user 替换为 admin 后,再 Base64 编码。
但需要注意的是,使用此方法要先将 Signature 部分删除掉,因为加密算法为 none 必须将签名置空,并且需要将 Header 和 Claims 分别处理后再用 . 号连接,因为实测直接一起处理是不行的。
最终的格式为:Header.Claims.(注意最后面还有一个 . 号)
重新访问 /admin,带上 admin 用户的 JWT 值,得到 Flag。
上述方法略为复杂,更方便的当然是使用工具,比如 jwt_tool、Burp 插件 JSON Web Tokens 等。
使用插件 JSON Web Tokens,将 HS256 替换为 none,user 替换为 admin,并删除 Signature 部分,重新发包即可。
jwt_tool 常用命令如下:
使用None算法
python3 jwt_tool.py JWT_HERE -X a
自定义修改生成
python3 jwt_tool.py JWT_HERE -T
使用字典破解
python3 jwt_tool.py JWT_HERE -C -d dictionary.txt
指定密码测试
python3 jwt_tool.py JWT_HERE -C -p password_here
需要注意的是,jwt_tool 最好是在 Linux 上运行,我使用的 Kali 运行,并且需要先导入几个包,命令如下:
python3 -m pip install termcolor cprint pycryptodomex requests
然后启动 jwt_tool,使用 -T 自定义修改模式,根据提示将 HS256 替换为 none,user 替换为 admin,最后会自动生成对应 JWT 值。
复制生成 JWT 值并删除 Signature 部分,重新发包即可获取 Flag。
2、暴力破解密钥
以 CTFShow - Web347 为例,同样访问 /admin 得到的是 user 的 JWT 值,尝试空加密算法无果。
由于加密算法为 HS256 对称加密,比较容易爆破密钥,所以考虑使用 jwt_tool 爆破密钥,最终得知密钥为 123456。
python jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e