当前位置: 首页 > news >正文

利用basee64特性 -- BYUCTF 2025 JWTF

题目信息: Unfortunately one of our JWTs was compromised by attackers, so we created a JWT Revocation List to ensure they can’t use it anymore.

代码量很少

# 导入必要的模块
# 从 flask 模块导入 Flask, request, redirect, make_response, jsonify 类和函数
from flask import Flask, request, redirect, make_response, jsonify
# 导入 jwt 模块用于处理 JSON Web Token,导入 os 模块用于与操作系统进行交互
import jwt, os# 初始化 Flask 应用
app = Flask(__name__)
# 从 flag.txt 文件中读取内容并赋值给 FLAG 变量
FLAG = open('flag.txt', 'r').read()
# 生成一个 32 字节的随机字节串,并将其转换为十六进制字符串作为应用的密钥
APP_SECRET = os.urandom(32).hex()
# 生成一个 32 字节的随机字节串,并将其转换为十六进制字符串作为管理员的密钥
ADMIN_SECRET = os.urandom(32).hex()
# 打印管理员密钥,方便调试
print(f'ADMIN_SECRET: {ADMIN_SECRET}')# JRL - JWT 吊销列表,用于存储需要吊销的 JWT 令牌
jrl = [# 编码一个包含管理员权限和用户 ID 的 JWT 令牌并添加到吊销列表中jwt.encode({"admin": True, "uid": '1337'}, APP_SECRET, algorithm="HS256")
]# 定义根路由,处理 GET 请求
@app.route('/', methods=['GET'])
def main():# 创建一个响应对象,内容为 'Hello World!'resp = make_response('Hello World!')# 设置一个名为 'session' 的 cookie,值为一个包含非管理员权限的 JWT 令牌resp.set_cookie('session', jwt.encode({"admin": False}, APP_SECRET, algorithm="HS256"))return resp# 定义 /get_admin_cookie 路由,处理 GET 请求,用于在知道管理员密钥时获取管理员 cookie
@app.route('/get_admin_cookie', methods=['GET'])
def get_admin_cookie():# 从请求参数中获取管理员密钥secret = request.args.get('adminsecret', None)# 从请求参数中获取用户 IDuid = request.args.get('uid', None)# 如果管理员密钥、用户 ID 为空或者用户 ID 为 '1337',则重定向到根路由if secret is None or uid is None or uid == '1337':return redirect('/')# 如果管理员密钥与预设的管理员密钥相等if secret == ADMIN_SECRET:# 创建一个响应对象,内容为 'Cookie has been set.'resp = make_response('Cookie has been set.')# 设置一个名为 'session' 的 cookie,值为一个包含管理员权限和用户 ID 的 JWT 令牌resp.set_cookie('session', jwt.encode({"admin": True, "uid": uid}, APP_SECRET, algorithm="HS256"))return resp# 定义 /flag 路由,处理 GET 请求,用于在用户为管理员时获取标志信息
@app.route('/flag', methods=['GET'])
def flag():# 从请求的 cookie 中获取名为 'session' 的值,并去除首尾空格和等号session = request.cookies.get('session', None).strip().replace('=','')# 如果 session 为空,则重定向到根路由if session is None:return redirect('/')# 检查 session 是否在 JWT 吊销列表中,如果在则重定向到根路由if session in jrl:return redirect('/')try:# 尝试解码 session 中的 JWT 令牌payload = jwt.decode(session, APP_SECRET, algorithms=["HS256"])# 如果解码后的令牌中 admin 字段为 True,则返回标志信息if payload['admin'] == True:return FLAGelse:# 否则重定向到根路由return redirect('/')except:# 解码失败则重定向到根路由return redirect('/')# 定义 /jrl 路由,处理 GET 请求,用于获取 JWT 吊销列表
@app.route('/jrl', methods=['GET'])
def jrl_endpoint():# 将 JWT 吊销列表以 JSON 格式返回return jsonify(jrl)# 如果该脚本作为主程序运行,则启动 Flask 应用
if __name__ == "__main__":app.run(host='0.0.0.0', port=1337, threaded=True)

我们先尝试获取被吊销的JWT

["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwidWlkIjoiMTMzNyJ9.NPRE_IxezKiALwrpSQkHy2DxuJEXmHblTYtvGUo-1Gw"]

JWT(JSON Web Token)由三个部分组成

  1. 头部(Header)
  2. 载荷(Payload)
  3. 签名(Signature)

每部分使用 Base64 编码,并由句点 . 分隔,形成如下格式:

Header.Payload.Signature

签名部分是

NPRE_IxezKiALwrpSQkHy2DxuJEXmHblTYtvGUo-1Gw

其解码后hex为

34 f4 44 23 17 b3 2a 20 0b c2 ba 52 42 41 f2 d8 3c 6e 24 45 e6 1d b9 53 62 db c6 52 8d 46

但是我们无论如何修改最后一位base64,其结果均相同

NPRE_IxezKiALwrpSQkHy2DxuJEXmHblTYtvGUo-1Gx
NPRE_IxezKiALwrpSQkHy2DxuJEXmHblTYtvGUo-1Ga
http://www.xdnf.cn/news/540973.html

相关文章:

  • 数据库(二):ORM技术
  • 大模型(3)——RAG(Retrieval-Augmented Generation,检索增强生成)
  • 【SPIN】PROMELA数据与程序结构详解(SPIN学习系列--7)
  • 【大模型】SpringBoot 整合Spring AI 对接主流大模型平台实战详解
  • 【神经网络与深度学习】激活函数的可微可导
  • 频率非周期性失稳
  • Elasticsearch面试题带答案
  • 第 84 场周赛:翻转图像、字符串中的查找与替换、图像重叠、树中距离之和
  • 算法-数对的使用
  • 【八股战神篇】Java多线程高频面试题(JUC)
  • 2025.05.19【Connectedscatter】连接散点图详解
  • (C语言篇)处理字符串的四个基础函数
  • ARP 原理总结
  • 无刷直流水泵构成及工作原理详解--【其利天下技术】
  • 【回溯法】0-1背包问题 C/C++(附代码)
  • 【C++模板与泛型编程】实例化
  • lovart design 设计类agent的系统提示词解读
  • python调用pip模块,使用pip_install脚本,在IDE中运行自动记录安装包到requirements文件的代码示例
  • Mergekit——任务向量合并算法Ties解析
  • 从基础到高级:网站反爬技术全景解析与第三方工具对比
  • C++类与对象--3 C++对象模型和this指针
  • 【计网】作业5
  • Python 训练营打卡 Day 29
  • 物流项目第二期(用户端登录与双token三验证)
  • python学习day1
  • C++字符串处理:`std::string`和`std::string_view`的区别与使用
  • 设计一个程序,将所有的小写字母转换为大写字母
  • 打造灵感投掷器:我的「IdeaDice」开发记录
  • sqli-labs第九关—‘时间盲注
  • 虚拟机的三个核心类加载器