<MyRusakov.ru />

Создание движка на PHP и MySQL 2.0

Создание движка на PHP и MySQL 2.0

Видеокурс "Создание движка на PHP и MySQL 2.0" научит Вас создавать профессиональные движки для сайтов на PHP и MySQL с использованием ООП и паттерна MVC.

В курсе разобрана вся теория по структуре движка: как всё устроено, какие должны быть объекты, какая у них иерархия и как они взаимодействуют между собой.

В практической части будет создан движок с чистого листа. Будет создано ядро, все адаптеры, все вспомогательные классы, а также классы для работы с объектами базы данных. И чтобы курс был максимально полезным, будет создан движок для сайта MyRusakov.ru.

Подробнее
Подписка

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Каким движком Вы предпочитаете пользоваться?

Безопасность при загрузке файлов на сервер в PHP

Безопасность при загрузке файлов на сервер в PHP

В прошлой статье мы с Вами разбирали загрузку файлов на сервер в PHP. Однако, я Вам уже сказал, что использовать код, который там был рассмотрен, категорически нельзя! И в этой статье мы поговорим о безопасности при загрузке файлов на сервер в PHP.

Давайте напомню код, который мы вчера рассматривали:

<?php
  $uploadfile = "images/".$_FILES['somename']['name'];
  move_uploaded_file($_FILES['somename']['tmp_name'], $uploadfile);
?>

Фактически, на данный момент может быть загружено абсолютно всё, что угодно: любые исполняемые файлы, скрипты, HTML-страницы и другие весьма опасные вещи. Поэтому обязательно надо проверять загружаемые файлы очень тщательно. И сейчас мы с Вами займёмся их тщательной проверкой.

Поскольку различных вариантов задач может быть очень много, мы рассмотрим вариант с загрузкой простого изображения, на которые должны накладываться следующие ограничения:

  1. Тип - только jpg (jpeg).
  2. Размер - менее 100 КБ.

Теперь реализуем скрипт "loading.php" в соответствии с этими требованиями:

<?php
  $blacklist = array(".php", ".phtml", ".php3", ".php4", ".html", ".htm");
  foreach ($blacklist as $item)
    if(preg_match("/$item\$/i", $_FILES['somename']['name'])) exit;
  $type = $_FILES['somename']['type'];
  $size = $_FILES['somename']['size'];
  if (($type != "image/jpg") && ($type != "image/jpeg")) exit;
  if ($size > 102400) exit;
  $uploadfile = "images/".$_FILES['somename']['name'];
  move_uploaded_file($_FILES['somename']['tmp_name'], $uploadfile);
?>

Теперь давайте подробно поясню, что здесь происходит. Первым делом мы проверяем на расширение загружаемого файла. Если оно представляет собой PHP-скрипт, то мы такой файл просто не пропускаем. Дальше мы получаем MIME-type и размер. Проверяем их на удовлетворение нашим условиям. Если всё хорошо, то мы загружаем файл.

Вы, наверное, можете спросить: "А зачем надо проверять и расширение, и MIME-type?". Тут очень важно понимать, что это далеко не одно и то же. Если злоумышленник попытается отправить PHP-файл через браузер, то и одной проверки MIME-type хватит, чтобы его попытка провалилась. А вот если он напишет какой-нибудь скрипт, который будет формировать запрос и отсылать вредосный файл, то этого не хватит. Почему? А потому, что MIME-type задаётся клиентом, а не сервером! И фактически, злоумышленник может поставить любой MIME-type (и картинки тоже), но при этом отсылать PHP-скрипт. И вот именно такую хитрую попытку мы и ломаем, проверяя на расширение файла.

Я сразу скажу, что данный код далеко не 100% защита (100% просто не существует), однако, взломать такой код будет очень и очень тяжело, поэтому можете смело утверждать, что Вы обеспечили высокую безопасность при загрузке файлов на сервер через PHP.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

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

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (46):

sync.o sync.o 30.05.2011 15:43:31

