Должны ли мы дезинфицировать $_FILES ['filename'] ['name']?

После того, как пользователь загрузит изображение на сервер, мы должны дезинфицировать $_FILES['filename']['name']?

Я проверяю размер файла/тип файла и т.д. Но я не проверяю другие вещи. Есть ли потенциальная дыра в безопасности?

Спасибо

Ответ 1

Абсолютно! Поскольку @Bob уже упоминал, что это слишком просто для перезаписывания имен обычных файлов.

Также есть некоторые проблемы, которые вы можете рассмотреть, например, не все разрешенные символы в Windows разрешены в * nix и наоборот. Имя файла может также содержать относительный путь и может потенциально перезаписать другие не загруженные файлы.

Вот метод Upload(), который я написал для phunction PHP framework:

function Upload($source, $destination, $chmod = null)
{
    $result = array();
    $destination = self::Path($destination);

    if ((is_dir($destination) === true) && (array_key_exists($source, $_FILES) === true))
    {
        if (count($_FILES[$source], COUNT_RECURSIVE) == 5)
        {
            foreach ($_FILES[$source] as $key => $value)
            {
                $_FILES[$source][$key] = array($value);
            }
        }

        foreach (array_map('basename', $_FILES[$source]['name']) as $key => $value)
        {
            $result[$value] = false;

            if ($_FILES[$source]['error'][$key] == UPLOAD_ERR_OK)
            {
                $file = ph()->Text->Slug($value, '_', '.');

                if (file_exists($destination . $file) === true)
                {
                    $file = substr_replace($file, '_' . md5_file($_FILES[$source]['tmp_name'][$key]), strrpos($value, '.'), 0);
                }

                if (move_uploaded_file($_FILES[$source]['tmp_name'][$key], $destination . $file) === true)
                {
                    if (self::Chmod($destination . $file, $chmod) === true)
                    {
                        $result[$value] = $destination . $file;
                    }
                }
            }
        }
    }

    return $result;
}

Важными частями являются:

  • array_map('basename', ...), это гарантирует, что файл не содержит относительных путей.
  • ph()->Text->Slug(), это гарантирует, что в имени файла разрешены только .0-9a-zA-Z, все остальные символы заменяются символами подчеркивания (_)
  • md5_file(), это добавляется к имени файла, если еще один файл с тем же именем уже существует

Я предпочитаю использовать имя, предоставленное пользователем, так как поисковые системы могут использовать его для получения лучших результатов, но если это не важно для вас, просто microtime(true) или md5_file() может немного упростить.

Надеюсь, это поможет! =)

Ответ 2

Имя файла - произвольная строка, предоставленная пользователем. Как правило, никогда не доверяйте произвольным пользовательским значениям.

Вы не должны использовать имя, указанное пользователем, как имя для сохранения файла на сервере, всегда создавайте собственное имя файла. Единственное, что вы можете с ним сделать, это сохранить его как метаданные в информационных целях. При выводе этих метаданных принимайте обычные меры предосторожности, такие как санитария и экранирование.

Ответ 3

вам также нужно проверить наличие дубликатов имен. Слишком просто для нескольких людей загрузить изображение под названием "mycat.jpg", которое, если оно будет загружено в ту же папку, будет перезаписывать ранее загруженный файл с тем же именем. Вы можете сделать это, поместив уникальный идентификатор в имя файла (как предлагает Prix). Также убедитесь, что тип файла не просто заканчивается расширением изображения, но также является фактическим изображением; вы не хотите, чтобы ваш сервер действовал как слепой хост для случайных файлов.