JWT 安全
cookie(放在浏览器)
cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie 由服务器生成,发送给浏览器,浏览器把 cookie 以 kv 形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该 cookie 发送给服务器。由于 cookie 是存在客户端上的,所以浏览器加入了一些限制确保 cookie 不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的 cookie 数量是有限的
session(放在服务器)
session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。
session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。
服务器使用 session 把用户的信息临时保存在了服务器上,用户离开网站后 session 会被销毁。这种用户信息存储方式相对 cookie 来说更安全,可是 session 有一个缺陷:如果 web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候 session 会丢失。
token
在 Web 领域基于 Token 的身份验证随处可见。在大多数使用 Web API 的互联网公司中,
tokens 是多用户下处理认证的最佳方式。
以下几点特性会让你在程序中使用基于 Token 的身份验证
- 无状态、可扩展
- 支持移动设备
- 跨程序调用
- 安全
token采用加密的方式操作cookie值
jwt(json(数据格式) web token)
JWT(JSON Web Token)由三部分组成:头部(Header)、载荷(Payload)、签名(Signature)
头部(Header):头部通常由两部分组成,算法类型和令牌类型
算法类型:指定用于生成签名的算法,例如 HMAC、RSA 或者 ECDSA。
令牌类型:指定令牌的类型,常见的是 JWT。
头部使用 Base64Url 编码表示,并作为整个 JWT 的第一部分。
头部的一个示例:
{
"alg": "HS256",none #表示签名时使用的加密方式,none表示失效
"typ": "JWT"
}
载荷(Payload):载荷存储了有关用户或实体的声明和其他有关信息。
声明:如用户 ID、角色、权限等信息。
注册声明:包含一些标准的声明(比如发行人、过期时间等)和一些自定义的声明。
载荷也使用 Base64Url 编码表示,并作为整个 JWT 的第二部分。
载荷的一个示例:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
签名(Signature):签名是对头部和载荷进行签名的结果,用于验证 JWT 的完整性和真实性。
签名生成方式:将头部和载荷进行 Base64Url 编码后拼接在一起,然后使用指定的加密算法(如 HMAC、RSA)进行签名,将生成的签名添加到 JWT 中。
头部
alg
是说明这个 JWT 的签名使用的算法的参数,常见值用 HS256(默认),HS512 等,也可以为
None。HS256 表示 HMAC SHA256。
typ
说明这个 token 的类型为 JWT
payload
有载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分
- 标准中注册的声明
- 公共的声明
- 私有的声明
标准中注册的声明(建议但不强制使用):
- iss: jwt签发者
- sub:jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
签名
服务器有一个不会发送给客户端的密码(secret),用头部中指定的算法对头部和声明的内容用
此密码进行加密,生成的字符串就是 JWT 的签名
搭建WebGoat靶场
前期准备
启动靶场
java -jar webgoat-server-8.1.0.jar --server.port=8888 --server.address=192.168.63.129(kali的IP)
注意大小写
kali的IP:8888/WebGoat
访问靶场
注册用户名和密码
-
登录成功
-
开启JWT tokens靶场
WebGoat靶场通过
第4关
目的:伪造签名并清空
解题思路:
-
修改 payload 数据,admin 修改为 true,将加密方式修改为 none
-
加密,然后再解密
步骤:
首先登录Tom用户
选择一个并开始投票,发现可以一致投票
点击删除,提示只有admin用户才能清空
利用bp开始抓包
右击发送到Repeater
将cookie的值利用进行JWT解码
利用base64编码,将HS512改为none
,false改为true
分别将修改后的base64编码放在Encoded中
将HEADER和PAYLOAD的Encoded放在bp的cookie中
提示已经成功完成任务
回到页面查看,删除成功
第5关
目的:修改 exp 有效时间
前期准备:
WebGoat的爆破密钥1.txt
步骤:
找到cookie值
用Encoded打开
将cookie值放入jwt.txt文档中
用管理员身份执行打开终端
hashcat -m 16500 jwt.txt -a 3 -w 3 1.txt --force
#-m 16500 16500对应的就是 jwt 的 token 爆破;
#-a 3 代表蛮力破解
#-w 3 可以理解为高速破解,就是会让桌面进程无响应的那种高速
#jwt.txt 是我把题目要求破解的 token 保存到的文件
爆破成功
将cookie值利用base64编码进行修改
- 修改有效时间
- 修改时间戳
- 修改uaername为WebGoat
修改密钥为bnsiness
将base64编码好的放在encoded中
复制cookie值,并提交
任务成功完成
第7关
步骤:
将这个cookie值进行解码
利用时间戳将有效期1526217811
改为2023年12月7号21点30分
利用base64编码分别改为1701955800
和none
分别将修改后的base64编码放在Encoded中
点击Checkout进行抓包,并提示我们不是一个JWT令牌,请重试
右击发送到Repeater
Authorization提示我们可以承载空值,然后将cookie值放入Authorization
中
提示我们成功的完成任务, tom 帮我们付钱成功