JWT

JWT

json web token,一种json数据传输的安全认证机制

分为三部分,header、payload、signature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
//header,签名算法,JWT的类型
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
对应:
{
"alg": "HS256",
"typ": "JWT"
}
//payload,传输的主要信息
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
对应:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
//signature,使用指定算法对Header和Payload进行签名生成
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
对应:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),

your-256-bit-secret

)

JWT 中的每一部分都是经过Base64编码的,所以可以Base64解码

流程

和一般token差不多吧

  1. 客户端将登录信息传送给服务器
  2. 服务器用私钥对用户信息加密成JWT,返回给客户端
  3. 客户端之后的每次请求,都携带JWT,供服务端检验和认证
  4. 服务端收到JWT,用公钥解密,对用户信息进行检验和认证
  5. 服务器响应给客户端,客户端有对应的响应

漏洞利用

签名未校验

目的:修改会话令牌以访问位于/admin的管理面板然后删除用户carlos

如果已知一个用户的账号和密码,登录进去,我们捕捉一下包

获取如下数据

1
Cookie: session=eyJraWQiOiI4ZmFiNjY4Ni02MmU2LTQyOTItYWFkMy1mZTk1Y2EwMjVhN2YiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY5NzU5OTMxNH0.Y_kO3WYAZQ7PiUxOiojCxeNkjW88NL-abM36qGU2lspHymMM7NrBVILMG4dvUV-XE6ZNqF-s0NSLDweuFDysXgV_h3BJe-s4-Kv9F5JWK48MV6Q-j2302sHfrMEAsh3tUrGQubJCi5q-0F2--tquNDD-4ZKCZ_qqC0J8yTWeJfjbBJEdXrmUa4eQcPlc73B9cdoJx-BE4f33i6wM9b_LOYtyRlMISm5L0gzEYLpFZnwSqZeEQ0JN7kVda3zfJLB-C0QznKG4Q-ZkjeQ5oRuLsos7ZHrB_lP5BtrSWW7Eli78Rm4nzUIWWI6FTbTP5uNfE0MIVHsfsku4OxOjDYyiCA

去解析JWT后,可以发现,payload部分内容

1
2
3
4
5
6
{
"iss": "portswigger",
"sub": "wiener", //更改为administrator
"exp": 1697599314
}

base64加密处理一下后,替换payload

eyJpc3MiOiAicG9ydHN3aWdnZXIiLCJzdWIiOiAiYWRtaW5pc3RyYXRvciIsImV4cCI6IDE2OTc1OTkzMTR9

进入admin面板

按题目要求访问 /admin 路径

我在浏览器进行访问时,还是提示仅administrator用户访问

Admin interface only available if logged in as an administrator

那只能继续在bp中访问

访问成功

delete carlos用户

跳转

总结

利用的漏洞原理是,因为JWT库会有验证(签名)方法和解码方法,如果开发人员的疏忽,只将JWT传进了解码方法,而没有用验证方法,那就可以绕过了

签名None

登录后,捕捉header部分

1
2
3
4
5
6
7
8
9
10
11
{
"kid": "48dbebfc-97c1-4f42-b1fa-b9232e598747",
"alg": "RS256" //替换为none
}

After:

{
"kid": "48dbebfc-97c1-4f42-b1fa-b9232e598747",
"alg": "none"
}

ewogICJraWQiOiAiNDhkYmViZmMtOTdjMS00ZjQyLWIxZmEtYjkyMzJlNTk4NzQ3IiwKICAiYWxnIjogIm5vbmUiCn0=

再编译替换header部分(=替换为%3d),同时替换payload部分(与上一个漏洞步骤一样),删除后面的签名部分

302,说明有戏

再把路径改为 /admin ,go

401未授权 !!!!!!!

emmm

将header部分改一下,再base64

eyJraWQiOiAiNDhkYmViZmMtOTdjMS00ZjQyLWIxZmEtYjkyMzJlNTk4NzQ3IiwKImFsZyI6ICJub25lIn0=

注意小数点不要丢

再试一次

访问/admin

