草庐IT

JWT安全漏洞以及常见攻击方式

烟雨醉沉浮 2023-08-16 原文

前言

随着web应用的日渐复杂化,某些场景下,仅使用Cookie、Session等常见的身份鉴别方式无法满足业务的需要,JWT也就应运而生,JWT可以有效的解决分布式场景下的身份鉴别问题,并且会规避掉一些安全问题,如CORS跨域漏洞,CSRF漏洞等。

JWT简介

JWT即Json Web Token的缩写,顾名思义,是Token的一种。它常被用来在向服务器发起请求时用作身份认证。使用JWT作为身份认证的优势在于:它不需要在服务端去保留用户的认证信息。仅需要对该Token正确性进行校验即可,这就意味着基于token认证机制的应用,不需要去考虑用户在哪一台服务器登录了,为应用的扩展提供了便利。

新技术带来便利的同时也会带来新的安全问题,如果JWT本身安全存在问题,那么整个身份认证机制就会得不到保障。

JWT由三部分组成,类似于xxx.yyy.zzz,前两部分是base64编码的内容,第三部分是加密的签名部分

  1. 第一部分被称为header,会说明字符串的类型以及加密方式,当然还会包含其他一些字段,在介绍JWT安全问题时会涉及到部分。

  2. 第二部分被称为payload,包含用户的身份id,是否是管理权限等字段,这部分中的相关字段可以根据实际情况自行定义。

  3. 第三部分是加密部分,对前面的“xxx.yyy”用头部中声明的加密方法进行加密,保证JWT的完整性。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWT常见安全问题

JWT相关CVE漏洞

下面是JWT相关的一些CVE漏洞

(CVE-2015-2951) alg=none签名绕过漏洞
(CVE-2016-10555) RS/HS256公钥不匹配漏洞
(CVE-2018-0114)密钥注入漏洞
(CVE-2019-20933/CVE-2020-28637)空白密码漏洞
(CVE-2020-28042)空签名漏洞

弱签名算法(无算法)

更改头部中声明的加密算法

例如将下面的HS256更改为none,可以只篡改前两部分,而不改变第三部分签名的情况下进行绕过,或者删除第三部分,但是记得保留“.” 这个符号,以保证符合JWT的格式

存在这种漏洞一般是第三方JWT库存在问题,或者是代码编写错误,生成JWT的代码中使用了none,如下所示

弱密码

如果JWT使用HS系列(对称加密)的加密方法,而且使用较为简单的Key进行加密,那么使用工具就极有可能能够得到key,之后就可以随意的篡改JWT了。

常用的工具

1.jwt_tool
2.hashcat

使用工具破解下面的JWT

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.dQknU80__AHPVDmZPFavWdML1XKrVYPLeOXNMo

利用kid标头

在JWT的头部中,除了存在typ 以及alg之外,还可以存在其他内容。KID 标头是一个密钥标识符。kid是RFC标准中用来表示密钥存储位置的地方,服务端可以根据这个提示来寻找解密密钥。
根据代码的编写情况,可能存在以下问题

  1. SQL注入
  2. 目录遍历
  3. 命令执行

SQL注入

这种情况是密钥存储在数据库中,使用kid字段查询相关内容,代码如下所示

目录遍历

kid的值表示的是密钥存储的文件,通过构造payload,就可能会造成目录遍历漏洞

命令执行

kid的值会被带入到要执行的命令之后,代码如下所示

利用JKU标头

jku头是用来获取jwks(json web keys)文件的,这是一个json文件,用来指定获取密钥。我们可以简单地托管我们自己的 JWKS 文件并将他的 jku 指向我们的服务器。

出现此问题的主要原因是应用程序必须解码令牌并使用它来获取 jwks,以便它可以构建公钥并验证令牌。

因此,如果应用程序在没有任何验证的情况下简单地信任 jku,那么这可能会被滥用。

jwks 文件的格式

利用步骤如下

  1. 创建公私密钥对
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
  1. 创建我的jwk 文件,通过在线工具 https://russelldavies.github.io/jwk-creator/ ,

public Key Use 选择 sigining,
Algorithm 选择JWT头部中声明的算法
Key id与 头部中声明的一致
然后将生成的公钥的值粘贴框中

  1. 修改并保存JWKS文件,根据原来JWKS文件中的kid的值,替换对应的部分,用生成jwk替换掉原来的部分,然后就可以篡改JKU头指向我们托管的服务器,以及payload中对应的值,然后进行利用公钥签名,向服务器发送我们构造的JWT即可,可以使用在线工具jwt.io,或者python以及java代码利用私钥生成篡改的JWT。

易受攻击代码示例

利用 X5C 标头

x5c 标头包含可用于验证JWT的 x509certificate/x509certificate 链。正常流程是提取证书中的公钥,然后验证JWT,如果信任x5c中的值,而不进行验证,那么我们可以生成自己的证书和然后用私钥签名篡改后的内容即可。

攻击流程

  1. 创建证书并提取公私密钥
openssl req -x509 -nodes -days -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem

2.篡改令牌并用您的 x509 证书代替 x5c 声明。

3.修改token,用私钥签名。

易受攻击代码示例

利用X5U标头

x5u标头的问题与juk的问题一致,只不过是地址指向的是存储证书的位置,它用于从 Web 服务器获取 x5c 证书,该证书将用于从中创建公钥并验证令牌。

利用流程

  1. 创建证书和公私 rsa 密钥对
openssl req -x509 -nodes -days -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem

2.托管证书

3.篡改token并用私钥签名

易受攻击代码示例

其他

exp标头

