0%

第80天-身份验证篇&JWT令牌&空密钥&未签名&密钥爆破&JWK&JWU&KID&算法替换

演示案例:

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

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

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

一、JWT介绍

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

1、JWT识别

1、标头(Header)

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

alg字段通常用于表示加密采用的算法。如”HS256”、”RS256”等

typ字段通常用于表示类型

还有一些其他可选参数,如”kid”、”jku”、”jwk”等

2、有效载荷(Payload)

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

iss:该字段表示jwt的签发者。

sub:该jwt面向的用户。

aud:jwt的接收方。

exp:jwt的过期时间,通常来说是一个时间戳。

iat:jwt的签发时间,常来说是一个时间戳。

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

3、签名(Signature)

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

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

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

后端就是通过第三部分来验证身份的,重新做一遍加密运算然后和第三部分进行对比,一样通过,反之不通过。

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

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

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

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

HS256:对称性加密(同一的密钥加密和解密) 可以采用爆破密钥攻击

RS256:非对称性加密(公钥和私钥,私钥解密或加密,公钥加密或解密)

二、识别检测利用项目:

BURP插件:Hae&JSON Web Tokens解jwt&JWT Editor生成密钥

https://jwt.io/

https://github.com/z-bool/Venom-JWT

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

https://github.com/wallarm/jwt-secrets

https://github.com/CompassSecurity/jwt-scanner

三、实验

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

1、实验室:通过未验证的签名绕过JWT身份验证

按照给的账号密码登进去就能看到身份验证使用了jwt,但是这关后端是没有校验签名而是直接看payload里的值,所以我们直接sub的值改成administrator即可越权访问/admin。

2、实验室:通过有缺陷的签名验证绕过JWT身份验证

这个就是后端没写死算法,而是看alg的值来用对应算法,所以直接算法置空,也没有验证签名了,直接看payload值

3、实验室:通过弱签名密钥绕过JWT身份验证

这个用上面的方法不行,但是观察到用的是SH256对称加密,那么就尝试密钥爆破,使用jwt-tool。

因为密钥是弱密钥所以可以爆破,爆破后那就随便搞了。

4、实验室:通过jwk标头注入绕过JWT身份验证

位置:JWT Header 头部字段,多用于 RS256 非对称验签,作用是给服务端提供验签公钥, 直接将公钥嵌入 JWT 头部。我们在jwt-editor新建一个rsa密钥,私钥保存在bp的缓存中,公钥插件把它转换成jwk格式,放到header中,用我们自己的私钥签发,公钥验签当然能绕过了!

5、实验室:通过jku标头注入绕过JWT身份验证

JWT Header 头部字段,多用于 RS256 非对称验签,作用是给服务端提供验签公钥, 存放 JWKS 密钥集的 URL 地址。这个和上面一个是一样的,只是从远程加载公钥而已。一样的操作,创建rsa密钥,然后复制到远程服务器,然后header加jku后面跟url,然后即可

6、实验室:通过kid头路径遍历绕过JWT身份验证

kid值就是密钥的一个编号,因为可能不用业务用的签发密钥不同,验签的时候也要用对应密钥,只针对对称算法。后端没写死密钥,而是把kid值作为路径了。目录穿越去访问dev/null这是一个空文件,所以签发验签都是空密钥就绕过了。

7、算法混淆

1、ctfshow-Web349(公钥私钥泄露)

这个就是私钥泄露了,写个脚本去把user值改了

pip install PyJWT==1.7.1

import jwt

public=open(‘private.key’,’r’).read()

payload={“user”:”admin”}

print(jwt.encode(payload, key=public, algorithm=’RS256’))

2、ctfshow-Web350(密钥混淆攻击RS256=>HS256)

这个和上面的空密钥绕过很像,都是后端没有写死算法。这里就是它这次没有泄露私钥,我们无法伪造jwt,但是我们可以改成HS256对称加密,加密解密都是一个密钥,所以全程不用获得密钥就能伪造。

将RS256算法改为HS256(非对称密码算法=>对称密码算法)

HS256算法使用密钥为所有消息进行签名和验证。

而RS256算法则使用私钥对消息进行签名并使用公钥进行身份验证。

var jwt =require(‘jsonwebtoken’);

var fs =require(‘fs’);

var privateKey = fs.readFileSync(‘./public.key’);

var token = jwt.sign({ user:’admin’}, privateKey,{ algorithm:’HS256’});

console.log(token)

8、某个测试目标

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

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjo0MDcyNjE1MzE0fQ.mwI2P1j8CIvhxBKFvcyU7TNLBeuFtiUM1mPrKanF1w4

Content-Type: application/x-www-form-urlencoded

db=sample&q=show users

复盘:

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

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

1)未授权访问:删除Token后仍然可以正常响应对应页面

2)敏感信息泄露:通过JWt.io解密出Payload后查看其中是否包含敏感信息,如弱加密的密码等

3)破解密钥+越权访问:通过JWT.io解密出Payload部分内容,通过空加密算法或密钥爆破等方式实现重新签发Token并修改Payload部分内容,重放请求包,观察响应包是否能够越权查看其他用户资料

4)检查Token时效性:解密查看payload中是否有exp字段键值对(Token过期时间),等待过期时间后再次使用该Token发送请求,若正常响应则存在Token不过期

5)通过页面回显进行探测:如修改Payload中键值对后页面报错信息是否存在注入,payload中kid字段的目录遍历问题与sql注入问题