(关于JWT kid安全部分后期整理完毕再进行更新~2023.05.16)

JWT的原理、渗透与防御

目录

  • JWT的原理、渗透与防御
    • 含义
    • 原理
      • JWT的起源
      • 传统session认证问题
      • token与session区别
      • JWT的结构与内容
    • JWT的攻击和渗透
      • 敏感信息泄露
      • 空密钥破解
      • 密钥爆破
      • CVE-2019-7644
    • JWT防御

含义

JWT全称为Json web token,是为了在网络应用环境间传递声明而执行的一中基于JSON的开放标准。常用于分布式站点的单点登录。
JWT的声明一般被用在客户端与服务端之间传递身份认证信息,便于向服务端请求资源。

(我理解就是token验证的一种数据格式)

原理

  1. 客户端提交用户名密码等信息到服务端请求登录,服务端在验证通过后前发一个具有时效性的token,将token返回给客户端

  2. 客户端收到token后会将token存储在cookie或localStorage中

  3. 随后客户端每次请求都会携带这个token,服务端收到请求后校验该token并在验证通过后返回对应资源

JWT的起源

有需求必然有其存在的道理,关于JWT的出现要先理解一下什么是传统session认证。
session认证
解决http协议本身并不能记录状态问题,session在每一次会话开始时产生,用于存放会话信息,每个session以键值对的方式生成(session_id=session),将session_id以cookie的形式(set-cookie)返回给客户端,客户端再次请求时携带session_id,服务端根据session_id使用对应的session作为认证信息为客户端响应对应服务。

听起来好像和JWT的原理差不多?不都是每一次会话的身份信息服务端发给客户端,存储在cookie当中,只是存储格式的差异么,一个是键值对,一个是json(严谨来说json也是键值对)。不急,继续往下读。

传统session认证问题

  • 服务端开销问题:由于认证信息存储在服务端,当认证用户量增加时,服务端开销会明显增大。
  • 扩展性不佳:由于存储在服务器端,意味着后续的请求也必须是在同一台服务器上才能响应对应资源,对于分布式应用,限制了负载均衡的能力以及应用扩展能力。
  • CSRF攻击:由于存储在浏览器cookie中,CSRF攻击时,网站校验浏览器中cookie后会认为时用户本人操作。

token与session区别

由上面的原理来看其实两者是十分类似的,但实际上,session的认证信息是存储在服务端,客户端的session_id仅仅是session的标识符,而token本身就是携带认证信息的。而且由于token是可以通过一定的手段在请求时与cookie分离独立出一个首部字段,故token是可以防御csrf攻击的。其二token机制服务端是不存储相关认证信息的,只是对token做解密并根据解密信息查询用户信息,故对于服务端的开销更小,也更利于分布式服务器应用的扩展。

由此可以总结出来,JWT的优点,或者说相比session,token的优点主要有下面两点:

  • 能存储更多认证信息,为服务器减轻负担。
  • 可以与cookie分离出来,单独一个首部字段,防御csrf攻击。

JWT的结构与内容

结构:一般是一段eyJ开头,由英文点分割开的三段字符

三段字符串分别对应:

  1. Header:加密算法与Token类型;
    对应部分:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
  2. Payload:用户信息和附加信息的声明,一般是Json类型的键值对;
    对应部分:eyJsZXZlbCI6ImFkbWluIiwicGFzc3dvcmQiOiIyYWM5Y2I3ZGMwMmIzYzAwODNlYjcwODk4ZTU0OWI2MyIsInVzZXJuYW1lIjoiam9lIn0
  3. Signature:
    ①base64编码后的Header
    ②base64编码后的Payload
    ③签名加密算法私钥。
    对应部分:6j3NrK-0C7K8gmaWeB9CCyZuQKfvVEAl4KhitRN2p5k
    通过base64解码或者通过https://jwt.io/来专门处理JWT结构。

JWT的攻击和渗透

当你在请求包中发现JWT格式的token时,有以下几种渗透思路:

  1. 未授权访问:删除Token后仍然可以正常响应对应页面
  2. 敏感信息泄露:通过JWt.io解密出Payload后查看其中是否包含敏感信息,如弱加密的密码等
  3. 破解密钥+越权访问:通过JWT.io解密出Payload部分内容,通过空加密算法或密钥爆破等方式实现重新签发Token并修改Payload部分内容,重放请求包,观察响应包是否能够越权查看其他用户资料
  4. 检查Token时效性:解密查看payload中是否有exp字段键值对(Token过期时间),等待过期时间后再次使用该Token发送请求,若正常响应则存在Token不过期
  5. 通过页面回显进行探测:如修改Payload中键值对后页面报错信息是否存在注入,payload中kid字段的目录遍历问题与sql注入问题

