JWT安全学习笔记
什么是JWT?
JWT全称Json Web Token是一种跨域验证身份的方案,JWT不加密传输的数据,但是能够通过数字签名来验证数据未被篡改。
JWT的组成
JWT分为三部分,头部(Header),声明(claims),签名(signature),三个部分以英文句号.隔开。JWT的内容以Base64URL进行了编码。
头部和声明是由base64url加密的。签名是整合头部和声明利用密钥进行加密的结果。
(在HTTP传输过程中,Base64编码中的"=“,”+“,”/"等特殊URL编码通常容易产生歧义,因此产生了与URL兼容的Base64url编码。)
头部(Header)
{
"alg":"HS256",
"typ":"JWT"
}
alg的含义:
说明这个JWT的签名使用的算法的参数,常见值用HS256(默认),HS512等,也可以为None。HS256表示HMAC SHA256。
typ的含义:
说明这个token的类型为JWT
声明(claims)
{
"exp":1416471934,
"user_name":"user",
"scope":[
"read",
"write"
],
"authorities":[
"ROLE_ADMIN",
"ROLE_USER"
],
"jti":"9bc92a44-0b1a-4c5e-be70-da52075b9a84",
"client_id":"my-client-with-secret"
}
JWT固定参数有:
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti: JWT ID用于标识该JWT
签名(signatura)
服务器有一个不会发送给客户端的密码(secret),用头部中指定的算法对头部和声明的内容用此密码进行加密,生成的字符串就是JWT的签名。
下面是一个用HS256生成Jw=WT的代码例子
HMACSHA256(base64Encode(header) + "." + base64urlEncode(payload),secret)
为了更深入的理解这个JWT的组成,我们通过webgoat靶场来练习一下
webgoat JWT安全练习第一题
给了一串JWT字符串,然后问username是什么?
解这题,我们可以一步一步解析一下每个部分。
以上的header使用base64解密如下:
claims解密如下:
这就很明显了,用户名是user,我们提交发现成了。
JWT的使用过程
1、用户端登录,用户名和密码在请求中被发往服务器。
2、(确认登录信息正确后)服务器生成JSON头部和声明,将登录信息写入JSON的声明中(通常不应写入密码,因为JWT是不加密的),并用secret用指定算法进行加密,生成该用户的JWT。此时,服务器并没有保存登录状态信息。
3、服务器将JWT(通过响应)返回给客户端。
4、用户下次会话时,客户端会自动将wT写在HTTP请求头部的Authorization字段中。
5、服务器对JWT进行验证,若验证成功,则确认此用户的登录状态。
6、服务器返回响应。
JWT修改伪造攻击
通过这题了解JWT传输过程,验证机制
通过这题了解JWT结构,加解密 过程以及注意事项
注意:
问题来了,因为JWT声明内容变了,因此签名需要重新生成,生成签名又需要密码,但是我们没有密码啊。不要慌,我们直接去掉签名就好了,修改头部为None
通过webgoat靶场的一个例子来阐述这个伪造攻击的过程
webgoat靶场JWT伪造例子
这题给了一个投票的界面。能发现当前是guest账户。题目要求重置投票的情况。但是都没有权限。
点击小人倒三角可以切换为其他用户,如图是切换成了tom
点击右上角的垃圾桶标志,可以重置投票。但是会被提示只有admin有权限。
我们点击那个垃圾桶标志抓包看看
在cookie中能很明显的发现jwt加密的字符串,我们拿到网站上解密一下试试,确实如我们所猜测。解密网址:jwt.io
能发现,其中的admin是false状态,那我们直接修改为true试试。
复制内容,到重放器里面重放一下试试。
很尴尬,说不对,也确实不对,我们不知道加密的密钥,那我们直接删除后面加密的内容呢?
成了!真的重置了。
继续看一题,了解JWT的整体加密过程。
webgoat靶场JWT伪造例题2–JWT加密爆破
打开题目,能看到给了一串JWT的字符串,然后题目要求将其中的用户名更改为webgoat然后重新提交。
这地方存在一个难题,就是我们虽然能知道header以及claims,但是我们不知道公钥,这咋办呢?不用怕,hashcat能直接破解。
我们将以上字符串保存为txt,然后使用hashcat爆破
hashcat -m 16500 /home/kali/Desktop/7.txt -a 3 -w 1 /home/kali/Desktop/dict/google-10000-english-master/20k.txt --force
16500代表是破解JWT,7.txt是上面的jwt字符串 -a 3以及-w 3代表暴力高速破解,后面是字典的位置,–force表示忽略错误。
能破解出来公钥是
washington
把原始的jwt字符串复制到以下网址
jwt.io
然后添加公钥washington,修改username为WebGoat,同时记得修改一下失效时间戳,时间戳往后延迟一点就行。
提交,能发现通过了
参考内容:
https://blog.csdn.net/zy15667076526/article/details/109560492
https://blog.csdn.net/weixin_50464560/article/details/120579337
https://git哈不.com/first20hours/google-10000-english(密码字典)