我有一个使用文件上传的网站正在运行。一切正常,除了其中一个用户。他们使用 IE8 将文件从其 SharePoint 服务器上传到网站。当我查看 PHP 中的 $_FILES 变量时,"name"键如下所示:
somefilename[1]
而不是
somefilename.pdf
然后阻止上传,因为不允许扩展。以前有人处理/见过这个吗?它看起来像一个临时名称,或隐藏的文件扩展名。
编辑:
你们中的一些人请求了 $_FILES 变量:
[Filedata] => Array
(
[name] => Algemene%20Voorwaarden%20Corporate%20Services%202011[2]
[type] => application/octet-stream
[tmp_name] => /tmp/phps19zye
[error] => 0
[size] => 148021
)
这应该是一个 PDF 文件。我需要扩展,不仅出于安全原因,[类型]更适合它,而且用于演示和功能。我需要为文件类型显示正确的图标,并单独显示图像进行处理。
HTML 表单只是一个基本的测试表单:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="uploadtest3.php" method="post" enctype="multipart/form-data">
<input type="file" name="file_upload" id="file_upload" />
<br /><input type="submit" value="Uploaden" />
</form>
</body>
</html>
PHP 文件如下:
$targetFolder = '/uploadtests/uploads3';
if (!empty($_FILES)) {
$tempFile = $_FILES['file_upload']['tmp_name'];
$targetPath = $_SERVER['DOCUMENT_ROOT'] . $targetFolder;
$targetFile = $targetPath . $_FILES['file_upload']['name'];
move_uploaded_file($tempFile,$targetFile);
echo "OK";
}
简介
以前见过这个问题,但不确定是什么原因造成的。 我什至不想称其为错误,因为some files extension can be intentionally removed or altered
出于恶意目的。
最important thing is validating file properly
,无需担心文件是否有扩展名
原因:
-
File Extension Can easily be faked
,如果您的应用程序仅依赖文件扩展名进行验证,那就太糟糕
了 $_FILES ['file_upload']['type']
会为所有没有扩展名的文件返回application/octet-stream
,因此它不是验证选项由于这是一个浏览器问题,那么它是一个
Client Related Problem
,所以你没有任何控制权。如果你能够管理这一点,你肯定会增加用户体验
简单补丁
解决方案非常简单。您只需要使用FILEINFO
验证文件并修复上传文件的任何扩展名问题。
您还需要根据其 Mime 类型验证所有上传的文件......并删除任何无效文件。
概念验证
$allowedTypes = array (
"pdf" => "application/pdf"
);
$pathFinal = "final";
$pathTemp = "temp";
try {
if (! empty ( $_FILES )) {
$tempFile = $_FILES ['file_upload'] ['tmp_name'];
$fileName = $_FILES ['file_upload'] ['name'];
$destinationTemp = $pathTemp . DIRECTORY_SEPARATOR . $fileName;
$destinationFinal = $pathFinal . DIRECTORY_SEPARATOR . $fileName;
/**
* Move To tempary File
*/
move_uploaded_file ( $tempFile, $destinationTemp );
$fileMime = mimeInfo ( $destinationTemp );
$key = array_search ( $fileMime, $allowedTypes );
/**
* Validate Mime Type
*/
if (empty ( $key )) {
unlink ( $destinationTemp );
throw new Exception ( "File Type not Supported" );
}
/**
* Fix Extention Issues
*/
$ext = pathinfo ( $destinationTemp, PATHINFO_EXTENSION );
if (empty ( $ext )) {
$destinationFinal .= "." . $key;
}
/**
* Transfer File to Original Location
*/
copy ( $destinationTemp, $destinationFinal );
unlink ( $destinationTemp );
echo "OK";
}
} catch ( Exception $e ) {
echo "ERROR :", $e->getMessage ();
}
使用的功能
function mimeInfo($file) {
return finfo_file ( finfo_open ( FILEINFO_MIME_TYPE ), $file );
}
somefilename
似乎是一个数组。您的用户是否选择了多个文件进行上传? 您需要限制允许上传的文件数量,或者捕获数组并正确处理它。您还可以确保将 SharePoint 设置为允许多个文件上载。
另外,我找到了有关IE8将文件上传传递到服务器的方式的信息。来源文章指出:
此外,互联网区域的"上传文件时包括本地目录路径"URLAction已设置为"禁用"。此更改可防止将可能敏感的本地文件系统信息泄漏到 Internet。例如,Internet Explorer 8 现在将仅提交文件名 image.png,而不是提交完整路径 C:''users''ericlaw''documents''secret''image.png。
这意味着,如果您的代码(或 Sharepoint(希望通过 PATH_SEP
将文件夹结构与文件名分隔开来,那么使用 IE8 显然会失败。
您应该检查文件类型,而不是按扩展名,而是按 Mime 类型。使用变量 $_FILES["uploaded_file"]["type"]
获取 Mime 类型。
这样,用户就不能用奇怪的ASCII字符篡改扩展名,并且您知道什么文件是可靠的。