JWT总结

JWT是什么

全称Json Web Token。是跨域身份认证的一种方式。JWT的声明一般是用来身份提供者与服务提供者之间传递被认证的用户身份信息。便于从服务器获取到资源。它也可以用来记录用户信息。与token不同的是,它不用查询数据库,只要在服务端使用密钥完成校验就行。

JWT的原理

服务器认证以后,就会生成一个json对象,并发回给用户。例如

{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2018年7月1日0点0分"
}

之后,客户端再与服务端通讯的时候都要发回这个json对象。服务器是只靠这个东西来认证身份的。但为了保证安全性,所以会加上签名。

JWT长什么样子

jwt是由三部分组成,分别是header payload signature这三部分。

Header

jwt的头部承载着两部分信息。一是声明类型,这里是jwt,二是声明加密的算法,通常就使用HMAC和SHA256,例如这样的一个完整的JSON。

{
     'typ': 'jwt',
     'alg': 'HS256'
}

对它的头部进行base64加密。就构成了jwt的第一部分。

ewogICAgICd0eXAnOiAnand0JywKICAgICAnYWxnJzogJ0hTMjU2Jwp9

Payload

这一部分就是存放有效信息的地方。这些有效信息包含三个部分。

标准注册的声明,公共的声明和私有的声明。标准注册的声明并不强制使用。

标准注册的声明有

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明是可以添加任何信息的,一般添加用户的相关信息或者其他业务需要的必要信息。这一部分客户端是可见的,所以不建议存放敏感信息。

私有声明是提供者和消费者所共同定义的声明,不建议存放敏感信息。用base64加密等于明文。

举例一个payload:

{
  "sub": "1234567890",
  "name": "XiLitter",
  "admin": true
}

同样对payload这一部分进行base64加密。

ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiWGlMaXR0ZXIiLAogICJhZG1pbiI6IHRydWUKfQ==

还是那句话,payload这一部分只进行base64加密,里面的信息对于任何人都是可见的。所以尽量别把敏感信息放在这个部分。

signature

这一部分是对前两部分的签名,防止数据被纂改。

首先是需要这个密钥的,这个密钥只有服务器知道,不会泄露给用户。然后就使用header头里的签名算法生成签名。相关公式:

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

默认采用的签名算法是HMAC SHA256.产生签名后,这三部分就用点(.)将这三部分连接起来,就组成了完整的jwt。

实际的jwt

JWT总结_第1张图片

看似很安全的认证方式,却成为了渗透人员最喜欢的攻击手段。

怎么入侵JWT

敏感信息泄露

上面也说了,jwt的payload是任何人可见的,所以如果这一部分添加有用户的敏感性息,那就会造成敏感信息泄露,(比如账号密码)很好理解。

将算法修改为none

其实jwt是支持将算法修改为none的,这样的话,jwt中的签名就会被清空,所以就没有什么安全性可言了。任何token都是可以的,最初由这样的设定是为了方便调试。所以一定要在真实环境中关闭该功能,不然的话,攻击者就可以伪造任意的token来进行任意用户登录网站。(管理员)

在赛题环境中,如果我们设置alg为none,并不带签名生成token。如果页面返回有效,说明存在漏洞。

密钥混合攻击

那就要用到JWT两种最常见的算法。HMAC和RSA。HMAC是对称加密算法,使用同一密钥对token进行签名和认证。而RSA是非对称加密算法,它是需要两个密钥,用私钥对token进行加密生成jwt,再用公钥进行认证。基础知识了解,再说说攻击思路:我们可以伪造解密的算法,由RS256改为HS256,那么被用于HS256解密的密钥就变成了RS256的公钥。为什么要这么做?HS256加密解密都用一个密钥,所以安全起见,服务端是不会让你知道HS356的密钥的,而RS256是由服务端用私钥加密,再用公钥解密,所以私钥用户是得不到的,而公钥无所谓得到,因为没有私钥加密,就伪造不了token。一旦我们更改解密算法,我们是可以获取到RS256的公钥,又因为改算法为HS256,它会将RS256的公钥作为密钥,那么不言而喻,我们可以伪造任意的

{"typ":"JWT","alg":"HS256"}.
{"login":"ticarpi"}.
[使用HS256签名,使用RSA公钥文件作为密钥验证。]

token了。这种攻击的预防也很容易,禁止同时使用这两种算法就行。

密钥弱口令

这个就不多说了,推荐一个密钥爆破工具GitHub - brendan-rius/c-jwt-cracker: JWT brute force cracker written in C

当然还要有一个重要的网站GitHub - brendan-rius/c-jwt-cracker: JWT brute force cracker written in C,可以在这个网站生成jwt。

练几个小题

敏感信息泄露

是一个登录框,这种题一般都少不了抓包。

JWT总结_第2张图片

这种形式的token,jwt无疑了。放在刚才那个网站得出flag

JWT总结_第3张图片

无签名

JWT总结_第4张图片

一样的登录框,同样抓包,没啥好说的

JWT总结_第5张图片

将jwt进行base64解码。将HS256改为none

JWT总结_第6张图片

payload部分修改为管理员

JWT总结_第7张图片

同时舍弃掉签名。构造payload

Token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ==.

用点将这三部分连接起来,即使signature没有。注意,在登录后的界面进行改包抓包。改jwt得到flag。

JWT总结_第8张图片

结语

目前就做这两题感受一下,明天再把剩下两题解决掉(ctfhub)

相关链接:

基于jwt的token验证 - 奕锋博客 - 博客园 (cnblogs.com)

JWT攻击手册:如何入侵你的Token - Bypass - 博客园 (cnblogs.com)

你可能感兴趣的:(#,基础漏洞,后端,json,web安全)