什么是最安全的php文件上传方法,能够处理所有文件类型?

3
我正在开发一个小型社交网络,想知道以下方法是否足以使我的“文件上传处理脚本”尽可能安全。我希望允许用户上传图片 [jpeg、jpg、png、gif]、视频 [3gp、wma、mp4] 和 mp3 文件。我已经阅读了许多在 SO 上的问题,但大部分似乎只详细涉及图像上传,而不是视频和 mp3。我想知道还有什么更多的措施可以使脚本成为最安全的上传脚本。[是的,我对安全非常担心,肯定希望我的网站以其安全性而不是速度而闻名]。
我目前的做法如下:
  • 检查用户是否已注册(通过检查会话)
  • 检查文件是否没有错误地上传
  • 检查文件大小是否在允许范围内
  • 清理文件名
  • 获取文件扩展名并检查它是否是允许的扩展名
  • 获取 MIME 类型并检查它是否是允许的 MIME 类型
  • 生成新的随机文件名
  • 设置 .htaccess 规则用于存储上传的文件到 public_html 外的文件夹中
  • 使用 move_uploaded_file()
  • 使用 chmod() 将 '0644' 设置为上传文件的权限
在 .htaccess 文件中将添加以下内容:
 SetHandler none
    SetHandler default-handler
    Options -ExecCGI
    php_flag engine off

ForceType application/octet-stream
<FilesMatch "(?i)\.jpe?g$">
    ForceType image/jpeg
</FilesMatch>
<FilesMatch "(?i)\.gif$">
    ForceType image/gif
</FilesMatch>
<FilesMatch "(?i)\.png$">
    ForceType image/png
</FilesMatch>
<FilesMatch "(?i)\.mp3$">
    ForceType audio/mpeg
</FilesMatch>
<FilesMatch "(?i)\.mp4$">
    ForceType video/mp4
</FilesMatch>

我将尝试的代码如下:

以下是我正在尝试的代码:

$fileInput = $_FILES['image'];
$sizeLimit="4000";
if($fileInput['error'] === UPLOAD_ERR_OK && isset($fileInput['tmp_name'])){
if($fileInput['size'] < $sizeLimit){
$cleanedName=stripslashes($fileInput['name']); //cleaning file name
$checking = pathinfo($cleanedName); //finding extension
$ext=$checking['extension'];
$finfo = finfo_open(FILEINFO_MIME_TYPE); // find mime type
$mimetype =  finfo_file($finfo, $fileInput['tmp_name']);
finfo_close($finfo);
.
.
.//generate random name and use move_uploaded_file() and chmod()
}
}

这种方法足以保护我的网站安全吗?还是这种方法存在明显的缺陷?感谢您的帮助。

如果您想更加安全,确保使用SSL。关于上传本身,无论文件类型如何,文件只是一个文件,较大的文件或特定类型的文件本质上并不更难或不安全。 - GolezTrol
@GolezTrol 谢谢。是的,我一定会使用SSL。我注意到SO上的大多数用户都建议使用GD来验证上传是否为图像,但是否有任何类似的验证方法可用于视频和音频以更确保文件的安全?我的方法是否存在任何容易被操纵的漏洞? - newbiePrgrmr
1个回答

0

建议检查文件名扩展名,但请注意,MIME类型很容易被欺骗,因此这不是安全检查的好方法。

你目前的做法很好,我的额外建议是:

  • 对所有上传文件进行病毒扫描 - 这主要是为了保护应用程序的其他用户,而不是您的服务器。
  • 将图像存储在网站根目录之外,并使用 此类方法 代理要提供的文件。这样做的好处是可以在代码中执行任何附加权限检查(因此 Bob 无法下载 Alice 的文件),并且由于文件被视为数据访问,所以不存在执行的机会。
  • 使用 X-Content-Type-Options: nosniff 标头提供文件,以防止通过 IE 的 mime 嗅探进行任何 XSS 攻击。
  • 使用服务器生成的名称存储图像。例如,您可以根据其数据库条目的主键命名每个文件。这将减轻任何 目录遍历 攻击(如此一类的攻击),如果用户确实成功上传了恶意内容,则更不可能在服务器上找到它。
  • 将所有图像加载到图像库中并重新保存它们,以确保它们没有针对流行浏览器的 漏洞嵌入
  • 建立某种手动监控系统,以监视任何上传的非法内容。
  • 保护您的表单免受 CSRF 攻击。

非常感谢这些精彩的建议。我计划使用clamAv来扫描文件。我希望基于会话的CSRF令牌足以缓解任何CSRF威胁。 - newbiePrgrmr
是的,基于会话的 CSRF 令牌是正确的选择。 - SilverlightFox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接