关于JWT鉴权安全问题

简介: JSON Web Token(JWT https://jwt.io )是一种跨域身份验证解决方案,其主要认证原理是提供一个可信签名,利用存在客户端的secret_key将明文的鉴权数据做一个签名,用于跨域校验权限的合法性。

什么是JWT

aaa

JSON Web Token(JWT  https://jwt.io )是一种跨域身份验证解决方案,其主要认证原理是提供一个可信签名,利用存在客户端的secret_key将明文的鉴权数据做一个签名,用于跨域校验权限的合法性。

举一个例子:

Authorizatione: yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.MXi3JVNa96zFigIouJL9dSmGxXmLkyO2lMyiJpw-sEs
1

https://jwt.io生成

JWT分为三段,由"."分开,第一段是加密算法,这里选择的是HS256,也就是基于SHA-256的HMAC,对称加密签名算法,介于安全性,其实用RS256(基于SHA-256的RSA256,非对称加密签名算法)更好,原因后面会提到。第二段是内容,这里就是给用户标上了admin的标签,在用jwt时,切记勿将敏感数据直接存入JWT,因为JWT本身只提供签名认证作用,其数据还是明文传输,任何人拿到都可以解密,并不能起到保密作用。

echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 --d
{"alg":"HS256","typ":"JWT"}
echo eyJ1c2VyIjoiYWRtaW4ifQ== | base64 --d
{"user":"admin"}

第三段就是加密签名内容了,客户端在接收到用户端传输过来的JWT后,会首先利用secret_key校验签名,如果签名正确,就会去解密第二段的内容,用于认证。

关于JWT的安全性

用JWT代替cookie做站点鉴权,对多个业务方共享一套账户体系的确带来了很大的便利,相互获取数据不用考虑带cookie跨域导致的一系列安全风险(例如JSONP、CORS等)也不用在交互身份信息时每次都实现一次OAUTH,对开发和安全有极大的帮助,但是由于JWT的安全性全部依赖与最后的签名,其实还是有安全风险的,下面分别说下自己遇到过的几个JWT伪造攻击成功的例子。
1、测试站点与主站点secret_key相同
之前在挖掘漏洞的时候遇到过,某需要拿下来的后台main.xxx.com,存在一个测试站点dev.xxx.com,两个站点可能功能存在部分不同,但都是利用JWT鉴权,并且main.xxx.com登陆存在验证码,而dev.xxx.com不用验证码可以爆破,于是我尝试爆破了dev.xxx.com。

发现存在弱口令 :

123456 / xxxxxxxxx

2

登陆成功后发现返回了一段token,是JWT。并且发现在之后请求数据的数据包里,是利用此段JWT鉴权。

3

 于是猜想,main.xxx.com与dev.xxx.com有没有可能存在是利用的同一段secret_key,这样我就能利用这段JWT去登陆main.xxx.com主站系统,burpsuite修改返回包为测试站点登陆成功的返回包:

4

直接登陆成功main.xxx.com:

5

这里,我们引出了一个安全隐患:对于不同的站点,JWT的secret_key不能设置为相同。
2、泄露secret_key导致任意用户登录

在很多开发框架里面,对DEBUG模式下的异常处理,都会将一些配置信息显示出来,以便于开发者调试,例如Django的调试页面:

6

来源:fofa.so

有的开发过程中,如果是自己实现的JWT,可能会将secret_key存在配置信息中,在部分框架的报错页面中,会导致secret_key泄漏,最后导致任意用户伪造登陆,例如hackerone上面最近披露的一个漏洞:

https://hackerone.com/reports/460545
图片.png

我在之前测试中也遇到过,当时是遇到一个利用JWT鉴权的框架开发的APP下找到一个Debug页面,发现secret_key直接回显在了Debug页面前端:

7

这样,我们可以利用低权限用户的JWT,去伪造高权限的JWT,具体方法如下:

base64 decode原本JWT的加密算法与JWT内容

伪造自己想伪造的内容部分

利用泄漏的secret_key对伪造的内容进行签名

8

利用得到的JWT字符串,直接用管理员权限登陆了刚刚的系统。

 当然,不止是DEBUG页面,类似泄漏的方法很多,例如Flask模板注入、格式化字符串漏洞可以直接读取配置信息、配置文件在WEB目录下可下载、CMS默认存在secret_key使用未修改等,这里就不一一叙述了。

对于secret_key泄漏情况,其实JWT本身设计的时候是有考虑到的,就是之前提到的JWT会提供不同的签名算法,其中说到了RS256算法会更好,其原因就是RS256(采用SHA-256 的 RSA签名)是一种非对称算法,它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。也就是说,我们这里只需要维护一个私钥服务用于保护私钥,而用于验证签名的公钥就可以分发到下面各个业务方,就算他们配置不当,将公钥泄漏,也无法通过公钥对我们的JWT认证系统伪造。

3、secret_key过弱,或者长期不更换导致可爆破

之前提到过,JWT有一个缺陷是无法对数据进行加密,也就是说数据是对用户都是明文可知的,这就出现一个问题:

既然需要加密的数据、算法我都知道,为什么不能考虑爆破密钥?

所以过弱的密钥肯定是很容易被爆破成功的,毕竟是签名算法,爆破是否成功也无需传入服务端进行校验,能否爆破成功完全在于本地主机的算力大小。有人可能就会想着,那设置一个较长、随机的强key就行了。

但实际情况是随着现在超算的发展,算力越来越强的情况下,只要secret_key一直能保持不变,就肯定是能在本地被算出来,只不过是一个成本大小的问题,有没有人愿意为了你的数据,去付出这样的成本。

当然,最后这一点只是一个经验猜想之谈,我也没有实际上去操作过,也没有例子可以说明,大家可以自己尝试,说不定就真的能爆破成功~。

利用JWT认证的安全建议

严格保护自己的secret_key,防止泄漏

禁止线上站点与测试站点用一套JWT

利用RS算法代替HS算法

线上环境一定要禁止debug

设置较强的secret_key,并且定期更换
相关文章
|
28天前
|
JSON JavaScript 数据格式
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
43 1
|
9月前
|
缓存 安全 NoSQL
Spring Cloud实战 | 第六篇:Spring Cloud Gateway+ Spring Security OAuth2 + JWT实现微服务统一认证鉴权
Spring Cloud实战 | 第六篇:Spring Cloud Gateway+ Spring Security OAuth2 + JWT实现微服务统一认证鉴权
Spring Cloud实战 | 第六篇:Spring Cloud Gateway+ Spring Security OAuth2 + JWT实现微服务统一认证鉴权
|
23天前
|
负载均衡 Cloud Native 安全
云原生最佳实践系列 6:MSE 云原生网关使用 JWT 进行认证鉴权
本文档介绍了如何在 MSE(Microservices Engine)云原生网关中集成JWT进行全局认证鉴权。
|
4月前
|
存储 缓存 NoSQL
【视频+源码】登录鉴权的三种方式:token、jwt、session实战分享
【视频+源码】登录鉴权的三种方式:token、jwt、session实战分享
|
4月前
|
SQL API Go
go-zero jwt 鉴权快速实战
go-zero jwt 鉴权快速实战
|
8月前
|
JSON 算法 中间件
如何实现jwt鉴权机制?
如何实现jwt鉴权机制?
86 0
|
8月前
|
存储 JSON 缓存
如何实现jwt鉴权机制之详解
如何实现jwt鉴权机制之详解
|
8月前
|
存储 JSON 缓存
详说JWT鉴权机制
详说JWT鉴权机制
146 0
|
9月前
|
缓存 安全 JavaScript
Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现统一认证授权和网关鉴权
Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现统一认证授权和网关鉴权
|
10月前
|
存储 JSON JavaScript
【项目实战】一、Spring boot整合JWT、Vue案例展示用户鉴权(下)
【项目实战】一、Spring boot整合JWT、Vue案例展示用户鉴权(下)
108 0