
JWT概述
JWT的全称是JSON Web Token。遵循JSON格式,跨域认证解决方案。声明被存储在客户端,而不是服务端内存中。服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。基于token的身份验证可以替代传统的cookie+session身份验证方法。
传统认证
Cookie
1 | HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。 |
摘录来自: 上野宣、于均良. “图解HTTP”。
JWT组成
JWT由三部分组成:header、payload、signature
header
header部分最常用的两个字段是alg和typ,alg指定了token加密使用的算法(最常用的为HMAC和RSA算法),typ声明类型为JWT
header类似如下:
1 | { |
payload
payload则为用户数据以及一些元数据有关的声明,用以声明权限,举个例子,一次登录的过程可能会传递以下数据:
1 | { |
signature
signature的功能是保护token完整性;生成方式是将header和payload两个部分链接,然后通过header部分指定的算法,计算签名。
抽象成公式就是
signature = HMAC-SHA256(base64urlEncode(header) + '.' + base64urlEncode(payload), secret_key
注意:编码header和payload时使用的编码方式为base64urlencode,base64url编码是base64的修改版,为了方便在网络中传输使用了不同的编码表,它不会在末尾填充”=”号,并将标准Base64中的”+”和”/“分别改成了”-“和”-“。
JWT安全
一个完整的jwt格式为(header.payload.signature),其中header、payload使用base64url编码,signature通过指定算法生成。
加密算法
空加密算法
JWT支持使用空加密算法,可以在header中指定alg为None
这样的话,只要把signature设置为空(即不添加signature字段),提交到服务器,任何token都可以通过服务器的验证。如下:
1 | { |
生成的完整token为ew0KCSJhbGciIDogIk5vbmUiLA0KCSJ0eXAiIDogImp3dCINCn0.ew0KCSJ1c2VyIiA6ICJBZG1pbiINCn0
(header+’.’+payload,去掉了’.’+signature字段)
空加密算法的设计初衷是用于调试的,在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。攻击者只需要把alg字段设置为None,就可以在payload中构造身份信息,伪造用户身份。
RSA改为HMAC
JWT中最常用的两种算法为HMAC和RSA。
HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,它是一种对称加密算法,使用相同的密钥对传输信息进行加解密。
RSA则是一种非对称加密算法,使用私钥加密明文,公钥解密密文。
在HMAC和RSA算法中,都是使用私钥对signature字段进行签名,只有拿到了加密时使用的私钥,才有可能伪造token。
现在我们假设有这样一种情况,一个Web应用,在JWT传输过程中使用RSA算法,密钥pem对JWT token进行签名,公钥pub对签名进行验证。
1 | { |
通常情况下密钥pem是无法获取到的,但是公钥pub却可以很容易通过某些途径读取到,这时,将JWT的加密算法修改为HMAC,即
1 | { |
同时使用获取到的公钥pub作为算法的密钥,对token进行签名,发送到服务器端。
服务器端会将RSA的公钥(pub)视为当前算法(HMAC)的密钥,使用HS256算法对接收到的签名进行验证。
https://skysec.top/2018/05/19/2018CUMTCTF-Final-Web/#Pastebin/
密钥暴破
暴破基础
- 知悉JWT使用的加密算法
- 一段有效的、已签名的token
- 签名用的密钥不复杂(弱密钥)
因此局限性还是较大
工具参考如下:JWT-Tools
简单的组合爆破起来相对较简单,一旦复杂起来将很难再进行实施爆破。
修改KID参数
kid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥
1 | { |
因为该参数可以由用户输入,因此也可能造成一些安全问题。
任意文件读取
kid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,因此,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。
1 | { |
SQL注入
kid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证。
1 | { |
命令执行
对kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。
1 | "/path/to/key_file|whoami" |
对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。
修改JKU/X5U
JKU的全称是”JSON Web Key Set URL”,用于指定一组用于验证令牌的密钥的URL。类似于kid,JKU也可以由用户指定输入数据,如果没有经过严格过滤,就可以指定一组自定义的密钥文件,并指定web应用使用该组密钥来验证token。
X5U则以URI的形式数允许攻击者指定用于验证令牌的公钥证书或证书链,与JKU的攻击利用方式类似。
信息泄漏
JWT保证的是数据传输过程中的完整性而不是机密性。
由于payload是使用base64url编码的,所以相当于明文传输,如果在payload中携带了敏感信息(如存放密钥对的文件路径),单独对payload部分进行base64url解码,就可以读取到payload中携带的信息。
JWT Tools
1 | git clone https://github.com/brendan-rius/c-jwt-cracker.git |

JWT在线工具
1 | pip3 install pycryptodomex |


1 | 1. 修改JWT |
交互工具
主要针对alg被致None,因在线工具无法修改为None,所以需要使用交互方式来获取token。
1 | python |
JWT攻击
以下题目参考ctfhub中关于JWT的CTF试题学习并练习;算法修改并未得到flag。
题一:信息泄漏
题目提示信息:敏感信息泄漏

访问URL
1 | http://challenge-f0ba92c933a7d9be.sandbox.ctfhub.com:10080/ |
提示输入用户名及密码

观察响应数据

发现Cookie属于JWT

复制并提交在线工具
1 | eyJBRyI6ImI5MmNlNzk1NDg4ZTZjMDExNjBmNjU4fSIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhZG1pbiIsIkZMIjoiY3RmaHViezA1OGFiZjNiM2IwZTlkOGQ1In0._TNIAg9rDfqtOFejHiIz9tXyJ7-hGqsKlJudTfXYZtw |

1 | ctfhub{058abf3b3b0e9d8d5b92ce795488e6c01160f658} |
题二:None
题目提示:JWT支持None,并且后端不执行签名验证。

访问URL
1 | http://challenge-9f380c0d9554b48b.sandbox.ctfhub.com:10080/login.php |
admin/admin登录:提示只有admin才能获得flag值。


获取登录token并进行在线解码处理
分别对header、payload进行解码修改对应值并编码处理。


1 | # 因后台不进行签名验证了,因此可直接替换对应值即可绕过。 |
用none算法生成的JWT只有两部分了,根本连签名都不存在。

替换token,重放后可得到flag值

1 | ctfhub{adcd547cd87ee1536fba1a7fe530a8d9719e9ee3} |
题三:弱密码
由题目得知:JWT采用对称加密算法,如果密钥的强度较弱的话,会被爆破攻击。

访问URL
1 | http://challenge-97dc1d0c313c1266.sandbox.ctfhub.com:10080/login.php |

admin/admin

获取JWT的token
1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IjEiLCJwYXNzd29yZCI6IjEiLCJyb2xlIjoiZ3Vlc3QifQ.dkimTl0KydTeIHQ1UvhjAK7FPfArIkgf8XWp7VsKZyE |
使用工具进行爆破得到密钥

修改对应值并获得最新的token

1 | ctfhub{11f50e22266935854562ba365e25aabd719a7cc3} |
题四:修改签名算法
题目:修改签名算法完成绕过;

访问URL
1 | http://challenge-9fc2bbd399072286.sandbox.ctfhub.com:10080/ |
登录入口信息及部分php提示

提示如下:主要关注点下面,主要是对JWT算法并绕过获得flag。

1 | {"username":"admin","password":"admin","role":"admin"} |
1 | pip install pyjwt |
未获取flag!!!
Referer
1 | https://xz.aliyun.com/t/6776 |
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章