PHP上传文件增强了安全性

时间:2010-05-01 20:08:00

标签: php security file upload

嘿..我的问题是如何防止有人上传病毒或某些恶意代码与您假装的扩展程序,例如我有一个pdf文件上传器,任何人都可以上传带有pdf伪装的二进制文件有很多程序要做

5 个答案:

答案 0 :(得分:13)

上传文件时会出现许多问题。第一个问题是文件可能不是您想要的文件,在本例中是pdf。变量$_FILES['file_name']['type']由攻击者控制,永远可信任。通常使用漏洞利用代码或使用篡改数据修改此值。

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扫描所有上传文件中的病毒。

答案 1 :(得分:7)

我们使用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 + php extension

添加clamav

答案 2 :(得分:1)

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

答案 3 :(得分:1)

您无法阻止某人上传病毒。最好的方法是对上传到您网站的所有文件运行clamscan等病毒扫描。

使用扩展程序检查/ MIME检查只会告诉您文件名称正确,或者具有正确的MIME签名。在实际扫描之前,你无法判断是否有病毒。

答案 4 :(得分:1)

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

  1. 始终将文件保存在文档根目录之外
  2. 编写PHP脚本以提供文件而不允许执行它们
  3. 这将阻止大多数基于文件上传的攻击,但不是全部。更全面,更完整的解决方案包括以下各项:

    1. 永远不要将文件存储在文档根目录之外,通过代理脚本(如上所述)提供。
    2. 使用finfo_file()验证实际文件内容的MIME类型。
    3. 上传时,保存为随机文件名而不是提供的文件名,并使用数据库行保留元数据(因此您的代理脚本可以找到要提供的正确文件)。
    4. 对磁盘上的实际文件内容进行编码/加密,并使脚本解码/解密。这可以防止恶意用户上传恶意负载,然后使用其他漏洞(例如LFI)来触发它。在这种情况下,base64_encode()应该提供足够的保障。 (但如果你的应用程序中有另一个漏洞,你应该真的修复它。)
    5. 如果您执行上述所有操作,则您的上传表单可能不会成为漏洞的来源。