JWT安全问题

JWT,Json Web Token是一个基于Token的身份认证协议,可以在某些情况取代Session认证。他的优点是服务器不储存任何的会话信息,只依靠客户端发送的JWT认证。

JWT分为三个部分:

Header+Payload+Signature

Header:

{alg:"RS256"}

Payload:

{"jti":"1","iat":1528630988,"sub":"测试用户1","exp":1528631588}

Signature:

乱码

这个乱码是

HMACSHA256( base64Encode(header) + "." + base64Encode(payload), secret)

签发流程:

服务器生成payload和header,根据加密算法(RS256或其他)和一串secret对header和payload加密作为客户端的Cookie。

认证流程:

客户端每次访问都带着Cookie,服务器收到Cookie后使用对应的公钥或秘钥再次加密header和payload与发送来的cookie对比,相同则通过。

攻击面:

  1. 修改算法攻击:加密方法是RS256,此时获得了公钥(加密秘钥)无法获得解密秘钥,可以修改RS256为HS256,让浏览器强行用公钥解密。
  2. 秘钥可控:通过一些方法可以获得任意用户的秘钥,就可以通过秘钥伪造jwt登陆任意用户了。
  3. 秘钥爆破:在HS签名算法时,只有一个秘钥,秘钥是否比较强就很重要了。
  4. 空秘钥攻击:JWT RFC允许空秘钥。得到一个token,base64decode他,把头部的签名方法改成None或者none提交

防御方法:

  1. 使用复杂的keys和secrets
  2. 更新正在使用的JWT库,确保没有CVE(2018-0114,Go-Jose version<=1.0.5)
  3. 检查过期时间
  4. 加强算法

利用java的jsontokenweb实现jwt

创建jwt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static StringcreateJWT(String id, String subject, long ttlMillis) throws Exception {
// 加密算法
SignatureAlgorithmsignatureAlgorithm = SignatureAlgorithm.HS256;
longnowMillis = System.currentTimeMillis();
Datenow = new Date(nowMillis);
SecretKeykey = generalKey();
JwtBuilderbuilder = Jwts.builder()
.setId(id)
.setIssuedAt(now)
.setSubject(subject)
.signWith(signatureAlgorithm, key);
if(ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);//超时时间
}
returnbuilder.compact();
}

检验jwt:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static ClaimsparseJWT(String jwt) throws Exception{
SecretKeykey = generalKey();
Claimsclaims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwt).getBody();
return claims;
}

参考:

  1. 基础: https://www.anquanke.com/post/id/145540
  2. ppt: Jwt == insecurity?
支持一下
扫一扫,支持forsigner