靶场下载地址:https://github.com/c0ny1/upload-labs
首先我总结了一下我所知道的文件上传的思路:
pass 1
前端验证
方法一:
直接尝试脚本文件,弹框警告
浏览器审查元素查看代码,发现form表单中存在onsubmit事件,删除此检测函数
然后进行上传,上传成功,右键点击复制图片地址
然后菜刀进行连接
成功绕过
方法二:
将准备好的a.php改为a.jpg然后打开burpsuite抓包,上传,修改filename为a.php,点击forward此时上传到服务器的仍为a.php
pass2
上传脚本文件,显示类型不正确
首先判断是否进行了MIME类型的限制
浏览器开启代理,打开burpsuite抓包
修改图中内容为下图所示允许的MIME类型
然后forward,上传成功
菜刀连接,同pass1
方法二:
将脚本后缀改为jpg,然后抓包修改filename为php,同样上传到服务器的也为php
pass3
首先上传脚本文件,显示失败;
抓包修改content-type为允许上传的格式,仍然失败
考虑可能对后缀做了限制
尝试可能未禁止的后缀类型,这里可以通过burpsuite抓包然后使用intruder模块进行测试
首先开始代理,打开burpsuite进行抓包,右键发送到intruder模块
然后清空所有参数,然后选中php后缀
然后设置payload,可以添加可执行脚本后缀的字典,这里我手动添加php4、php5、phtml
然后点击start attack
添加的这些后缀的长度不同,右键
复制到浏览器查看
发现成功上传,此时复制地址菜刀连接,成功。其实这三个格式均成功上传到了服务器。
pass4
在尝试修改content-type、尝试未限制后缀、大小写、双写、末尾添加空格、.、::$DATA均无法绕过,此时尝试上传.access文件
.access文件是apache服务器中的一个配置文件,负责相关目录下的网页配置。可以理解为设置什么类型的文件按照php进行执行
.htaccess文件攻击需要有一个前提:apache的httpd-conf配置文件中AllowOverride All,然后重启服务。
然后创建.htaccess文件,内容:SetHandler application/x-httpd-php
设置当前目录所有文件都使用PHP解析。只要内容符合PHP语法规范就会被当作PHP执行,不符合则会报错
然后上传.htaccess文件
上传成功,然后再上传内容为一句话木马的图片文件
上传成功
此时菜刀连接
pass 5
尝试其他类型绕过失败,尝试大小写绕过
将脚本大小写混淆,a.PhP
然后菜刀连接,成功
pass 6
先尝试其他类型、大小写混淆、双写、添加.、添加::$DATA均无效,尝试末尾添加空格,成功上传
菜刀连接,成功
pass 7
末尾添加.,利用的就是windows下,末尾添加.会自动忽略
成功上传,菜刀连接
pass 8
添加::$DATA
上传成功,菜刀连接
pass 9
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
分析源码,首先通过trim()函数去除了文件名两边的空格,然后通过deldot函数去除文件名末尾的点,再从右向左取第一个.,取出这个点到结尾的字符串为文件后缀,然后转化为小写,去除文件名中的::
D
A
T
A
,
再
次
去
除
首
尾
的
空
格
。
当
构
造
.
.
时
,
首
先
去
除
掉
最
右
边
的
点
,
变
成
了
.
空
格
,
然
后
取
后
缀
就
变
成
了
.
空
格
也
就
是
‘
DATA,再次去除首尾的空格。 当构造. .时,首先去除掉最右边的点,变成了.空格,然后取后缀就变成了.空格也就是`
DATA,再次去除首尾的空格。当构造..时,首先去除掉最右边的点,变成了.空格,然后取后缀就变成了.空格也就是‘file_ext=". "最后通过过滤,
f
i
l
e
e
x
t
‘
变
为
了
.
通
过
了
判
断
,
此
时
‘
file_ext`变为了. 通过了判断,此时`
fileext‘变为了.通过了判断,此时‘file_name`末尾为.空格,上传到服务器时就会自动转化为php
pass 10
替换不允许上传后缀为空
此时通过双写绕过