Столкнулся с такой проблемой. Если попытаться загрузить файл больше, чем "выдерживает" сервер (у меня на Denwer'e - 10Mb), то массив $_FILES вообще не заполняется, и проверить размер файла через $_FILES['somename']['size'] становится невозможным. Как тогда защитить свою форму от таких попыток?

Ответить

Admin Admin 30.05.2011 15:50:51

Никак. Это и не важно, так как никакой нагрузки на сервер всё равно не идёт. Такой файл просто даже не рассматривается, поэтому бояться не надо. Главное написать пользователям о максимальном размере файла для загрузки.

Ответить

Alim_(I) Alim_(I) 30.06.2011 13:59:30

А как сделать чтобы не только jpg принимался?

Ответить

Admin Admin 30.06.2011 14:16:38

Надо добавить при проверке mime-type и другие тоже. Например, image/png и/или image/gif.

Ответить

Alim_(I) Alim_(I) 30.06.2011 15:02:15

<span><span>То есть вот так?: <span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="yellow"> if </span><span>(($type<span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="cyan"> != </span>"</span></span><span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="lime">image/jpg</span><span>,g<span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="yellow">if</span><span><span>,bmp,png")<span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="lime"> && </span>($type</span><span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="cyan"> != </span>"image/jpeg,g</span><span id="dtx-highlighting-item" dtx-highlight-backgroundcolor="yellow">if</span>,bmp,png")) exit; Или как?</span></span> P.S. Только к gif png bmp привязать image/ .

Ответить

Admin Admin 30.06.2011 15:03:43

Нет. if ($type != "image/jpg") && ($type != "image/png") && ($type != "image/gif") и так далее

Ответить

int int 27.03.2015 09:07:16

Регулярные выражения очень медленные и лучше избегать ситуация использования их в цикле. поэтому предлагаю взять расширение регулярным выражением и потом просто прогнать через in_array где будет массив расширений. Так будет гораздо лаконичнее

Ответить

mg15 mg15 18.08.2011 08:30:55

Здравствуйте,Михаил! Такая проблема:я поменял в Вашем скрипте путь сохранения файла с images на images_gallery,но загружаемые картинки всё равно упорно сохраняются в папку images... // <? $blacklist = array(".php", ".phtml", ".php3", ".php4", ".html", ".htm"); foreach ($blacklist as $item) if(preg_match("/$item$/i", $_FILES['somename']['name'])) exit; $type = $_FILES['somename']['type']; $size = $_FILES['somename']['size']; if (($type != "image/jpg") && ($type != "image/jpeg")) exit; if ($size > 102400) exit; $uploadfile = 'images_gallery/'.$_FILES['somename']['name']; move_uploaded_file($_FILES['somename']['tmp_name'], $uploadfile); ?> Подскажите,что я не так делаю? Заранее спасибо! p.s.Всё заработало!Я не понял,в чем прикол был....наверно,магнитные бури!))))

Ответить

razo razo 21.10.2011 18:06:13

таким способом $blacklist = array(".php", ".phtml", ".php3", ".php4", ".html", ".htm"); foreach ($blacklist as $item) if(preg_match("/$item\$/i", $_FILES['somename']['name'])) exit; мы защищаемся от дос атак

Ответить

haker haker 21.12.2012 22:55:42

Михаил,а как подставить редактор tiny MCE в свою админку?

Ответить

Admin Admin 22.12.2012 10:32:47

На официальном сайте есть подробная инструкция http://www.tinymce.com/wiki.php/Installation Если плохо знаете английский, то есть сайт http://translate.google.com

Ответить

haker haker 22.12.2012 10:46:53

Михаил,в меня токой вопрос,а в курсе с нуля до гуру Вы будите какой движок делать?

Ответить

Admin Admin 22.12.2012 13:06:55

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

Ответить

haker haker 22.12.2012 16:46:30

Михаил,я перечислил деньги за курс.Там проверьте свою почту там есть время оплаты и номер квитанции.Спасибо.

Ответить

maks1232123 maks1232123 22.12.2012 17:45:54

Михаил,а после перечисление денег за курс Вам указывать что надо??

Ответить

Admin Admin 22.12.2012 18:14:44

Зависит от способа оплаты.

Ответить

maks1232123 maks1232123 22.12.2012 19:24:51

Михаил,а как установить апачь сервер и создать свой сервер из компа?

Ответить

Admin Admin 22.12.2012 21:29:31

http://myrusakov.ru/php-make-server.html

Ответить

Adrenalin Adrenalin 05.03.2013 20:25:25

С момента написания статьи прошло больше года. Сейчас ты используешь дополнительную защиту для загрузки изображений? Какую? Можно пример :)

