前言

最近学习了JWT相关的知识以及利用技巧,对此做一些总结梳理

基础知识

JWT标准文档 RFC 7519: JSON Web Token (JWT)

简介

JWT全称为JSON Web Token,将json对象作为载体来传输信息。通常用于身份认证和信息交换。JWT 可以使用密钥(HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对自身进行签名。

结构

JWT分为三部分,分别为Header,Payload以及Signature

我们通过解密网站来看看整体的情况

Header

{"alg": "HS256","typ": "JWT"
}

头部包含JWT的配置信息,alg代表JWT的签名算法,typ代表类型。还有像jwk,kid,jku,cty,x5c等参数信息

这段json通过Base64Url编码组成JWT的第一个部分

Payload

{"sub": "1234567890","name": "John Doe","iat": 1516239022
}

payload包含着一些声明,这里有三种类型的声明:注册声明,公共声明,私有声明

注册声明

例如,iss(issuer) jwt签发人,exp(expiration time) 过期时间, sub(subject) jwt所面向的用户等

更多细节可以查看RFC文档 RFC 注册声明

公共声明

这些声明可以由使用JWT的人随意定义,但为了避免冲突,最好是在IANA JSON Web Token Registry上定义

私有声明

这些声明是为了各方进行信息交换自定义的声明,既不属于注册声明,也不属于私有声明

这段json也会通过Base64Url编码组成JWT的第二个部分

Signature

要想创建签名,你需要获取header,payload以及相应的密钥。

例如,假如我们使用的是HS256算法进行加密,签名将通过以下方式创建

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

创建的签名作为第三部分组成JWT的最后部分

最后形成的就是我们下图看到的样子,由点进行分割。

JWT相关安全问题

敏感信息泄露

JWT本身包含一些敏感信息,我们可以通过JSON Web Tokens - jwt.io对相关JWT进行解码从而获取敏感信息

未对签名进行验证

如果服务端并没有对签名进行验证,那我们就可以随意修改JWT中的信息,从而可能达到越权的目的。

未对加密算法进行强验证

我们知道Header部分的alg声明了加密的算法

例如这里,我们原本声明的是HS256加密算法

{"alg": "HS256","typ": "JWT"
}

但如果服务端并未对Header声明的加密算法进行强验证,我们就可以通过将alg修改来绕过签名认证,达到随意修改JWT的目的。

空加密算法绕过

修改脚本

import jwt# payload
token_dict = {"secretid": "","username": "admin","password": "123","iat": 1660183824
}headers = {"alg": "none","typ": "JWT"
}
jwt_token = jwt.encode(token_dict,  # payload, 有效载体"",  # 进行加密签名的密钥algorithm="none",  # 指明签名算法方式, 默认也是HS256headers=headers# json web token 数据结构包含两部分, payload(有效载体), headers(标头))print(jwt_token)

虎符 CTF Web 部分 Writeup – glzjin

HFCTF2020的easyLogin考察了相关的知识点

因为开发者的使用不当,导致参数alorithms错写成了algorithm。node中的jsonwebtoken库中判断如果!secret&&!argorithms则使用传入jwt的header中的algorithm,所以只需要绕过题目中对secretid的限制,将secret置为空,就可以使用none算法,从而无需验证签名。

将RS256修改未HS256绕过

HS256为对称加密算法,使用相同的密钥进行解密。而RS256为非对称加密算法,使用私钥对消息进行签名并使用公钥进行身份验证。

如果我们能获得公钥,并且服务端对加密算法没有进行强验证,我们就可以将header头中的算法改为HS256算法,通过公钥进行签名来生成我们需要的JWT从而实现越权等操作。

修改脚本

import jwt
public = open('public.key', 'r').read()
payload={"user": "admin"}
print(jwt.encode(payload, key=public, algorithm='HS256'))

绕过弱签名密钥

如果签名使用了弱密钥,我们可以尝试使用工具对密钥进行爆破

相关工具

c-jwt-cracker

使用示例

JWT标头注入

通过jwk参数注入自签名的JWT

JWK 英文全称为 JSON Web Key,是一个JSON对象,表示一个加密的密钥,他不同于alg属性,JWK是可选的,以下就是一个示例

{"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG","typ": "JWT","alg": "RS256","jwk": {"kty": "RSA","e": "AQAB","kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG","n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"}
}

在理想情况下,服务器应该是只使用公钥白名单来验证JWT签名的,但对于一些相关配置错误的服务器会用JWK参数中嵌入的任何密钥进行验证,攻击者就可以利用这一行为,用自己的RSA私钥对修改过的JWT进行签名,然后在JWK头部中嵌入对应的公钥进行越权操作

通过jku参数注入自签名的JWT

有些服务器并不会直接使用JWK头部参数来嵌入公钥,而是使用JKU(JWK Set URL)来引用一个包含了密钥的JWK Set,我们就可以借此来构造一个密钥从而实现越权操作

通过kid参数注入自签名的JWT

服务器可能会使用多个加密密钥来为不同类型的数据进行签名,出于这个原因,在JWT头部有时会包含一个kid参数,以避免服务器验证签名时出现错误,而在JWT规范中并没有对这个kid定义具体的结构,他仅仅是开发人员任意选择的一个字符串,可能只是一个指向数据库中的一个特定条目,甚至只是一个文件的名称也有可能

我们有时可以通过修改KID参数来达到相关的攻击

任意文件读取

kid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。

{"alg" : "HS256","typ" : "jwt","kid" : "/etc/passwd"
}

SQL注入

kid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证

{"alg" : "HS256","typ" : "jwt","kid" : "key11111111' || union select 'secretkey' -- "
}

命令注入

kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。

"/path/to/key_file|whoami"

对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。

防御措施

● 使用最新的 JWT 库,虽然最新版本的稳定性有待商榷,但是安全性都是较高的

● 对 jku 标头进行严格的白名单设置

● 确保 kid 标头不容易受到通过 header 参数进行目录遍历或 SQL 注入的攻击

● 始终为颁发的任何令牌设置一个到期日

● 尽可能避免通过URL参数发送令牌

● 提供aud声明(或类似内容),以指定令牌的预期接收者,防止其应用在不同网站

● 让颁发服务器能够撤销令牌

JWT安全 知识点总结相关推荐

  1. jwt判断token是否过期_前端也得搞懂 JWT 这个知识点

    什么是 JWT 概念 JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案. JWT 原理 JWT 组成 JWT 由三部分组成:Header,Payload,Signature ...

  2. jwt token注销_辩证的眼光搞懂 JWT 这个知识点

    什么是 JWT 概念 JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案. JWT 原理 JWT 组成 JWT 由三部分组成:Header,Payload,Signature ...

  3. 从SCTF看JWT安全 (附SCTF web writeup)

    原创作者:Fz41 这两天在打SCTF,有一题涉及到JWT的简单的知识,现在来把JWT相关的知识汇总一下,虽然不是主要的考察内容,但是作为一个基础知识,还是要掌握的. JWT技术介绍 来源 用户认证的 ...

  4. CTFSHOW 菜狗杯--WEB

    WEB签到 eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]); 简单的解释下这个嵌 ...

  5. 使用MAKER进行注释: 学习MAKER的配置参数

    MAKER配置文件详解 本文翻译自http://weatherby.genetics.utah.edu/MAKER/wiki/index.php/The_MAKER_control_files_exp ...

  6. 鉴权必须了解的5个知识点:cookie,session,token,jwt,单点登录

    从状态说起 [HTTP 无状态] 我们知道,HTTP是无状态的,也就是说,HTTP请求方和响应方间无法维护状态,都是一次性的,它不知道前后的请求都发生了什么 但有的场景下,我们需要维护状态,最常见的, ...

  7. JWT最全知识点-动力节点

    一个JWT,应该是如下形式的:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9 ...

  8. 手绘10张图,把CSRF跨域攻击、JWT跨域认证说得明明白白的

    作者 | 写代码的明哥 来源 | Python编程时光 这篇文章本应该是属于 HTTP 里的一部分内容,但是我看内容也挺多的,就单独划分一篇文章来讲下. 什么是跨域请求 要明白什么叫跨域请求,首先得知 ...

  9. 你可能没那么了解 JWT

    0)前言 最近在开发一个统一认证服务,涉及到 OIDC 协议,其中授权码模式所颁发的 id_token 使用的是 JWT ( JSON Web Token ) ,因为这次使用的库的默认签名算法和以往不 ...

