Jwt security issue

JWT介绍与jwt的结构

什么是JWT,jwt全称:Json Web Token,是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的,jwt可以用于授权与信息交换,作为跨域身份验证的一种方案.

JWT的结构:Header(头部) . Payload(负载) . Signature(签名) 由3部分组成

Header结构
1
2
3
4
5
{
"alg":"HS256"//默认HMAC SHA256 HS256
"typ":"JWT"
"kid":"/key/"//可选参数 指定加密算法的密钥
}

alg表示签名算法,typ表示令牌类型 后用Base64Url加密为字符串

Payload结构
1
{"jti":"1","iat":1528630988,"sub":"user1","exp":1528631588}

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

Signature结构

Header指定的算法( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret) ,例如:

1
2
3
4
5
6
7
8
9
10
header
{
"alg":"HS256"//默认HMAC SHA256 HS256
"typ":"JWT"
"kid":"/key/"//可选参数 指定加密算法的密钥
}
payload
{"jti":"1","iat":1528630988,"sub":"user1","exp":1528631588}
signature
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

用来根据Header指定的算法和secret对header和payload加密作为客户端的Cookie

Base64Url算法

1
JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。

最终:

header.payload.Signature 其中header 与 payload 可以解密 Signature用于保证 内容不可篡改

base64encode(header).base64encode(payload).Header指定的算法( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

攻击面:

加密算法层面

修改算法攻击:加密方法是RS256(非对称加密),此时获得了公钥,无法获得解密私钥,可以修改RS256为HS256,这时候服务器会使用公钥解密客户端提交的信息

1
2
3
4
5
6
7
8
9
{
"alg" : "RS256",
"typ" : "jwt"
}
换成
{
"alg" : "HS256",
"typ" : "jwt"
}

JWT RFC允许空秘钥:得到一个token后,我们可以base64解密,把header的算法为none时,使服务端不使用算法解密 直接读取内容 即无法校验内容是否被篡改,使得我们可以修改jwt中的信息

即:

1
2
3
4
{
"alg":"none"//默认HMAC SHA256 HS256
"typ":"JWT"
}

签名中的secret可控通过一些方法可以获得任意用户的秘钥,就可以通过秘钥伪造jwt登陆任意用户
签名中的secret可爆破:在HS签名算法时,只有一个秘钥就是secret

其他攻击方法

使用JWT作为cookie用于跨域登录认证导致的问题,所有子域名都能通过该jwt登录,当该token泄露无需密码就能登录等,以及token过期时间问题。

signature中的secret泄露,各种泄露方式debug报错泄露,模板注入泄露获取配置文件,当Flask等Py模板注入受限只能获取配置文件中的内容可以考虑一下该攻击方案,获取备份文件解析问题导致下载备份文件泄露,以及默认的secret等等。。

敏感信息泄露:payload中的内容包含敏感信息如手机号,身份证,银行卡,密码等等

header中的Kid

kid在header的作用是用于指定加密算法的密钥,当kid指定密钥文件时修改为我们要读取的文件时导致的任意文件读取漏洞,当kid是从数据库中读取时可以导致SQL注入漏洞,当kid是通过grep这种调用程序匹配时出现命令执行问题

XSS的拓展

修改payload中内容导致的xss问题 如报错导致的xss 返回payload 信息的xss(如登录某一系统采用的是jwt方式进行身份验证,其中登录后展示的用户信息包含在jwt中修改这些信息为xss payload

在与服务器传输数据时,如一些修改个人信息的数据包中被放到jwt中,可以结合csrf发送这些数据包

jwt的玩法是多种多样的,可以根据具体情况来利用

Tips:因为Cookie不能跨域的原因所以一般是会放在HTTP请求头的 Authorization 字段 或者使用POST跨域传递

关于JWT鉴权安全问题

chybeta师傅的文章