0

在我的网站上,我允许用户使用以下方式上传图片......

$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 并上传,如果是这样,如何应对?

4

6 回答 6

2

Mime 类型不可信,因此,正如@yoeriboven 所说,您可以使用:

if (!getimagesize($_FILES['profile_image']['tmp_name'])){
    die('Not an image');
}

但您也不能允许执行上传到您的上传文件夹的任何文件。您可以通过以下方式执行此操作.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" />

(显然以上内容可以在客户端进行更改,因此不能依赖)

于 2013-06-05T11:48:30.093 回答
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]

于 2013-06-05T11:52:54.760 回答
1

我认为.exe文件不能重命名。否则它将成为损坏的文件,因此不建议重命名 .exe 文件,并且在 php 文件上传中,数据使用 post 方法进行,因此数据不可见,因此它是安全的。

于 2013-06-05T11:42:43.153 回答
1

例如,您可以使用它。如果不是图像,它将返回 false:

if (!getimagesize($_FILES['profile_image']['tmp_name'])){
    die('Not an image');
}
于 2013-06-05T11:44:52.700 回答
1

您在这里担心的不是exe可以上传(因为有办法绕过任何安全性,甚至是MIME),而是以后可以执行这个exe(只是上传一个exe文件不会执行它,它只会放在那里) ?

但是,如果您想保护它,我建议您阅读 MIME 类型并通过它。强制文件扩展名也是一种方法(因此 MIME 图像/png 将被更改,因此扩展名将是 .png 而不是用户放置的任何内容)。

于 2013-06-05T11:45:28.133 回答
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;
    }
}
于 2013-06-05T12:14:46.913 回答