敏感信息泄露

JWT渗透测试站点:https://authlab.digi.ninja/Leaky_JWT

机翻:带签名的JMTs看起来像是机密数据,但很容易解码。当开发人员将这些放在一起时,他们只是将整个用户对象从数据库中提取出来,并将其放入令牌中,而不是只包含所需的信息。
你已经从你的受害者的本地存储器中获得了下面的令牌,解码它并使用下面的信息登录。
利用jwt.io对token进行解密,解密后的payload部分包含了类似MD5加密的密码,用MD5碰撞解密出弱口令Password1


登录成功,welcome Joe~

空密钥破解

测试地址:https://authlab.digi.ninja/JWT_None

机翻:除了允许对JWT签名使用HMAC和RSA散列算法之外,一些解析器还允许通过指定“none”来禁用散列。我从来没有在野外遇到过这种情况,但有一些活跃的库支持它所以我总是检查它以防万一,特别是当你偶尔听到它突然出现的报告,有时在最糟糕的地方!2020年4月,研究人员发现Autho容易受到这种攻击,并在博客文章中写道:Auth0身份验证API中的JSON Web令牌验证绕过。(就是说应用空密钥的情况是极少的,除非在一些应用组件中启用,所以看到的话还是测一下这个功能。)
这次要用到工具进行改包,BP上先下载一个名为“JSON Web Token Attacker”的工具,方便后续进行JWT渗透测试。下载完成后页面点击“Validate Token”抓包。

当请求中出现JWT格式内容时,BP会出现高亮提示,对改包进行重放看响应的信息,就是登录的用户信息。


如果随意对JWT payload进行修改,会被服务器拒绝。

如果修改不正确的加密方法,也会被服务器拒绝。

点开扩展插件JWS,payload中level修改为admin,修改用户名rdrug,点击Attacker,选择none payload进行测试,最后测试加密方式为None时,请求成功,利用空加密方式实现账户越权。

密钥爆破

测试地址:https://authlab.digi.ninja/JWT_Cracking

重要部分机翻:当使用HMAC生成签名时,生成签名的函数需要一个密钥。如果你能以某种方式获得该密钥,无论是从服务器上窃取、猜测还是强行使用,那么你就可以签署自己的令牌,在大多数情况下,这意味着你可以对有效负载及其包含的声明进行任何修改。

爆破工具:c-jwt-cracker、hashcat等

爆破原理:将header和payload部分用base64解码后,利用字典作为密钥进行加密与第三部分的SIGNATURE进行对比。

  • hashcat
    命令.\hashcat.exe -m 16500 -a 0 hash.txt FastPwds.txt
    hash.txt存放hash文本,FastPwds.txt存放字典文本。(hashcat的其他具体参数和使用方法这边请:https://blog.csdn.net/Samuel677/article/details/118875875)

  • c-jwt-cracker
    命令./jwtcrack (jwt-hash)

    安装过程的坑:因为工具是c写的,在第一次编译这个工具的时候可能会报错

    这时候需要
apt-get install libssl-dev

安装ssl扩展库。
如果回显找不到库的时候,先执行:

sudo apt-get update

快速检测依赖,并自动安装相关依赖。
再make进行编译,成功后会生成bin文件jwtcrack

从破解的密钥为”hello”后在jwy.io,使用获得的密钥重新签发token并修改Payload。

将生成的jwt重新发给服务端,验证通过。

CVE-2019-7644

测试链接:https://authlab.digi.ninja/Auth1

当篡改payload时,报错回显泄露正确的signature。攻击者可以伪造令牌以绕过身份验证和授权机制。
修改payload中的用户level后,将jwt发给服务器。回显中会暴露signature正确的值。

FO8ZDKSDNVnt_VB3f35_ofEMGFDTrv0dVo8hjGXDtn8替换3NdjwjYHnZz-tSsvXWeYedYzIiJpAlc0-wQgMjjnZq8,重新请求。
登录成功。

JWT防御

  1. 禁用空密钥算法。
  2. 编写一个方案以防万一密钥泄露。
  3. 不设置弱密钥,并密钥将密钥放在安全的地方
  4. 不允许发送方设置任意签名算法。
  5. 不在负载中放置敏感信息。
  6. 确保令牌的有效期足够短。
  7. 确保免受重放攻击。
  8. 避免在URL中发送令牌。

参考链接:
https://blog.csdn.net/cdyunaq/article/details/122561096
https://blog.csdn.net/qq_53079406/article/details/124458006