PHP文件上传漏洞原理以及如何防御详解

PHP文件上传漏洞

一、漏洞描述 

在本人开发过程中文件上传的功能是很常见的,比如一个游戏平台:

①用户可以上传自己的头像图片,

②用户论坛发表文章时又需要上传图片来丰富自己的文章,

③更有甚者游戏开发用户需要上传APK文件等。文件上传功能是十分重要的,

所以针对这个功能的漏洞就由下面来讨论研究,经过实战例子和跟大家探讨如何防护。

​ 为了方便统一讨论,目前我们就以上传图片功能来做讲解,会由浅到深的进行。

注意:代码中有详细的注释,请新手读者认真阅读。为方便新手读者,代码可能会写的比较原始,有一定基础的读者请自行尝试封装。如有疑问请在评论区留言。谢谢。

第一种漏洞使用:

我们先看一个前端HTML代码上传图片的简易版代码:upload.html




测试文件上传漏洞


选择你要上传的图片:


上面代码的页面效果:

PHP文件上传漏洞原理以及如何防御详解_第1张图片

一般开发为了快速实现效果就会写出类似下面的代码:upload_file.php

 上面的代码就是简单的把上传的文件保存到服务器上。然而并没有做任何的过滤或者防护措施。这是很致命的操作。如果此时我们写一个简单的一句话木马入侵就会很容易操控系统。例如:cmd.php

// 简单的一句话木马

然后我们利用上面html代码上传到服务器的uploads文件中,此时我们假设访问

http://www.域名.com/uploads/cmd.php?cmd=system('whoami') 

即可触发我们写好的木马。

第一个防护:验证文件类型

我们来动手改下上面uplaod_file.php的文件(下面是新版)

 1024*1024*2)
{
	echo "Upload false, the file size is too large";
	return ;
}

// 开始上传文件
if(!move_uploaded_file($file['tmp_name'], $save_upload_path)) {
    echo '您的图片上传失败.';
    return;
} else {
    echo $save_upload_path . '文件已经成功上传!';
    return;
}

以上就是就基本的防御,通过判断文件的类型以及文件的大小来达到限制其他文件的上传。但是已经说了这是最简单的,所以是很容易被破解的,下面来介绍第二种情况。

第二种漏洞使用:

有一定基础的PHPer都会做一定基础防御,但是道高一尺魔高一丈。下面我们来介绍一套组合拳:抓包工具:Burpsuite; 中国菜刀:Cknife(Burp Suite 是用于攻击web 应用程序的集成平台,包含了许多工具。)(希望大家能 "善" 用此类工具,心无杂念。)具体如何用这些工具我就不在这里赘述了。

使用上面的工具能帮助入侵者修改文件的类型甚至是文件的大小,以此来骗过系统程序的判断。有的小伙伴可能会想到控制文件的后缀,其实通过Burpsuite抓包依然是可以将.png的文件变成.php文件运行的。

所以我们需要全面防护,但是要记住一句话:安全是相对的,没有任何绝对的安全!

全面防护:最终版upload_file.php

 1024*1024*2)
{
	echo "Upload false, the file size is too large";
	return ;
}
// 识别文件后缀名
if( $end_upload_ext !== 'jpg' || $end_upload_ext !== 'jpeg' || $end_upload_ext !== 'png' )
{
	echo "Upload false, the file size is too large";
	return ;
}

// 开始上传文件
if(getimagesize($uploaded_tmp))
{
	// 将图片重新复制一遍,防止有害数据保留下来
    if( $uploaded_type == 'image/jpeg' ) {
        $img = imagecreatefromjpeg( $uploaded_tmp );
        imagejpeg( $img, $temp_path, 100);
    }
    else if($uploaded_type == 'image/png') {
        $img = imagecreatefrompng( $uploaded_tmp );
        imagepng( $img, $temp_path);
    }
    else
    {
    	return ;
    }
    // 释放图片资源
    imagedestroy( $img );
    // 临时保存的图片转存到真实路径下
    if( rename( $temp_path,  __dir__ . DIRECTORY_SEPARATOR . $save_upload_path . $target_file ) ) {
        echo "upload file successfully";
    }
    else {
        echo "upload false";
    }
    // 删除临时图片文件(为防止未清理临时文件前程序崩溃等,建议加多一个守护进程清除,以及增加报错记录)
    if( file_exists( $temp_path ) )
    {
        unlink( $temp_path );
    }

    return;
}

// 增加csrf防御
runCsrfToken();

upload_file.php文件代码详解:

  • 确保文件数据真实存在
  • 增加请求token,防止跨域攻击
  • 然后通过限制文件的类型、文件的后缀名,以及文件大小来控制上传白名单
  • uniqid()函数能帮助我们获取微秒级的13位数的时间戳,减少在同一时间上传相同文件名而造成误差的可能。
  • 通过getimagesize()函数判断该文件是否是真实的图片资源。
  • 最后通过将图片重新复制成一个新的图片,去除掉有害的数据,留下真实的图片资源。
  • 最后增加一步防止CSRF攻击

写在最后:安全是相对的,此文是希望大家能够认真对待一些web漏洞,在探索的过程中会遇到很多有趣的。本文如有遗漏或不正确之处,欢迎在评论区留言。

 

 

 

 

 

你可能感兴趣的:(web漏洞)