最新文章

  1. 使用MySQL组复制的限制和局限性
  2. AtomicInteger
  3. Silverlight Curve Animation / 曲线动画
  4. Python打包之pyinstaller
  5. 2_RabbitMQ工作模式_Work queues_Publish/Subscribe_Routing_Topics_HeaderRpc
  6. 什么可以搜python答案_超星Python程序设计答案章节测试答案免费,能搜索网课答案的公众号...
  7. ListView的性能优化之convertView和viewHolder
  8. arcgis 删除图形重复折点_【干货】ArcGIS中画环状图斑、挑子区及消除图斑重复区域...
  9. Vertica系列: Vertica DB连接负载均衡
  10. linux修改key文件夹,linux 中如何根据xml文件的key来修改value呢?
  11. android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码...
  12. cassandra学习笔记五
  13. mysql mysqldump导出与导入sql文件
  14. 按timestamp查询_04. 复杂查询
  15. 雨棚板弹性法计算简图_钢结构雨篷图纸计算书
  16. Maven详细安装教程
  17. C++ STL库之vector
  18. 对比excel 轻松学python电子书_对比Excel,轻松学习Python数据分析
  19. 1.JsDroid命令行调试命令
  20. javascript 获取汉字笔画拼音,使用笔画排序

热门文章

  1. 索引聚焦如何使 SQL Server高效 -- 设计(ITPUT 讨论汇总)
  2. 中国天气网接口类(中国天气预报)
  3. 电路实验一阶电路误差分析_逆变器电路原理分析,以及各种逆变器控制电路!...
  4. 称重传感器的应用(HX711)
  5. 【设计篇】36 # 如何理解可视化设计原则?
  6. 【算法应该怎么“玩” - 王晓华】计算机对于不等式的判断逻辑
  7. 浙江省计算机英语三级,关于2020年下半年浙江省高校计算机和大学外语(CET3)等级考试报名的通知...
  8. 阿里云服务器Centos/tomcat6 配置http/https证书访问
  9. 新东方百万年薪招聘私域运营,实在智能RPA数字员工以一抵百
  10. Unity3dRPG 相机跟随player旋转_轻松记录美好生活——橙影智能摄影机M1众测报告_相机配件...