安全图像上传PHP
在我的网站上,我允许用户使用以下方式上传图像安全图像上传PHP,php,mysql,file-upload,Php,Mysql,File Upload,在我的网站上,我允许用户使用以下方式上传图像 $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('Th
$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,如果是这样,如何应对?我认为.exe文件不能重命名。否则它将成为损坏的文件,因此不建议重命名.exe文件,在php文件中,使用post方法上载数据,这样数据就不可见,因此它是安全的。您可以使用此示例。如果不是图像,则返回false:
if (!getimagesize($_FILES['profile_image']['tmp_name'])){
die('Not an image');
}
您在这里关心的不是exe可以上传(因为有办法绕过任何安全性,甚至MIME),而是这个exe以后是否可以执行(只是上传一个exe文件不会执行它,它只会放在那里)
但是如果你想得到它,我建议你去做。强制文件扩展也是一种方法(因此MIME图像/png将被更改,因此扩展名将为.png,而不是用户放在那里的任何内容)。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" />
(显然,上述内容可以在客户端更改,因此不必依赖)您可以先检查文件扩展名,但有些人可能会试图伪造文件扩展名,以便:
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>
ForceType应用程序/八位字节流
ForceType图像/jpeg
ForceType图像/gif
ForceType图像/png
此代码放在上载目录的.htaccess文件中,只允许图像与其默认处理程序关联。其他所有内容都将作为普通字节流使用,不会运行任何处理程序。(查看本文)这是我不久前用于图像上传的函数。 它将检查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;
}
}
函数checkMagicNumberJPEG($filename){
//打开文件并读取前2个字节
$file=fopen($filename,'r');
$contents=fread($file,2);
$ascii='';
//转换为十六进制
对于($i=0;$i
检查文件的mime类型()还检查这是您的服务器配置为执行.jpg
文件吗?