前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JWT 原理与设计上的缺陷及利用(基础篇)

JWT 原理与设计上的缺陷及利用(基础篇)

作者头像
FB客服
发布2023-03-29 15:47:08
9730
发布2023-03-29 15:47:08
举报
文章被收录于专栏:FreeBuf

基本概念

JSON Web Token (JWT)是一个开放标准 ( RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象的形式安全传输信息。此信息可以验证和信任,因为它是数字签名的。JWT可以使用密钥(使用HMAC算法)或使用RSAECDSA的公钥/私钥对进行签名。

不理解上述解释没有关系,在解释 JWT 具体是个啥之前,先看看它会被用在什么地方。

跨域认证

HTTP/HTTPS协议中,由于其是无状态协议,所以其中对于用户身份的认证过程一般是这样的:

基于 session 的认证

  1. 用户向服务器提供用户名与密码进行用户认证。
  2. 服务器收到验证用户身份合法后,为了避免该用户下次再次请求还需要重新认证(无状态协议不会记录),服务器会在当前会话(session)里面保存相关与用于身份有关的数据(用户身份等)。
  3. 服务器根据该session生成一个session_id用于唯一标识该session,并将其放入Cookie中返回给用户。
  4. 随后用户的每次请求都会带上该Cookie,服务器便可从该 Cookie 中获取到该用户的session_id以便对应之前保存在服务端的数据得知用户的身份。

但这种方式存在的一些缺点:

  • 随着用户的增多,服务端将保存大量session,增大开销 解决方案1:启用Session Ticket参数,将加密的session通过服务端的密钥加密后保存于客户端本地进行验证。
  • 扩展性不好,不适用于分布式站点的单点登录(SSO)的场景:若是存在服务器集群,比如最简单的一家公司有两个网站,要求两个网站实现单点登录的功能(即:登录一个网站另一个关联网站也自动登录),此时若采用session认证,就需要两个网站共享session,在并发量大的情况下,不可能直接传输,而是应当将session持久化保存在本地(比如说数据库中),再向其请求,但这样工程量较大,而且一旦数据库持久化出问题单点登录将会失败(所有用户的单点登录)。
  • 易受CSRF等攻击。

基于 JWT 的认证

  1. 首先用户通过浏览器向服务器发起一个POST请求,其中携带着usernamepassword进行认证。
  2. 服务器验证用户身份后,会生成具有该用户标识信息的一个JWT对象,为了防止其中关于用户的信息在传输过程中被篡改,再用自己生成的一个secret对其加上签名并将其发给用户。
  3. 之后用户再次请求时,只需要带上这个JWT对象(类似于一个token),服务器即可验证其身份。 客户端得到JWT对象字符串后,一般将JWT对象字符串放在HTTP请求的头信息的Authorization字段中(也可以放在Cookie中,但放在Cookie中是无法跨域的 )发给服务器。

JWT 对象结构

这里可直接通过其官网进行Debugger,官方网站:https://jwt.io/

以官网提供的例子为例,JWT对象长这样:

一个 JWT 对象由三个部分组成,以.进行分隔,所以上面这个JWT对象可以分为三部分:

代码语言:javascript
复制
`Header.Payload.Signature`
  • Header(头部) eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
  • Payload(负载) eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
  • Signature(签名) SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header(头部)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9是一个Base64URL 编码后的数据,解码后得到的内容为:

代码语言:javascript
复制
代码语言:javascript
复制
{  "alg": "HS256",  "typ": "JWT"}

Header部分是一个JSON对象,描述JWT的元数据,其中有这几个参数:

  • alg签名使用的算法 默认为HMAC SHA256( 简写为HS256
  • typ用于标识该令牌(token)的类型为JWT

Payload(负载)

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ同样为Base64URL 编码后的数据。

代码语言:javascript
复制
{  "sub": "1234567890",  "name": "John Doe",  "iat": 1516239022}

但此处有一个特殊的地方在于,此处使用Base64URL编码与Base64有点小区别,编码后的数据,会将其用于填充的==去掉。

Base64有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略+替换成-/替换成_这就是Base64URL算法。

Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段供选用:

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题(jwt所面向的用户)
  • aud (audience):受众( 接收jwt的一方 )
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间(Unix 时间格式)
  • jti (JWT ID):编号(jst的唯一标识,主要用来作为一次性 token ,从而避免重放攻击)

这些只是官方的字段,若像定义,还可以定义私有的字段。

JWT 默认是不加密的,任何人都可以控制,将私密信息放到此处将会被泄露。

Signature(签名)

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c此处并不是Base64编码的数据。

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c计算过程:

首先,需要指定一个secret,这个密钥由服务器生成,只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照下面的公式产生签名。

代码语言:javascript
复制
HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)
代码语言:javascript
复制

用于对前两部分加一个签名,防止前两部分的数据被篡改(被篡改后计算所得值不同)。

JWT 特点

JWT默认是不加密,但也是可以加密的。生成原始Token以后,可以用密钥再加密一次。

JWT 的缺点

由于服务器不保存session状态,因此无法在使用过程中废止某个token,或者更改token的权限。也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑,建议:

  • JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输。
  • JWT的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

针对 JWT 相关的攻击

未经验证的签名绕过 JWT 身份验证

由于后端没有对JWT的签名进行验证,可导致Payload字段遭到修改,以达到越权访问的目的。

这里使用Burp官方提供的Lab: JWT authentication bypass via unverified signature靶场,实验链接:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature

题目要求:

为我们提供了一个常规用户的账户与密码wiener:peter让我们越权使用 admin 账户,并用其删除carlos账户。

1:登录后抓包

注意之后的所有操作中若在Burp中对JWT的对象属性进行修改后,都要点击Apply changes否则修改不会对应在原报文中。

  • 通过wiener:peter进行账户登录后,启动Burp挂上代理并点击My account进行抓包。
  • 从中可以看到用于验证客户端浏览器身份的JWT对象字符串,此处是放在Cookie中进行传输通过对其中Payload段进行Base64URL解密,可以获得其Payload携带的信息(见截图右下角)。

此处也可以使用Burp的插件JSON Web Token来查看JWT对象的结构。

2:改包越权访问 administrator 账户

由于后端没有对JWT对象做签名的验证,所以此处可以直接修改其中的sub字段为administrator,并修改登录的idadminisrator。

之后便会访问到administrator的界面,点击其特有的Admin panel管理界面并抓包。

此时再次修改请求发出用于确认身份的JWT对象中sub属性为administrator。

成功访问,删除用户即可。

若对上述过程还存疑,可看该视频:https://youtu.be/Xy0pvy8ZdvU

爆破 Secret 进行越权

使用hashcatJWT服务端的secret进行破解。

这里使用Burp官方提供的Lab: JWT authentication bypass via weak signing key靶场,实验链接:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-weak-signing-key

题目要求:

本实验使用基于 JWT 的机制来处理会话。它使用极弱的密钥来签署和验证令牌。这可以很容易地使用一个常见的秘‍密词表暴力破解。其余账户与要完成的任务与上一题相同。

1:正常登录获取 JWT token

此处与上一题的过程相同,首先抓包获取JWT token。

2:爆破 secret

此处使用Burp官方提供的一个字典文件通过hashcat来暴力破解其secret值。

代码语言:javascript
复制
hashcat -a 0 -m 16500 JWT_token JWTsecretDirectory
  • JWT_token要破解的刚刚抓包获取的JWT token
  • JWTsecretDirectory官方提供的secret字典

最终破解得到secret = secret1

3:计算 administrator 的 JWT token

之后的操作就简单了,和前一题类似。

参考文章:

1.http://book.fsec.io/201-%E6%BC%8F%E6%B4%9E%E5%8E%9F%E7%90%86%E4%B8%8E%E5%B7%A5%E5%85%B7/201-A-%E6%BC%8F%E6%B4%9E%E5%8E%9F%E7%90%86/201-A24-JWT%E6%BC%8F%E6%B4%9E.html

2.https://www.4hou.com/posts/zlK2

3.https://jwt.io/

4.https://portswigger.net/web-security/jwt

5.https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list

6.https://www.freebuf.com/articles/web/337347.html

精彩推荐

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本概念
  • JSON Web Token (JWT)是一个开放标准 ( RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象的形式安全传输信息。此信息可以验证和信任,因为它是数字签名的。JWT可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
  • 跨域认证
  • 在HTTP/HTTPS协议中,由于其是无状态协议,所以其中对于用户身份的认证过程一般是这样的:
    • 基于 session 的认证
      • 基于 JWT 的认证
      • JWT 对象结构
        • Header(头部)
          • Payload(负载)
            • Signature(签名)
              • JWT 的缺点
              • 针对 JWT 相关的攻击
                • 未经验证的签名绕过 JWT 身份验证
                  • 1:登录后抓包
                  • 2:改包越权访问 administrator 账户
                • 爆破 Secret 进行越权
                  • 1:正常登录获取 JWT token
                  • 2:爆破 secret
                  • 3:计算 administrator 的 JWT token
              • 参考文章:
              相关产品与服务
              多因子身份认证
              多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档