点击蓝字 关注我们
日期:2023-04-17 作者:Yukong 介绍:关于 JWT
的一些攻击手法。
0x00 JWT介绍
JWT
是JSON Web Token
的缩写,一种基于JSON
的开放标准(RFC 7519
)。将用户信息加密到token
里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token
,通过token
验证用户身份。基于token
的身份验证可以替代传cookie
+session
身份验证方法。
JWT
的格式如下:
eyJraWQiOiJrZXlzLzNjM2MyZWExYzNmMTEzZjY0OWRjOTM4OWRkNzFiODUxIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJkdWJoZTEyMyJ9.XicP4pq_WIF2bAVtPmAlWIvAUad_eeBhDOQe2MXwHrE8a7930LlfQq1lFqBs0wLMhht6Z9BQXBRos9jvQ7eumEUFWFYKRZfu9POTOEE79wxNwTxGdHc5VidvrwiytkRMtGKIyhbv68duFPI68Qnzh0z0M7t5LkEDvNivfOrxdxwb7IQsAuenKzF67Z6UArbZE8odNZAA9IYaWHeh1b4OUG0OPM3saXYSG-Q1R5X_5nlWogHHYwy2kD9v4nk1BaQ5kHJIl8B3Nc77gVIIVvzI9N_klPcX5xsuw9SsUfr9d99kaKyMUSXxeiZVM-7os_dw3ttz2f-TJSNI0DYprHHLFw
由.
分割的三部分组成,这三部分依次是:
-
标头(
Header
):标头通常由两部分组成:令牌的类型,即JWT
;以及所使用的签名算法,例如HMAC
SHA256
或RSA
。 -
有效载荷(
Payload
):包含声明。声明是关于实体(通常是用户)和附加数据的声明。声明分为三种类型:注册声明、公共声明和私人声明。 -
签名(
Signature
):标头、有效载荷、密钥、标头中指定的算法,对其进行签名。
0x01 身份验证和获取JWT令牌
-
用户使用用户名和密码,并经过服务器验证成功后登录;
-
服务器创建一个新令牌;
-
并将此令牌返回给客户端;
-
此后用户浏览器要携带
token
,去向服务端发送请求; -
服务器读取令牌,并在成功验证后首先验证签名;
-
合法则返回对应的信息给用户。
更多具体内容请参考:https://jwt.io/introduction
0x02 攻击方式
2.1 空加密算法攻击
JWT
支持使用空加密算法,可以在header
中指定alg
为None
,同时把signature
设置为空(即不添加signature
字段),提交到服务器,任何token
都可以通过服务器的验证
(1)以Tom
身份登录,点击重置投票,系统提示只有admin
才可以重置:
(2)使用burp
抓包,看到token
,进行JWT
解密:
解密工具:https://github.com/ticarpi/jwt_tool
python jwt_tool.py <JWT> # 自动解密JWT
(3)将header
中alg
的加密算法改为none
,payload
中admin
的值改为true
:
python jwt_tools.py <jwt> -T # 进入交互式修改JWT的值
(4)删除最后的签名字段,替换burp
中的access_token
,并发送,可以绕过admin
权限:
2.2 未校验签名
某些服务端并未校验JWT
签名,可以尝试修改signature
后(或者直接删除signature
),查看其是否还有效。
(1)在请求头Authorization
中发现了JWT
字段,发送包提示JWT
已失效:
(2)使用在线解密平台解密JWT
(https://jwt.io/#debugger)
(3)发现有效时间截止至2018
年,修改exp
字段改为未来时间,并删除签名字段:
2.3 爆破密钥
有密码验证的地方就会有爆破,不过JWT
的密钥爆破需要一定的前提条件:
-
已知
JWT
使用的加密算法 -
已知一段有效的、已签名的
token
-
签名使用的密钥是弱密钥(可以爆破出来)
(1)已知一段JWT
,进行解密得到加密算法为HS256
,并且该用户为Tom
:
(2)利用该JWT
和jwt_tool
对密钥进行暴力破解:
python jwt_tools.py <jwt> -C -d 字典
(3)爆破出密钥为victory
,根据题目要求将用户改为WebGoat
,同时此题存在时间校验,需要将exp
中的时间改为未来时间,进行重新加密:
2.4 修改 KID 参数
KID
是jwt header
中的一个可选参数,全称是key ID
,它用于指定加密算法的密钥,因为该参数可以由用户输入,所以也可能造成一些安全问题。格式如下:
{
"typ": "JWT",
"kid": "webgoat_key",
"alg": "HS256"
}
1、任意文件读取
KID
参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。
{
"typ": "JWT",
"kid": "/etc/passwd",
"alg": "HS256"
}
2、SQL注入
KID
也可以从数据库中提取数据,这时候就有可能造成SQL
注入攻击,通过构造SQL
语句来获取数据或者是绕过signature
的验证
(1)例如:要求删除Tom
的账户信息,此时登录的用户为Jerry
:
(2)存在KID
字段尝试注入,将KID
值修改为SQL
语句,username
改为Tom
,签名密钥与SQL
语句相同,例如SQL
语句中为3
的base64
编码Mw==
,所以此时签名密钥写3
:
(3)删除成功:
3、命令注入
对KID
参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby
,在读取密钥文件时使用了open
函数,通过构造参数就可能造成命令注入。
{
"typ": "JWT",
"kid": "/path/to/key_file|whoami",
"alg": "HS256"
}
0x04 总结
JWT
具有方便解析,服务端不保存用户信息,不用做sessonid
复制,可以避免CSRF
漏洞攻击等优点,日常渗透和漏洞挖掘过程中使用这种认证方式的系统也越来越常见,学习并掌握JWT
的相关攻击手法是必不可少的。
参考文章
免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。
原文始发于微信公众号(宸极实验室):『红蓝对抗』JWT 攻击手法
- 我的微信
- 微信扫一扫
-
- 我的微信公众号
- 微信扫一扫
-
评论