除了上面的问题,如果头部中没有exp标头声明JWT的过期时间,那也是存在风险的,一旦获得该令牌,那么就可以重复使用。

跨服务中继攻击

三个组件,下面两个可以会向用户发送JWT令牌,然后令牌服务在签发令牌时不进行必要的验证,那么可能两个应用在具有相同的用户名时,签发相同的令牌,那么就可以替代其他用户登录到另外一个应用中。

实验部分

https://portswigger.net/web-security/all-labs

未验证签名

成功登录后,可以看到获得的Cookie内容就是JWT格式的,

eyJraWQiOiJhZThiOTNhMC01ZWJjLTQzZWYtOWY3My04ODVmMzY1NzdjZWEiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY3NjU1NjMxOX0.LM-PYrwNfxoSYvh13Fx4iWP46dYNPhNrq_X1PbVH4JBdtAwolKEIu5ICe_XLUI668CKgwTrlcLzQq8g7gsVvyAttwJKpdfICI-Mncn1CRx6vkxBPxrYhOniRR9G3b_dSwWuuyrpHPV2Zncl8_6wrRO1lB5Yd0zO4TZhATv5hq60iO8F75kRSyD8WnllvNOJVUtTPatmdkq-G8R-bJ0PPlhsXzCXRuWKOlkKl5nyE_aF-tiCAryK6cN_u5pQlc4fYtPds6fnxrPtp7fKPFHCoUSUG7HaA48WqGF603uiKdtLbtia0eEwtSjfT_Wk15Blau4wcGwzCnHeF4Tp2SxWSpA

因为该问题是程序不会对签名部分进行任何验证,因此直接修改payload部分,然后任意输入私钥生成JWT即可

再次构造payload

访问成功,之后可以发现删除用的URL,成功删除用户。

无算法漏洞

  1. 登录后获得Cookie中的JWT
  2. 然后将头部中的alg更改 none,payload中的用户名替换为administrator,base64编码后替换原来的部分,然后删除签名部分,记得保留点号,保证格式正确,然后就按照第一个实验中的步骤删除用户即可。

使用弱密钥加密

  1. 成功登录获得到JWT后进行解码查看,可以看到JWT使用的HS256,这个是对称加密算法,存在使用所密钥的该路,可以使用jwt_tool,等工具尝试对密钥进行猜解。

  2. 破解的密钥结果为secret1,那我们就可以对JWT进行篡改了。

  3. 使用jwt.io网站生成JWT,然后按照上面两个实验的步骤删除用户即可。

JWK标头注入

安装bp扩展 JWT Editor,然后使用JWT Editor Keys生成RSA密钥对,点击确认

在JSON Web Token选项卡 的底部,单击Attack,然后选择Embedded JWK。出现提示时,选择您新生成的 RSA 密钥并单击确定。

jku标头注入

  1. 使用扩展生成RSA密钥并保存,然后选择Copy Public Key as JWK,并按照JWKS文件的格式保存到攻击者的服务器。

  2. 添加jku头,值为对应jwks文件对应的url

  3. 将生成的kid替换原来的kid,用来标识用户的用户名,然后选择对应的密钥进行签名,之后不走与上面的实验一致。

利用kid标头绕过

上面的知识部分有讲过kid是用来帮助寻找密钥的,有一种情况就是保存在指定路径的某个文件中,文件名是kid的值。

攻击这个靶场时,我用windows上面的burp怎么样都没办法进行签名,怀疑时burp版本问题,换了个版本也不行,打开虚拟用kali里面的burpSuit,就成功了。

  1. 首先修改kid的值,为…/…/…/…/…/…/dev/null,然后将sub修改为administrator。

2.生成密钥,然后保存,记得将k的值修改为AA==,其实也就是空,

混淆算法

这个漏洞应该是在程序中没有指明算法导致的问题。

1.首先访问jwks.json文件,将keys的值,也就是框起来的部分,粘贴出来

2.然后使用JWT Editor的插件,生成RSA密钥,选择生成JWT的,生成之后,将上面的值替换掉里面的内容,然后点击确定,保存

3.然后对保存的密钥右键,copy as public pem,去进行base64的加密。然后选择生对称加密的密钥,将加密后的值替换到k中,然后保存

4.然后,将加密算法更改为HS256,用户名标识改为administrator,然后就有管理员权限了,之后的步骤就是删除用户,没什么好写的。

参考

https://www.freebuf.com/articles/web/303200.html
https://www.jianshu.com/p/576dbf44b2ae
https://zhuanlan.zhihu.com/p/86937325
https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3
https://systemweakness.com/hacking-jwt-d29f39e202d5
https://lazyhacker.medium.com/jwt-vulnerabilities-list-simple-explanation-134c4dcc5e61

有关JWT安全漏洞以及常见攻击方式的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  6. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. Tomcat AJP 文件包含漏洞(CVE-2020-1938) - 2

    目录1.漏洞简介2、AJP13协议介绍Tomcat主要有两大功能:3.Tomcat远程文件包含漏洞分析4.漏洞复现 5、漏洞分析6.RCE实现的原理1.漏洞简介2020年2月20日,公开CNVD的漏洞公告中发现ApacheTomcat文件包含漏洞(CVE-2020-1938)。ApacheTomcat是Apache开源组织开发的用于处理HTTP服务的项目。ApacheTomcat服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件。该漏洞是一个单独的文件包含漏洞,依赖于Tomcat的AJP(定向包协议)。AJP自身存在一定缺陷,导致存在可控

  9. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  10. 阿里云国际版免费试用:如何注册以及注意事项 - 2

    作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。​关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐

随机推荐