Ответить

Admin Admin 05.03.2013 21:40:05

Не использую.

Ответить

Adrenalin Adrenalin 06.03.2013 01:24:05

У меня папка для фото: foto Проверку mime пытаюсь выполнить так: $imageinfo = getimagesize($_FILES['somename']['tmp_name']); if($imageinfo["mime"] != "foto/gif" && $imageinfo["mime"] != "foto/GIF" && $imageinfo["mime"] != "foto/jpeg" ... Или нужно обязательно вот так: if($imageinfo["mime"] != "image/gif" && $imageinfo["mime"] != "image/GIF" && $imageinfo["mime"] != "image/jpeg" ...

Ответить

Admin Admin 06.03.2013 04:15:43

Mime-type foto не существует, поэтому только второй вариант.

Ответить

Adrenalin Adrenalin 06.03.2013 16:48:44

Понял. А что конкретно значит эта строка: $uploadfile = "images/".$_FILES['somename']['name']; move_uploaded_file($_FILES['somename']['tmp_name'], $uploadfile);

Ответить

Admin Admin 06.03.2013 23:17:26

Первая строка - это имя будущего файла, а вторая строка - это перемещение данных из временного файла в этот новый файл.

Ответить

Adrenalin Adrenalin 07.03.2013 02:51:11

Но это ещё не сохранение? Потому что у меня для этого существует свой каталог. Эти строки его нигде не скопируют?

Ответить

Admin Admin 07.03.2013 09:45:13

Это уже сохранение.

Ответить

Evg Evg 14.03.2013 21:41:56

Круто все объясняешь, молодец и спасибо тебе за это. Прочитал уже статьи про регулярные выражения, только не пойму $item\$ - это строки, которые заканчиваются на $item. а зачем тогда обратный слэш перед мета $? это мы его экранируем что ли? после переменных всегда так делается?

Ответить

alikhanov_k@mail.ru alikhanov_k@mail.ru 15.04.2013 11:13:02

Здравствуйте! Скрипт хорошо работает, спасибо вам. Только есть одно но... Если загружать файлы больше 100 кб, то экран становится белым и ничего там нет! Можно ли сделать вывод надписи вроде "Ошибка размер больше 100 кб!" или что-нибудь похожее?

Ответить

Admin Admin 15.04.2013 11:31:44

Можно, например, вместо exit можно поставить echo с соответствующим сообщением.

Ответить

alikhanov_k@mail.ru alikhanov_k@mail.ru 15.04.2013 11:47:13

Спасибо работает! А как сделать чтобы было сообщение о загрузке изображении. То есть если ошибка то пусть пишет "Error" а если загрузил то пусть пишет "ОК". Я полный Чайник в php, сижу с утра и не могу сделать это сам.

Ответить

Admin Admin 15.04.2013 12:51:03

Нужно освоить для начала оператор if, а затем move_uploaded_file($_FILES['somename']['tmp_name'], $uploadfile) - вот это поместить внутрь if, и если функция вернула true, значит, вывести, что файл загружен, иначе вывести ошибку.

Ответить

alikhanov_k@mail.ru alikhanov_k@mail.ru 15.04.2013 13:12:31

Спасибо большое все работает!

Ответить

kumakbtu kumakbtu 05.05.2013 22:04:57

$size > 102400 Здесь размер в битах показано?

Ответить

Admin Admin 06.05.2013 10:02:03

В байтах.

Ответить

t00039_jack t00039_jack 09.05.2013 23:13:40

Здравствуйте Михаил. У меня массив $_FILES пустой. В какой момент он заполняется и почему он может быть пустым ?

Ответить

Admin Admin 10.05.2013 11:47:13

Заполняется при отправке. Возможно, не указан атрибут enctype у формы.

Ответить

t00039_jack t00039_jack 11.05.2013 10:48:37

Спасибо, всё получилось. В enctype была опечатка.

Ответить

t00039_jack t00039_jack 11.05.2013 14:48:39

Здравствуйте Михаил. При попытке загрузить файл получаю сообщение: "Warning: POST Content-Length of 9956836 bytes exceeds the limit of 8388608 bytes in Unknown on line 0" Это ограничение метода POST или результат настроек сервера ?

Ответить

Admin Admin 11.05.2013 14:59:26

Это настройки сервера: http://myrusakov.ru/php-load-bigfile.html

Ответить

ketovpavel ketovpavel 30.07.2013 08:53:27

Привет, Михаил! Скрипт полезный весьма благодарин вам за это. Есть вопрос: Как сделать так чтоб все картинки при загрузке переименовывались в уникальные названия например вот этим способом: $token = md5(uniqid("")); $better_token = md5(uniqid(rand(),1)); Подскажите пожалуйста, куда его нужно прописать, чтоб применить этот способ вот в этот скрипт? Суть проблемы такова что при загрузке картинок сохроняются русские символы и при совпадении названия перезаписываются сами изображения

Ответить

ketovpavel ketovpavel 30.07.2013 11:02:29

Всё я сам решил! Добавил просто в скрипт следующий код: $uploadfile = "./uzer/images/".$_FILES['somename']['name']; $newfile = "./uzer/images/".$_FILES = md5(uniqid(rand(),1)).'.jpg'; rename($uploadfile, $newfile) or die("Unable to rename $uploadfile to $newfile.");

Ответить

vira vira 02.08.2013 09:02:35

Здравствуйте Михаил! У меня такой вопрос,можно ли при загрузке сделать чтобы файл переименовался? у меня не получается код вот такой: $type = $_FILES['filename']['type']; $size = $_FILES['filename']['size']; if ($size > 4194304) { echo("<b>Размер файла превышает четыре мегабайта</b><br>"); exit; } if (($type != "image/jpg") && ($type != "image/jpeg")&& ($type != "image/JPG")&& ($type != "image/JPEG")){ echo("<b>Вы можете загружать только jpg и jpeg</b><br>"); exit; } $uploaddir = './img/'; $file = $uploaddir . basename($_FILES['filename']['name']); if (move_uploaded_file($_FILES['filename']['tmp_name'], $file)) echo "<b>Файл загружен</b><br>"; else { echo "<b>Ошибка загрузки файла</b><br>";exit; }

Ответить

Admin Admin 02.08.2013 16:04:26

Можно, в move_uploaded_file() сразу и передаете нужное имя.

Ответить

phrenicum phrenicum 27.08.2014 13:10:24

Михаил, здравствуйте! Создавал хостинг изображений по бонусу из вашего курса PHP и MySQL с Нуля до Гуру, но возникла проблема: на странице вывода изображений выводится такая ошибка - "Fatal error: Call to private method Image::loadImage() from context '' in V:\home\localhost\www\myproject\show_image.php on line 3". 3 ряд совпадет с Вашим в обучающем видео. Как решить эту проблему?

Ответить

tikkiwiki tikkiwiki 01.09.2014 10:06:26

Ошибка может быть не обязательно в третьем ряду. Вообще интерпретатор Вам поясняет : Что Вы не можете получить доступ к защищенным методам из экземпляра класса. Чтобы получить доступ к защищенному методу родительского класса из экземпляра подкласса Вы должны объявить открытый метод в подклассе, а затем вызвать защищенный метод родительского класса от открытого метода подкласса.

Ответить

wapj wapj 21.09.2015 03:47:38

Почему пропускает файл mp4 после чего выводится 2 ошибки: 1 - Warning: POST Content-Length of 130113051 bytes exceeds the limit of 8388608 bytes in Unknown on line 0 2 - Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent in Z:\home\**********\www\*********\controller.php on line 6 Как этого избежать?

Ответить

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.