1.1、原理
在存在文件上传功能的页面,若没有对上传的文件进行检测、验证以及过滤。可能会导致恶意用户上传恶意脚本文件,被获取服务端的权限。
1.2、文件上传代码常用函数
$_FILES数组内容如下: $_FILES['myFile']['name'] 客户端文件的原名称。 $_FILES['myFile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。 $_FILES['myFile']['size'] 已上传文件的大小,单位为字节。 $_FILES['myFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,但 用 putenv() 函数设置是不起作用的。
move_upload_file(filename,destination)函数:将上传的文件移动到指定位置
preg_match():执行正则表达式
2.1、前端JS限制绕过
原理:浏览器通过JS代码对上传的文件进行格式验证
绕过方式:
1》可以通过Burp抓包修改上传文件的格式
2》修改JS其中关键的检测函数,或者直接禁用JS
漏洞代码分析:
上述JS函数只允许“.jpg | .png | .gif”的图片格式上传。
2.2、服务端MIME类型验证
MIME简介:
content-type属性:定义服务端发送给客户端MIME的类型。
浏览器能处理的所有资源都有对应的MIME类型。
浏览器根据所接受数据的MIME类型判断用什么方式处理。
MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
检测原理:服务端通过对MIME类型格式的验证进行过滤。
绕过方式:通过Burp抓包修改Content-Type属性的值来进行检测绕过。
漏洞代码分析:
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;}
2.3、文件头绕过
原理:不同的文件存在的文件头格式不同,服务端代码通过检测上传文件的文件头格式来判断是否存在恶意上传。
绕过方式:在上传的恶意文件中修改或添加服务端允许上传的对应文件头。
常见的文件头:
JPEG:0xFFD8FF
PNG: 0x89504E470D0A1A0A
GIF: 47 49 46 38 39 61 (GIF89a)
漏洞代码分析:
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)){
return $ext;
}else{
return false;
}
2.4、.htaccess文件上传
原理:.htaccess文件上传是利用.htaccess文件可以对服务器进行配置的功能,实现将扩展名为.jpg .png等文件当作PHP文件解析的过程。
.htaccess基础
.htaccess文件(分布式配置文件)提供了一种基于每个目录进行配置更改的方法。她是包含一个或多个配置指令的文件,放在特定的文档目录中,文件的指令适用于该目录及其所有子目录。
.htaccess是Web服务器的一个配置文件,可以通过.htaccess文件实现web服务器中的文件的解析方式、重定向等配置。
.htaccess文件上传配置
(1)指定文件名:
ForceType application/x-httpd-php SetHandler application/x-httpd-php (2)指定文件后缀:
AddType application/x-httpd-php.jpg
2.5、文件截断上传
原理:PHP的版本低于5.3.4时,会把它当作结束符,导致后面的数据直接被忽略,造成文件上传被截断。当上传路径可控时,可以通过%00截断进行木马上传。
绕过方式:
通过可控的上传路径,将恶意脚本后面通过%00截断。
漏洞代码:
$img_path=$_GET['save_path']."/".rand(10,99).date("YmdHis").".".$file_ext; //代码
?save_path=../upload/+rand(生成随机文件名) //文件保存路径
?save_path=../upload/1.php%00+rand文件 //通过%00截断后rand生成的随机文件名无效
2.6、竞争条件上传
竞争条件:指多个线程在没有进行锁操作或者同步操作的情况下同时访问同一个共享代码、变量、文件等,运行的结果依赖于不同线程访问数据的顺序。
原理:文件上传时,先上传、再检测、不合条件时再删掉的场景,攻击者利用多线程并发不断上传一个可以写webshell的脚本,然后马上访问这个刚上传的文件,当服务端判断并删除的时间大于客户端线程访问的时间时,客户端可以在删除之前访问到这个脚本并成功运行写入webshell。
漏洞分析:
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
PS:(本文使用代码出自upload-lab靶场)。