一、文件上传漏洞概述
文件上传漏洞就是利用文件的上传功能去上传可执行的脚本文件,并通过此脚本文件获得服务器的访问权限。常见的站点一般都有文件上传功能,例如上传用户头像、上传附件、编辑文档等。当我们没有过滤上传的文件时或者服务器配置不安全就会造成文件上传漏洞。
若通过一些绕过手段,上传了webshell,就会造成服务器权限受到危害。
二、WebShell
“web”的含义是需要服务器开放web服务,“shell”是取得对服务器某种程度的权限。webshell就是入侵者通过网站端口对网站服务器进行操作的权限。
根据复杂程度,被分为:大马和小马(一句话木马)
许多一句话木马可以配合菜刀和蚁剑使用。
三、文件上传漏洞绕过方法
1.客户端JavaScript验证
可以看到该服务器在前端用javascript对上传的文件进行了过滤,所以我们上传文件会提示,文件不允许上传。
绕过有两种方法:
(1)通过burp suite软件,抓到正常上传的请求报文,修改报文的内容,发送报文,便可以绕过javaScript检验。
(2)通过修改javaScript,改变其中的关键函数。
2.服务器端Mine类型检测
mine类型是描述消息内容类型的因特网标准
常见的有:
text/html (HTML文档)
image/gif (gif图像)
text/plain(纯文本)
image/png (png图像)
application/xml(xml)
application/msword (word文档)
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 = '文件类型不正确,请重新上传!';
可以看到服务器将文件类型进行了限制,只允许image/jpeg的类型上传。我们可以利用burp抓包,将content-type类型改为:image/jpeg。
3.服务端文件扩展名验证
(1)黑名单
$deny_ext = array('.asp','.aspx','.php','.jsp');
可以看到服务端对上传文件的扩展名进行了限制:
我们可以寻找黑名单中没有被禁止的文件类型,例如
php3|php4|php5|phtml
也可以使用%00截断
%00截断是chr(0),它代表着NULL,空字符
当程序在输出含有chr(0)变量时,char(0)后面的数据会被停止,就是它被当成了结束符,我们上传文件时可以利用%00截断,在文件扩展名验证时,是取文件的扩展名来验证,但是最后保存到本地的文件时%00会截断文件名。
例如:127.0.0.1/phpinfo.php%00.jpg
上传时绕过了验证,但是保存到本地时就是phpinfo.php,%00后被截断了。
(2)白名单
只允许上传指定后缀的文件,我们可以利用操作系统的特性来绕过。
例如:上传文件名phpinfo.php(空格)
phpinfo.php(.)
最后生成文件时,字符会被自动去除。
4.利用服务器特殊配置(Apache)
如果在Apache中.htaccess的配置有效,且可以被上传,那可以尝试在.htaccess中写入:
SetHandler application/x-httpd-php
phpinfo.jpg即可以php脚本解析
5.利用服务器的特殊配置(以CGI/FastCGI)
我们可以,Nginx默认使用CGI的方式,所以可以利用.user.ini文件。我们可以在该文件中修改php.ini中的一些选项,从而进行绕过。构造语句:
auto\_prepend\_file=phpinfo.jpg
意思是在加载php文件之前先加载phpinfo.jpg文件,相当于包含了该文件的内容。
四、文件上传漏洞防御
对文件内容进行检测
对中间件作安全的配置
文件扩展名使用白名单
....