在我的网站上,我允许用户使用以下内容上传图片...
$max_filesize = 1572864; // 1.5MB
$upload_path = 'uploads';
$upload_path = $upload_path.'/';
$filename = $_FILES['profile_image']['name'];
if(filesize($_FILES['profile_image']['tmp_name']) > $max_filesize)
die('The file you attempted to upload is too large.');
if(!is_writable($upload_path))
die('permission errorrr!');
if(move_uploaded_file($_FILES['profile_image']['tmp_name'],$upload_path . $filename)){
// TA DA!
}
我刚刚接受了一些有关如何安全的信息,以及如何使其更加安全,我问我已经设法将.png文件更改为.jpg并上传它,所以理论上可以.exe被重命名和上传,如果是这样,怎么能被反击?
答案 0 :(得分:2)
Mime类型不可信任,因此,正如@yoeriboven所说,你可以使用:
if (!getimagesize($_FILES['profile_image']['tmp_name'])){
die('Not an image');
}
但您也不能允许执行上传到您的uploads文件夹的任何文件。您可以通过.htaccess
(假设您正在使用Apache)执行此操作:
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI
为了帮助用户,您可以做的另一件小事是使用HTML5的accept
属性:
<input type="file" name="file" accept="image/gif, image/jpeg" />
(显然上面的内容可以在客户端更改,因此不能依赖它)
答案 1 :(得分:2)
您可以先检查文件扩展名,但有些人可能会尝试伪造它:
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>
此代码放在上传目录中的.htaccess文件中,只允许图像与其默认处理程序相关联。其他所有内容都将作为普通字节流提供,不会运行任何处理程序。 (查看此文章[1])
答案 2 :(得分:1)
我认为.exe文件无法重命名。否则它将成为损坏的文件,因此不建议重命名.exe文件,并在php文件上传数据使用post方法,因此数据不可见,因此它是安全的。
答案 3 :(得分:1)
你可以用这个例子。如果它不是图像,它将返回false:
if (!getimagesize($_FILES['profile_image']['tmp_name'])){
die('Not an image');
}
答案 4 :(得分:1)
你关注的不是exe可以上传(因为有办法绕过任何安全性,甚至是MIME)但是这个exe可以稍后执行(只是上传一个exe文件不会执行它,它只会躺在那里)?
但是如果你想保护它,我建议reading up on MIME types并继续它。强制执行文件扩展也是一种方式(因此MIME图像/ png将被更改,因此扩展名为.png而不是用户放置的任何内容)。
答案 5 :(得分:0)
这是我之前用过我的图片上传器的功能。 它将检查jpeg文件的幻数并返回true或false。
function checkMagicNumberJPEG ($filename) {
// Open file and read first 2 btytes
$file = fopen($filename, 'r');
$contents = fread($file, 2);
$ascii = '';
// Convert to hex
for ($i = 0; $i < strlen($contents); $i++) {
$ascii .= dechex(ord($contents[$i]));
}
// Close file
fclose($file);
// Check magic number
if($ascii == 'ffd8') {
return true;
} else {
return false;
}
}