删除carlos

总结

当对header部分的alg为none时,意味着不签名,导致了任何token都是有效的,一般是开发者为了调试设置的,因为疏忽没有关闭这个功能导致漏洞

密钥暴力猜解

一般加密密钥为对称密钥和非对称密钥

对称:双方都知道这个密钥,是同一种密钥

非对称:接收方有私钥,发送方有公钥

然后前面已经说过,signature是对header和payload的签名

用hashcat进行破解(渗透中用来破解哈希的一种工具)

首先我们有一个字典,这些字典都是一些已知的密钥,比如!FWER!@#@!之类的

hashcat遍历这字典里的每一个密钥,对JWT的header和payload进行签名,将结果签名与服务器的原始签名进行比较,匹配的话,说明破解成功。

比如密钥为 **114514!!!**,知道了密钥

重新构造一下payload,将name改为administrator,然后用 这个密钥对header和payload进行哈希即可,到时候就得到第三部分的签名

base64 to json

总结

如果开发者对签名进行了校验。尝试使用一些默认的、简单常见的密钥进行爆破,从而获得真正的密钥,进而伪造一个高权限账户。

JWT头部注入

场景1

在实际场景中,header有更多的参数,比如有jwk,提供一个代表密钥的嵌入式JSON对象

该参数以jwk格式将其公钥直接嵌入令牌本身

理想情况下服务器应该只使用有限的公钥白名单来验证JWT签名,然而错误配置的服务器有时会使用jwk参数中嵌入的键值,攻击者可以通过使用自己的RSA私钥对修改后的JWT进行签名,然后在jwk头中嵌入匹配的公钥来利用这种行为

bp有一个拓展叫 JWT Editor,2023年的版本,用该工具生成自己的RSA私钥,嵌入进去,达到越权的目的

场景2

有些服务器使用jku(jwk set url)引用包含密钥的JWK集,而不直接使用JWK头参数嵌入公钥,当验证签名时,服务器从这个URL获取相关的密钥,这里的JWK集其实是一个JSON对象

场景3

kid header path traversal

服务器如果使用几个密钥来签署不同类型的数据的话,会有kid这种参数,帮助服务器验证签名时使用对应的密钥。这个kid可能是数字,文件名称,或者路径

比如

1
2
3
4
5
6
{
"kid": "../../path/to/file",
"typ": "JWT",
"alg": "HS256",
"k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}

如果服务器支持对称算法的话,那攻击者完全可以将kid指向一个知晓的静态文件,

使用与该文件内容匹配的密钥对JWT签名。

最简单的方法之一是使用**/dev/null**,这是一个空文件,读取它将返回一个空字符串,因此用空字符串对令牌进行签名将会产生有效的签名

所以做法:

先jwt editor生成一个对称密钥,这个密钥的值为null(AA==)

1
2
3
4
5
{
"kty": "oct", //密钥类型oct
"kid": "38576880-33b7-4446-ade4-f1a78bb6d5c2", //对应id
"k": "AA==" //密钥值为null
}

从而构造的header中,kid为 ../../../../../../../dev/null

payload中sub 改为 administrator

用jwt editor对header和payload用oct签名,得到最终的JWT

JWT算法混淆

攻击者可以用不同于服务器预期的算法去验证JWT的签名。

如果后端上,总是传递一个 固定的公钥 给验证签名的方法。

然后服务器会通过映射到/jwks.json或/.well-known/jwks.json的端点将它们的公钥公开为JSON Web Key(JWK)对象,攻击者通过访问/jwks.json去获取服务器公钥信息

将公钥转换为合适的格式,创建恶意JWT,签名,达到攻击效果

令牌派生公钥

https://xz.aliyun.com/t/12906#toc-5

敏感信息泄露

一般是攻击者抓到了JWT敏感信息,比如一个完整的JWT,然后攻击者base64解码,得到了里面的用户名,还有密码,密码可能还要进一步哈希解码。最终达到登录的目的。

参考网址

https://xz.aliyun.com/t/12906#toc-5

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 是羽泪云诶
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信