赞
踩
靶场链接及官方资料:https://portswigger.net/web-security/jwt
JWT
是token
的一种实现,全称为 JSON Web Token
。以形式来说,它就是一个字符串,将用户的信息保存在一个json
字符串中,编码后得到的一个token
,这个token
有签名功能防篡改
认证流程:
post提交表单后,后端验证完成生成一个jwt,接下来返回该jwt至客户端,随后请求中带上该jwt,即可工作。
传统cookie
、session
对比:
1、JWT数据量小,传输速度快
2、由于是json,JWT是跨语言的,应用广
3、更适用于移动端,因为它们不支持cookie
4、避免csrf,因为不依赖cookie
5、作为请求头可以跨域工作
JWT
结构
由Header、Payload、Signature组成
JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
Header
{
"alg": "HS256", #签名算法 HMAC SHA256
"typ": "JWT" #统一为JWT
}
Payload
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
#自定义即可
Signature
仅单向验证是否被篡改,摘要算法。
比较关键的一点在于,签名的密钥存储在服务器中,一般情况下无法重新签名
尝试生成一个可跳转 https://jwt.io/
。
更多JWT详情 https://blog.csdn.net/weixin_45070175/article/details/118559272
。
为了更好的对JWT
进行分析和编辑,可以在bp
商店中下载JWT Editor
JWT
库通常提供一种验证令牌的方法和另一种仅对它们进行解码的方法。例如,Node.js
库jsonwebtoken
具有verify()
和decode()
.
有时,开发人员会混淆这两种方法,只将传入的令牌传递给该decode(
)方法。这实际上意味着应用程序根本不验证签名。
靶场登录账户密码:winner
peter
在bp
中直接双击JWT
可以直接以句号分隔,在右边的inspector
选项卡中会自动对它进行解码,不过并不支持一起全部解码,只能一段一段的查看。
这里可以明显看到解码后的结果有一个wiener
的用户名
将其修改为administrator
,重新发出请求,即可以administrator
的身份登录
请求敏感链接
完成题目要求
在Header
中,设置alg
的值可以选择签名方式,就像前面的介绍,可以选择HS256
,即HMAC
和SHA256
。在某些情况下可以设置为None
,即不签名,但是一般都会过滤这种危险的设置,实战中较少,可以尝试大小写等等绕过。
不能直接请求管理页面
设置sub
参数为administrator
,和上面一样
更改alg
参数为none
再次请求成功
请求敏感链接成功
通过弱签名绕过JWT
身份认证。虽然签名含密钥且为单向,但是如果使用的弱密钥,是可以用相应的工具来完成破解
这里使用的是hashcat,进行破解,使用语句如下:
hashcat -a 0 -m 16500 <jwt> <wordlist>
因为是单向,需要字典来爆破,建议在github
上找找,这里我使用的是:
https://github.com/wallarm/jwt-secrets
爆破成功,得到弱密钥,secret1
base64
编码
在JWT Editor
中产生对称密钥对,设置k
值为你密钥的base64
值
理论上来说,可以使用这个插件直接更改密钥,重新签名,不过我暂时没用起。你也可以在网页端,重新设置密钥,在这个下面我写上了secret1
。复制这个重新产生的字符串就可以了
绕过认证成功
通过 jwk
标头注入绕过 JWT
身份验证。在Header
中可以插入一些其他头。
JSON Web
签名 (JWS
) 规范描述了一个可选的jwk
标头参数,服务器可以使用该参数以 JWK
格式将其公钥直接嵌入到令牌本身中。
首先在插件中产生RSA Key
,选择RSA
选项,点击生成即可
在repeater
中改到JWT
编辑界面,选择下面的嵌入JWK
进行攻击
选择你产生的RSA
密钥对
嵌入成功,更改sub
参数为administrator
请求敏感链接成功
某些服务器不是直接使用 header
参数嵌入公钥,而是jwk
允许您使用jku
(JWK Set URL) header 参数来引用包含密钥的 JWK Set
。验证签名时,服务器从该 URL
获取相关密钥。
这也是header
中的另一个头,和上一个不同的是它是远程请求得到密钥对后工作。
和上面相同的方法产生RSA
密钥对,然后复制公钥作为JWK
捕捉到受JWT
攻击的包
使用攻击服务器,在像这样输入你的JWK
{ "keys": [ { "kty": "RSA", "e": "AQAB", "kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab", "n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ" }, { "kty": "RSA", "e": "AQAB", "kid": "d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA", "n": "fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw" } ] }
浏览请求网页如下
手动插入jku
头,带上url
,并更改sub
为administrator
,注意需要重新签名一下,点一下sign
即可
请求敏感链接成功
服务器可以使用多个加密密钥来签署不同类型的数据,而不仅仅是 JWT。出于这个原因,JWT 的头部可能包含一个kid(Key ID)参数,该参数帮助服务器在验证签名时识别使用哪个密钥。
验证密钥通常存储为 JWK 集。在这种情况下,服务器可以简单地查找与kid令牌相同的 JWK。但是,JWS 规范没有为此 ID 定义具体的结构 - 它只是开发人员选择的任意字符串。例如,他们可能使用kid参数来指向数据库中的特定条目,甚至是文件的名称。
如果此参数也容易受到目录遍历的影响,则攻击者可能会强制服务器使用其文件系统中的任意文件作为验证密钥。
如果服务器还支持使用对称算法签名的 JWT
,这尤其危险。在这种情况下,攻击者可能会将kid
参数指向一个可预测的静态文件,然后使用与该文件内容匹配的密钥对 JWT
进行签名。
从理论上讲,您可以对任何文件执行此操作,但最简单的方法之一是使用/dev/null
,它存在于大多数 Linux
系统上。由于这是一个空文件,因此获取它会返回 null
。因此,使用 Base64
编码的空字节对令牌进行签名将产生有效的签名。
首先捕捉易受攻击的数据包
直接请求admin
路径是不行的
这里尝试对称密钥对,使用的k
就为 null
的base64
编码,也就是“AA==”
当然,你仍然可以和前面一样,在网页中直接输入密钥值,产生一个新的JWT
。kid
参数使用路径穿越定位到空文件,然后输入密钥,记得勾选secret base64 encoded
复制该值,即可完成访问
访问敏感链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。