Безопасная загрузка изображений с помощью PHP?

Я хочу загружать изображения на свой сервер из окна браузера. Однако поле загрузки будет видно всем, поэтому мне нужно установить некоторые ограничения. Я нашел только загрузку файла w3schools (а что касается w3fools.com, я ему не доверяю). Я хочу, чтобы ограничения были:

Максимальный размер 2,5M

Типы изображений jpg, jpeg, png, gif

Итак, вот код, который предоставляет w3schools, но он никуда не сохраняет файл? Я немного изменил его, чтобы удовлетворить мои потребности.

<?php
$allowedExts = array("jpg", "jpeg", "gif", "png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/jpeg"))
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 2500000)
&& in_array($extension, $allowedExts))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Error: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Stored in: " . $_FILES["file"]["tmp_name"];
    }
  }
else
  {
  echo "Invalid file";
  }
?>

И поскольку я не хочу, чтобы мой сайт был взломан, мне нужно безопасное решение, любая помощь в этом?

Изменить

Код даже ничего не делает. Итак, как мне это сделать?


person Community    schedule 27.09.2012    source источник
comment
Я думаю, вам следует взглянуть на stackoverflow.com/a/10271295/1226894, он отвечает на ваш вопрос.   -  person Baba    schedule 27.09.2012
comment
Поскольку вы принимаете только изображения, вы также можете посмотреть stackoverflow.com/a/10464964/1226894, где вы узнаете, как лучше обнаружить поддельные изображения   -  person Baba    schedule 27.09.2012
comment
@Baba Я использовал предоставленный вами код и вышел на улицу со своей собакой. Когда я вернулся, мой сайт wordpress был заменен на !X!X HACKED BY RUSSIAN PEOPLE !X!X и российский флаг под ним. Я взглянул на загрузку изображения и заметил несколько странных файлов в папке загрузки, а в папке index был файл hack.php, который я посмотрю. Однако файл был загружен с вашим скриптом, и мой сайт был взломан. Как?   -  person    schedule 27.09.2012
comment
Возможно, это не единственная дыра на вашем сайте ... вам нужно будет проверить весь сайт.   -  person Baba    schedule 27.09.2012
comment
Я просто делаю это, и у меня была только одна загрузка файла на весь сайт.   -  person    schedule 27.09.2012
comment
Что заставляет вас думать, что единственный способ взломать сайт my wordpress site вы говорите, что Wordpress - это только один файл ??? нет смысла вам отвечать   -  person Baba    schedule 27.09.2012
comment
Ну и почему все файлы, используемые для взлома, находятся в каталоге uploads?   -  person    schedule 27.09.2012
comment
@Baba это правда, что ваш код содержит дыры в безопасности, однако я думаю, что вам не следует удалять его, поскольку для большинства лучше всего подходят упрощенные примеры (легче читать и понимать). В зависимости от версии/конфигурации сервера может быть, что простой атаки с нулевым символом достаточно, чтобы пропустить ваши проверки расширений, и если сервер настроен так, что каждый может выполнить любой файл .php из любого каталога, просто отправив HTTP-запрос... нет необходимости объяснять больше. Никогда не доверяйте пользовательскому вводу и используйте функции, которые могут обрабатывать любые двоичные последовательности, а не только обычный текст. Или используйте шаблоны для данных.   -  person Sampo Sarrala - codidact.org    schedule 27.09.2012


Ответы (3)


Вам нужно использовать функцию php move_upload_file, а также я внес изменения в ваш оператор if, вот рабочий и проверенный пример:

<?php

if (isset($_REQUEST["submit"])) {

    $allowedExts = array("jpg", "jpeg", "gif", "png");
    $extension = end(explode(".", $_FILES["file"]["name"]));

    if ($_FILES["file"]["type"] == "image/gif" || $_FILES["file"]["type"] == "image/jpg" || $_FILES["file"]["type"] == "image/jpeg" || $_FILES["file"]["type"] == "image/png" && $_FILES["file"]["size"] < 2500000 && in_array($extension, $allowedExts)) {

      if ($_FILES["file"]["error"] > 0) {

        echo "Error: " . $_FILES["file"]["error"] . "<br />";

      }
      else {

        $fname = $_FILES["file"]["name"];
        move_uploaded_file($_FILES["file"]["tmp_name"], $fname);

        echo "Upload: " . $_FILES["file"]["name"] . "<br />";
        echo "Type: " . $_FILES["file"]["type"] . "<br />";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
        echo "Stored in: " . $fname;

      }

    }
    else {

      echo "Invalid file type";

    }

}
?>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" name="submit" value="submit" />
</form>

Вы также можете использовать функцию getimagesize, как было предложено, выполнив следующее:

$size = getimagesize("http://www.simplestudio.rs/060620121945.jpg");

$file_format = $size['mime'];

$file_format будет представлен, например, как «image/jpeg», поэтому вы можете легко проверить типы изображений следующим образом:

foreach($allowedExts as $allowed) {

$chk_types = strpos($file_format, $allowed);

if($chk_types > -1) {
$type_is_good = true;
break;
}

}
person Develoger    schedule 27.09.2012
comment
Да, он добавляет изображение и показывает информацию о нем, но безопасно ли это? Я попытался загрузить файл .crx, и это не удалось, но есть ли какие-либо способы это сделать? - person ; 27.09.2012
comment
Я отредактировал свой ответ, добавив использование getimagesize, так как он намного безопаснее, чем $_FILES[file][type]. Кроме того, вы можете проверить пользовательский агент в качестве базовой проверки для ботов (даже это может быть подделано ботом). Но не стесняйтесь искать в Google дополнительную информацию о безопасности загрузки изображений... - person Develoger; 27.09.2012

Использование: move_uploaded_file, См. Руководство

И еще кое-что,

переменную $_FILES["file"]["type"] использовать не рекомендуется, так как ее можно изменить в настройках браузера.

Вместо этого используйте getimagesize, см. Руководство.

person Vipin Jain    schedule 27.09.2012

person    schedule
comment
Добро пожаловать в Stack Overflow. Извините, но я просто не могу понять, что вы пытаетесь здесь сказать. Вам нужно будет переформатировать свой код (я пытался, но отказался) и дать некоторое объяснение, почему он полезен. - person michaelb958--GoFundMonica; 21.07.2013