在目前微服务的架构下,使用JWT作为用户的身份认证方式越来越常见。本篇文章就来认识一下JWT的生成方式以及可能存在的安全风险。
由于本人水平有限,文章中可能会出现一些错误,欢迎各位大佬指正,感激不尽。如果有什么好的想法也欢迎交流~~
JWT(JSON Web Token)是一种用于身份认证和授权的开放标准,它通过在网络应用间传递被加密的JSON数据来安全地传输信息使得身份验证和授权变得更加简单和安全。
用来身份验证和授权
WT对于渗透测试人员而言可能是一种非常吸引人的攻击途径,因为它们不仅是让你获得无限访问权限的关键而且还被视为隐藏了通往以下特权的途径,例如:特权升级、信息泄露、SQLi、XSS、SSRF、RCE、LFI等。
JWT(JSON Web Token)的结构由三部分组成,分别是Header、Payload和Signature,每个部分以“.”分割。如下图:
下面来具体说一下每个部分
Header包含了JWT使用的算法和类型等元数据信息,通常使用JSON对象表示并使用Base64编码,Header中包含两个字段:alg和typ
alg(algorithm):指定了使用的加密算法,常见的有HMAC、RSA和ECDSA等算法
typ(type):指定了JWT的类型,通常为JWT
上面为hearder的一个实例,其中alg指定了使用HMAC-SHA256算法进行签名,typ指定了JWT的类型为JWT
Payload包含了JWT的主要信息,通常使用JSON对象表示并使用Base64编码,Payload中包含三个类型的字段:注册声明、公共声明和私有声明
这部分是重要的,可以自定义信息保存在此
公共声明(Public Claims):使用 JWT 的人可以随意定义这些声明( 可以自己声明一些有效信息如用户的id,name等,但是不要设置一些敏感信息,如密码 )。但是为了避免冲突,应该在 JWT注册表中定义它们,或者将它们定义为包含抗冲突名称空间的 URI。
私有声明(Private Claims):这些是创建用于在同意使用它们的各方之间共享信息的习惯声明,既不是注册声明,也不是公开声明( 私人声明是提供者和消费者所共同定义的声明 )。
注册声明(Registered Claims):预定义的标准字段,包含了一些JWT的元数据信息,例如:发行者、过期时间等
{
"sub": "1234567890",// 注册声明
"name": "John Doe",// 公共声明
"admin": true // 私有声明
}
这里共同声明和私有声明都是可以自己定义的,因此要额外关注,注意是否存在敏感信息。
另外注册声明是JWT已经预定义好的,通常有下面的一些字段
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
注意:对于已签名的Token,这些信息虽然受到保护,不会被篡改,但任何人都可以阅读。除非加密,否则不要将机密信息放在 JWT 的有效负载或头元素中。
Signature是使用指定算法对Header和Payload进行签名生成的,用于验证JWT的完整性和真实性,Signature的生成方式通常是将Header和Payload连接起来然后使用指定算法对其进行签名,最终将签名结果与Header和Payload一起组成JWT,Signature的生成和验证需要使用相同的密钥,下面是一个示例Signature
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
其中HMACSHA256是使用HMAC SHA256算法进行签名,header和payload是经过Base64编码的Header和Payload,secret是用于签名和验证的密钥,最终将Header、Payload和Signature连接起来用句点(.)分隔就形成了一个完整的JWT,下面是一个示例JWT,其中第一部分是Header,第二部分是Payload,第三部分是Signature,注意JWT 中的每一部分都是经过Base64编码的,但并不是加密的,因此JWT中的信息是可以被解密的
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
下面是一个JWT在线构造和解构的平台:
由于Header和Payload部分是使用可逆base64方法编码的,因此任何能够看到令牌的人都可以读取数据。如果在Header和Payload内写了敏感信息,则会导致敏感信息泄露。
可以使用上面的在线工具对JWT进行解密,,存在敏感信息的话就可以直接拿到