PHP上传文件增强安全性

问题描述:

嘿..我的问题是如何防止某人上传病毒或一些恶意代码与您假装的扩展例如我有一个PDF文件上传,任何人都可以上传一个二进制PDF伪装有很多的程序来做到这一点。PHP上传文件增强安全性

看看php的FileInfo扩展名。
对实际内容类型的识别与unix file command类似。
但这只对恶意用户有帮助,他们只是简单地重命名virus.exe到virus.pdf。它不会阻止上传有害的pdf(在一个或多个更广泛的PDF阅读器中使用某些错误)。

上传文件时出现了许多安全问题。第一个问题是该文件可能不是您想要的文件,在这种情况下是pdf。变量$_FILES['file_name']['type']受攻击者控制,可以从永不可信。此值通常使用漏洞代码或使用tamperdata进行修改。

1)在你的secuirty系统的第一步是确保该文件具有.pdf扩展:

if("pdf"!=substr($fileName, strrpos($fileName, '.') + 1)){ 
    die("Invalid File Type"); 
} 

2)接下来,你应该检查它使用PHP filetype()功能是什么文件类型。

3)一个严重的问题是,这些PDF文件可以利用漏洞,例如在Adobe制作的软件中常见的buffer overflows。这些PDF用于传播Drive By Download攻击中的病毒。

最好的解决方案是安装Web应用程序防火墙Mod_Security。这将阻止像SQL注入和XSS攻击你的Web应用程序的攻击。 Mod_Secuirty可以配置为使用modsec-clamscan来扫描全部病毒上传文件。

+0

Rook感谢您的博文,我已经涵盖了除了mod_security之外的所有安全性,我会要求将其安装在我的hostgator主机上。 Thanks dude :) – mandril 2010-05-04 18:59:18

+0

@mandril欢迎您,我很乐意帮助 – rook 2010-05-04 19:14:16

+2

filetype()如何提供帮助?在我看来,它所要做的就是告诉你文件是文件还是目录。也许你的意思是[finfo-file()](http://www.php.net/manual/en/function.finfo-file.php)? – 2011-03-28 21:44:58

您无法防止某人上传病毒。最好的方法是在上传到您网站的所有文件上运行像clamscan这样的病毒扫描。

使用扩展检查/ MIME检查只会告诉您文件命名正确,或者具有正确的MIME签名。除非实际扫描它,否则无法确定是否存在病毒。

我们使用fileinfo +文件扩展名的组合检查。虽然浏览器通常发送MIME类型,但不应该相信它,因为这可能是劫持

在我们的案例中我们不在我们的服务器上运行任何文件。所以我们所做的是有一个extension while list像(例如):pdf jpg png等。和一个blacklisted mime extensions列表。通过这种方式,我们避免了使用扩展名与MIME类型不匹配的文件的风险。

一旦文件被保存在服务器中,我们总是强制MIME类型为application/octet-stream,因此文件是总是已下载。

是这样的:

<?php 

$allowed_types = array(
/* images extensions */ 
'jpeg', 'bmp', 'png', 'gif', 'tiff', 'jpg', 
/* audio extensions */ 
'mp3', 'wav', 'midi', 'aac', 'ogg', 'wma', 'm4a', 'mid', 'orb', 'aif', 
/* movie extensions */        
'mov', 'flv', 'mpeg', 'mpg', 'mp4', 'avi', 'wmv', 'qt', 
/* document extensions */        
'txt', 'pdf', 'ppt', 'pps', 'xls', 'doc', 'xlsx', 'pptx', 'ppsx', 'docx' 
         ); 


$mime_type_black_list= array(
# HTML may contain cookie-stealing JavaScript and web bugs 
'text/html', 'text/javascript', 'text/x-javascript', 'application/x-shellscript', 
# PHP scripts may execute arbitrary code on the server 
'application/x-php', 'text/x-php', 'text/x-php', 
# Other types that may be interpreted by some servers 
'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh', 
'text/x-c++', 'text/x-c', 
# Windows metafile, client-side vulnerability on some systems 
# 'application/x-msmetafile', 
# A ZIP file may be a valid Java archive containing an applet which exploits the 
# same-origin policy to steal cookies  
# 'application/zip', 
         ); 


$tmp_file_extension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION)); 

if(!strlen($tmp_file_extension) || (!$allow_all_types && 
    !in_array($tmp_file_extension,$allowed_types))) { 
    return false; 
} 

$finfo = new finfo(FILEINFO_MIME, MIME_MAGIC_PATH); 

if ($finfo) { 
    $mime = $finfo->file($file_name_tmp); 
} 
else { 
    $mime = $file_type; 
} 

$mime = explode(" ", $mime); 
$mime = $mime[0]; 

if (substr($mime, -1, 1) == ";") { 
    $mime = trim(substr($mime, 0, -1)); 
} 

return (in_array($mime, $mime_type_black_list) == false); 

除了这一点,你可以添加virus scan使用clamav +的php extension

最简单的两个步骤的答案allow users to securely upload files in PHP是:

  1. 始终保存文件根目录外的文件
  2. Writ e一个PHP脚本,在不允许它们执行的情况下提供这些文件

这将停止大多数基于文件上载的攻击,但不是全部。一个更全面的和完整的解决方案包括以下各组成:

  1. 文档根外从不存储文件,经由代理脚本服务于它(如上)。
  2. 使用finfo_file()验证实际文件内容的MIME类型。
  3. 上传时,保存为随机文件名而不是提供的文件名,并使用数据库行保留元数据(并且您的代理脚本可以找到要提供的正确文件)。
  4. 对磁盘上的实际文件内容进行编码/加密,并对脚本进行解码/解密。这可以防止恶意用户上传恶意负载,然后使用其他漏洞(例如LFI)来触发它。在这种情况下,base64_encode()应提供足够的保障。 (但是,如果你在你的应用程序有另一个弱点,你应该真的解决这个问题。)

如果你做到以上的,你的上传表单将不可能永远是脆弱性的来源。

+0

这是我读过的第一个关于您的第4点用于文件上传的地方。没有其他地方看过。 + 1.为什么它是这么写的与冲突的意见,在这里和php.net的爱......不这样做。不要这样做。我喜欢你的帖子。 – Joeme 2017-06-30 21:55:40