Безопасность Cайта
Вступление:
Во все времена существования сайтов, большие и успешные игроки интернет-бизнеса есть те люди, сайты которых защищены от взломов и передачи информации третьим лицам. Об этом в интернете написано множество статей с советами о безопасности сайтов. Но, к сожалению, придерживаясь других рекомендаций, Вы не обезопасите свой сайт даже на 30%. Поэтому я решил написать эту статью, цель которой дать все полные рекомендации, о которых не знают большинство, для самой высокой безопасности Ваших интернет-ресурсов!
Неоспоримая безопасность обеспечивается комплексным подходом на уровне сервера, приложения, домена и как показывает практика, очень много сайтов взламываются из-за неполноценного подхода к обеспечению безопасности.
Безопасность на уровне сервера
Хостинг, или VPS
Хостинг, безусловно, более доступный в плане ценовой политики, для хранения сайтов в сравнении с выделенным сервером (VPS / VDS). Для ответа на вопрос о безопасности, предлагаю рассмотреть недостатки хостинга:
- Много сайтов на одном ПК. Количество колеблится от 100 до 1 000 и никто не даст гарантию, что у каждого из них с безопасностью все хорошо. Для взлома сервера, хакеру достаточно найти уязвимый сайт и взломать его.
- Отсутствие возможности индивидуальной установки конфигурации ОС, Apache и PHP. На хостингах настройки выставлены по умолчанию и риски взлома увеличиваются.
- Один интернет "шнурок" для всех сайтов. Отправляя множество запросов и мусора в ед. времени на сайты, лежащие на одном ПК, хакер добивается перегрузки на "шнурок", что приводит к длительной, или невозможной загрузки страниц другими посетителями.
В отличии от хостинга VPS /VDS открывает возможность самостоятельной установки с настройкой ОС, конфигурации сервера, и интерпретатора индивидуально, для каждого проекта. Из-за отсутствия сайтов-соседов безопасность зависит только с Вашей стороны. Аренда VPS / VDS заметно дороже, но в соображении безопасности оно того стоит!
Защита панели хостинга
Если атакуемый хакерами сайт написан на чистом коде качественно, то это толкает на крайние меры — взлом хостинга (сервера), а точнее подбор пароля в панель хостинга. Сайт — это файлы с программным кодом, которые хранятся на сервере и обрабатываются при запросе клиента (браузера), для получения конкретной страницы. В этой ситуации безопасность сервера очень важна. Риски взлома возрастают из-за наличия некачественных по коду сайтов-соседов, которые можно очень легко взломать и навредить Вашому ресурсу. На многих хостингах и серверах панель управления не защищена 2-х уровневой авторизацией. К примеру, подтверждение входа, после ввода правильного логина и пароля через почту, или СМС. Не исключение, что в готовых панелях, например, VestaCP возможны уязвимости. Для более высокой безопасности рекомендательно собрать свой сервер, установив на него ОС класса Unix. После этого шансы взлома сервера резко уменьшаются за счет отсутствия панелей управления и некачественных сайтов-соседов, собранных на готовых CMS, Framework.
Fail2Ban
Эта программа блокирует все IP-адреса вредителей, усердно пытающихся подобрать пароль, например, к FTP, файловому менеджеру, консоли SSH. Устанавливается только на выделенный сервер вместе с панелью VestaCP, или отдельно, если панель управления сервером отсутствует.
Безопасность FTP
По умолчанию на серверах и хостингах 21 порт (ФТП) открыт для всех и подобрать пароль не составит труда. Эффективный способ защиты - это закрытие 21 порта FTP для всех, с помощью файла ".ftpaccess" помещенного в базовую директорию, разрешенную для Apache:
<Limit ALL>
Deny from all
</Limit>
В примере выше доступ по ФТП закрыт всем, а это значит, что подбор пароля невозможен. Но если требуется регулярно использовать 21 порт для обмена файлами с сервером — напишите скрипт, который после успешной многоуровневой авторизации допишет в файл Ваш IP и всех авторизованных юзеров, а после завершения использования ФТП - удалит IP с файла.
<Limit ALL>
Deny from all
Allow from 130.180.211.174
</Limit>
Модуль mod_sequrity
Безопасность в основном зависит от сценариев и программистов, которые их пишут, но для защиты нужно использовать по максимуму все возможности. Модуль mod_security анализирует входящие HTTP-запросы на сервер и принимает решение, пропускать запрос, или нет, на основе заданных администратором правил. Идентичность работы модуля сравнима с сетевым экраном встроенного в ОС.
Установка молудя возможна после скачивания с сайта www.modsecurity.org. Загруженный файл модуля необходимо положить в папку "modules" и включить его в конфигурационном файле Apache httpd.conf, после чего перезагрузить сервер.
Рассмотрим дополнительные, не менее важные правила фильтрации запросов:
- SecFilterEngine On — включает режим фильтрации запросов;
- SecFilterCheckURLEncoding On — проверяет кодировку (URL encoding isvalid);
- SecFilterForceByteRange 32 126 - задает диапазон разрешенных символов. Символы, с кодом менее 32 принадлежат классам служебных символов, например: "перевод каретки", "конец строки". Большинство из подобных символов невидимы, но им принадлежат соответствующие коды. Хакеру нереально ввести в URL запроса невидимы символы, зато реально ввести их коды. Чтобы указать, например, символ с кодом 13, нужно написать в URL запросе %13. Поэтому запросы, содержащие символы в диапазоне менее 32 и более 126 не нужно пропускать к серверу.
- SecAuditLog logs/audit_log — задает имя файла журнала, в котором будет сохраняться информация об аудите;
- SecFilterDefaultAction "deny,log,status:406" — задает действие по умолчанию. В данном случае указан запрет на доступ (deny);
- SecFilter xxx redirect:http://domain.com — при срабатывании фильтра пользователя переадресуют на Web-сайт domain.com;
- SecFilter yyy log,exec:/home/apache/report-attack.pl — если фильтр срабатывает, то будет выполнен сценарий /home/apache/report-attack.pl;
- SecFilter /etc/password — в запросе не должно быть обращений к файлу /etc/passwd. Таким же образом нужно добавить запрет к обращению и к файлу /etc/shadow;
- SecFilter /bin/ls — в запросах не должно быть обращений к программам. В данном случае запрещается команда ls, позволяющая хакеру просматривать содержимое каталогов, если в сценарии есть ошибка. Необходимо запретить обращения к командам cat, rm, cp, ftp и др.;
- SecFilter "\.\./" — классическая атака, когда в URL указываются символы точек. Такие запросы нужно отклонить;
С основными правилами Вы знакомы. Больше правил можно найти на сайте разработчиков этого модуля.
Модуль mod-evasive
Защитой от DDOS атак в Apache служит модуль mod-evasive для отслеживания количества HTTP-запросов к сайту и страницам, за указаный промежуток времени с конкретного IP и его блокировке на определенное время, при нарушении заданных условий.
После занесения в черный список IP злоумышленника, при попытках открыть сайт снова, приложение Apache все-равно открывается, но теперь вместо страницы сайта, будет возвращена ошибка с кодом 403. Иначе говоря, конкретной блокировки IP нет. В этом случае, Apache не тратит ресурсы и время на вызов PHP, а сразу выдает error 403.
Посылая запросы в большом количестве, http сервер Apache вынужден отклонять их с кодом ответа 403, забирая при этом все ресурсы сервера на эти действия. Если Вы пользуетесь выделленым сервером, mod-evasive устанавливать стоит, поскольку сервер будет легче положить, если на запросы хакера Apache будет вызывать ещё и приложение PHP.
Установка в Ubuntu запускается командой:
sudo apt-get install libapache2-mod-evasive
Для создание файла настроек запустите команду:
sudo touch /etc/apache2/mods-available/mod-evasive.conf
Откройте файл настроек:
sudo nano /etc/apache2/mods-available/mod-evasive.conf
Вставьте и настройте условия для mod-evasive:
<IfModule mod_evasive20.c>
DOSHashTableSize 4096
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 300
DOSEmailNotify admin@site.com
</IfModule>
Описание доступных опций:
- DOSHashTableSize — размер хэш-таблицы, обрабатывающей запросы к веб-серверу
- DOSPageCount — число запросов к одной странице от одного IP в течение заданного интервала времени.
- DOSSiteCount — число запросов ко всему сайту с одного IP в течение заданного интервала времени.
- DOSPageInterval — интервал времени для директивы DOSPageCount (в секундах)
- DOSSiteInterval — интервал времени для директивы DOSSiteCount (в секундах)
- DOSBlockingPeriod — время в секундах на блокировку IP
- DOSEmailNotify — e-mail для отправки уведомления о блокировке
- DOSSystemCommand — команда, которая будет выполнена при блокировке IP. В переменную «%s» передается адрес блокируемого IP)
- DOSWhiteList — список белых IP адресов, можно и по маскам (напр. 192.168.1.*). Можно указать свой IP.
После настройки необходимо сохранить файл и выйти из редактора. Включим модуль mod-evasive и чтобы изменения вступили в силу, перезагружаем Apache:
sudo a2enmod mod-evasive
sudo service apache2 restart
Напомню, что этот модуль устанавливается на выделенный сервер. Это значит на хостинг его установить нереально. И все-же хостинг можно защитить, написав приложение на PHP, логику которого рассмотрим ниже на этой странице.
Запрет на выполнение сценариев в ненужных местах
Возможность запустить скрипт в папке, служащей для хранения изображений, CSS и JavaScript кода может привести к неожиданным последствиям, а запретить подобное достаточно просто. Для этого создайте файл ".htaccess" и положите в папку, в которой необходимо запретить выполнение кода:
<FilesMatch "\.([Pp][Hh][Pp]|[Cc][Gg][Ii]|[Pp][Ll]|[Ph][Hh][Tt][Mm][Ll])\.?.*">
Order allow,deny
Deny from all
</FilesMatch>
После этого, прямой заход в папку и попытка запуска файла с кодом неосуществимы, а запрос будет переадресован на страницу 404.
Ещё один способ запрета выполнения скриптов - это команда отключения запуска PHP-движка в файле .htaccess: php_flag engine off. В отличии от способа выше, файлы PHP будут открываться, как текстовые файлы, а хакер сможет просмотреть их содержимое.
Просмотр содержимого папки со скриптами
Сайт пишется на коде и файлы с кодом хранятся в определенных папках, содержимое которых можно просмотреть обратившись к ним напрямую. Защитой от этого служит запрет на индексирование с помощью файла ".htaccess" и командой запрета:
Options All —Indexes
После чего, просмотр содержимого папки и всех вложенных файлов и папок невозможно, а так же эту папку невозможно увидеть в списке, где просмотр содержимого не запрещен.
Прямое обращение к файлам
На практике, довольно часто, возникает необходимость запретить прямое обращение ко всем файлам с определенным типом, или к конкретному файлу. Команда в файле ".htaccess" реализует это.
<Files ~ ".bd|777.zip">
Order Deny,Allow
Deny from all
</Files>
В этом примере запрещено прямое открытие всех файлов с расширением ".bd" и конкретного zip-архива с названием "777.zip". Через разделитель "|" можно указывать необходимое количество файлов, доступ к которым через URL необходимо запретить вообще.
index.php в URL
Очень часто при наличии "index.php" в теле запросе заканчивается ошибкой в приложении, чем и пользуется хакер, для просмотра место хранения файла, в котором эта ошибка возникла. Воспрепятствовать подобному можно, добавив команду в корневой ".htaccess", которая перенаправит запрос на страницу 404, при обнаружении подобного.
RewriteEngine On
RewriteRule ^(.*)index\.php$ $1 [R=404,L]
Хотлинк
Вставка URL изображений Вашего сайта на другой называется хотлинком. Этот момент относится к безопасности. Скопировав прямой URL-адрес изображений требуемого количества и вставив на другой сайт, с большой посещаемостью, хакер добивается перегрузки "интернет-шнурков" Вашего сервера. Для защиты от хотлинка необходимо запретить загрузку изображений с других сайтов, кроме поисковых систем. Для этого в корневом файле .htaccess прописываем условия:
RewriteCond %{HTTP_REFERER} !^$
#Далее список разрешенных сайтов
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?kwo-master.com (наш домен).*$ [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yandex.ru [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?google. [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?msn. [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yahoo. [NC]
RewriteCond %{HTTP_REFERER} !search?q=cache [NC]
#Список запрещенных для хотлинка форматов
RewriteRule \.(jpe?g|bmp|gif|png|webp|css|zip|pdf|txt|doc)$ - [NC,F,L]
Теперь наши изображения другие сайты загружать не смогут. Но и это можно очень легко обойти, подделав заголовок HTTP_REFERER. Пример подделки заголовка показывать не буду.
Безопасность PHP системного уровня
HTTP-сервер принимает запрос и если запрос не доставляет никаких сомнений - открывается интерпретатор, выполняющий файлы сайта. Самый быстрый и популярный, как не странно, приложение PHP, к настройке которого необходимо подойти крайне внимательно и ответственно! Конфигурационный файл php.ini содержит в себе множество гибких настроек и индивидуальное конфигурирование обязательно!
Отключение опасных функций
В язык php встроено несколько тысяч функций и среди них есть функции, воспользовавшись которыми хакер может получить доступ к ini-файлам, выполнить php-код из строки, что недопустимо. С помощью "disable_functions" можно отключить подобные функции вообще, уменьшив риск взлома.
disable_functions = ini_get, ini_get_all, parse_ini_file, passthru, php_uname, proc_open, shell_exec, show_source, system, popen, eval, posix_getpwuid, posix_getgrgid, posix_uname
Вот так выглядят параметры конфигурации PHP
Все функции, указанные в disable_functions не будут выполняться. Безусловно, можно добавить и другие функции, если таково требует безопасность.
- ini_get — получает значение опции конфигурации
- ini_get_all — получает все опции конфигурации
- parse_ini_file — чтение и разборка файла конфигурации
- passthru — выполняет внешнюю программу и выводит сырой вывод
- php_uname — возвращает информацию об ОС, на которой установлен РНР.
- proc_open — выполняет команду и открывает файловый указатель для ввода/вывода.
- shell_exec — выполняет команду в оболочке/shell и возвращает полный вывод в виде строки.
- show_source — выделение синтаксиса файла.
- system — выполняет внешнюю программу и отображает вывод.
- popen — открывает файловый указатель процесса.
- eval — вычисляет строку как PHP-код.
- posix_getgrgid — возвращает информацию о группе по её group id.
- posix_uname — получает системное имя.
Конфигурационные переметры php.ini стоящие внимания:
- max_execution_time — устанавливает максимальное время в сек. на выполнение PHP скриптов. По умолчанию равна 30 сек
- max_input_time — время на прием данных методом POST. По умолчанию 60 сек.
- max_input_vars — устанавливает максимальное количество принятых переменных GET | POST | COOKIE. Количество по умолчанию 1000. рекомендуемое значение - 40.
- memory_limit — устанавливает максимальный объем выделяемой оперативной памяти, для обработки каждого пользователя. По умолчанию - 128M
- post_max_size — указывает максимально допустимый размер, для отправки данных методом POST. По умолчанию - 8M
- upload_max_filesize — указывает максимально допустимый размер загружаемого файла методом POST. По умолчанию - 2M
- max_file_uploads — указывает максимальное количество файлов, которые может принять сервер одним запросом, с помощью POST. По умолчанию - 20
- file_uploads — По умолчанию - "On" (разрешает загрузку файлов на сервер). Если надобности в приеме файлов нету - рекомендательно установить значение "Off"
Безопасность на уровне приложения
Важный момент о _SESSION.
Чуть ли ни каждый разработчик по своему незнанию и небольшому опыту доверяет заданным по умолчанию конфигурациям сессий, не подозревая, какое это зло и как может этим воспользоваться хакер. Сессии широко используют в популярных задачах, например: регистрация, каптча, голосования и многие другие. Файлы сессий хранятся на сервере в одной папке и хакеру / злоумышленнику наплодить их, имитируя реальных пользователей, используя сокеты, платные сервисы покупки заданий очень легко.
В процессе создания интерпретатор PHP кладет файл сессии в одну директорию, а как Вы знаете, время хранения по умолчанию равно 1440 сек. Многие заблуждаются, убеждая себя об окончательной ликвидации файла _SESSION спустя 1440 сек. Но увы... Не тут-то было... Сессия продолжает хранится на сервере, занимая при этом место на диске.
Чтобы резко уменьшить шансы на размножение сессий, необходимо прибегнуть к файлу php.ini с конфигурациями сессий, путем увеличения вероятности срабатывания функции уборщика мусора. Рассмортим важные параметры:
- session.save_path - задает директорию хранения сессий. Обязательно снимите комментарий и укажите директорию в корне всех сайтов.
- session.auto_start - будет ли при каждом старте PHP запускаться модуль инициализации сессии. По умолчанию - 0 (отключено). Далеко не во всех ситуациях используются сессии, поэтому заданное значение по умолчанию рекомендательно оставить.
- session.cookie_lifetime - задает время существования файла cookie в секундах, хранящего ID-сессии пользователя. По умолчанию - 0 (до перезапуска браузера).
Замечание: когда сессия создана - файл хранится на сервере заданное количество сек., а кука с ID в таком случае до закрытия браузера. В промежутке существования файла сессии на сервере, при закрытии браузера, файл куки удалится, что заставит сервер создать новую сессию и куку для Вас. Если пользователю действительно нужна кука с ID-сессии до самого конца жизни файла сессии - необходимо указать время, которое равно времени жизни самого файла сессии на сервере. - session.gc_probability - в сочетании с session.gc_divisor определяет вероятность запуска функции сборщика мусора (файлов сессий, время которых превысило время их жизни). По умолчанию равен 1
- session.gc_divisor - в сочетании с session.gc_probability определяет вероятность запуска функции сборщика мусора при каждой инициализации сессии. Значение по умолчанию равно 100. Вероятность рассчитывается формулой: gc_probability/gc_divisor, то есть 1/100 означает, что функция-уборщик запускается в одном случае из ста, или 1% при каждом запросе.
Замечание: при высокой посещаемости таковой вероятности запуска может оказаться недостаточно. Рекомендую увеличить вероятность запуска функции уборки мусора, например, 30% из 100%, изменив параменты gc_probability=30 и gc_divisor=100. - session.gc_maxlifetime - позволяет задать время в секундах, по истечении которого файлы сессий будут восприниматься функцией-уборщиком, как мусор. По умолчанию - 1440 сек. Строго не рекомендуется увеличивать это значение. Оптимальное значение - 900 сек.
- session.sid_length - задает длину генерируемого ID-сессии. Длинна колеблится от 22 до 256 и по умолчанию равно 26. Чем длиннее ключ ID - тем сложнее его подобрать. Рекомендуемое значение от 32 символов.
С помощью файла .htaccess разрешается указывать для каждого сайта свою директорию хранения файлов сессий. В таком случае, функция уборки мусора будет срабатывать на директорию, заданную в файле php.ini.
Остальные конфигурации изложены на оф. документации по PHP.
Защита от флуда
Начинающие хакеры пытаются флудить. Что это такое? К примеру, у Вас на сайте есть форма, для отправки данных. Это может быть форма регистрации, поиска и отправки сообщения на форум. В этой ситуации есть классная возможность завалить сервер сообщениями, или наплодить кучу зарегистрированных пользователей.
Одним из способов защиты от подобной атаки будет запрет на отправку формы с одного и того же IP-адреса, в конкретную единицу времени. Логика в сценарии следующая:
- После отправки формы, сервер принимает IP-адрес, с переменной $_SERVER["REMOTE_ADDR"] и текущее время функцией time().
- Вторым этапом воспроизводится поиск IP в базе и если он существует - скрипт получает время. Если, например, не прошло более 2-х минут - время обновляется на текущее и форма не принимается.
- И последнее. Если IP-адреса в базе не найдено - записываем его и текущее время, а затем удаляем старые IP-адреса, где время более 2-х минут.
Убедившись в присутствии таковой защиты, злоумышленники не будут "флудить" на сервере, поскольку это отнимает много времени и скорее всего Ваш сервер будет оставлен в покое.
Недостаток этого способа в следующим: много пользователей скрыты за прокси-серверами, и все они видны в сети под одним и тем же IP-адресом. Если кто-то из них, в попытке "флуда", засветится в базе — другие пользователи не смогут отправлять форму в течении заданного в скрипте времени.
CAPTCHA
Каптча используется в целях проверки данных с гарантией, что их отправил человек, а не бот. Такая проверка в сети интернет очень актуальна. Злоумышленник желая навредить сайту пишет скрипт, который будет "флудить", а именно накручивать голосование, регистрироваться, отправлять формы обратной связи. Правильно написанная каптча заставит злоумышленника прилагать собственные усилия и много времени, для прохождения проверки. Варианты каптчи могут быть реализованы в виде:
- Картинки с проверочным кодом, который нужно ввести.
- Математической задачи, или вопроса, на который нужно ответить.
Каптча служит эффективным способом защиты отправляемых на сайт форм. Для накрутки 10-ти голосов, злоумышленнику необходимо 10 раз правильно ввести каптчу.
Очень часто хакеры пишут программы, способны распознавать каптчу и для этого необходимо программно генерировать шумы на изображении:
- Покрыть фон и код точками. Для этого необходимо создавать цикл, что является ресурсоемким действием.
- Заранее подготовить картинку, а лучше несколько десяток, или сотен разных картинок с шумом (линиями, точками) и рисовать код каптчи на холсте изображения. Для хорошего результата нужно, чтобы цвет фона каптчи и шума сливался с кодом. Теперь все будет сливаться, и распознать образы программно станет проблематично. Но если картинка фона статична, все-равно возможно очистить шум программно.
- Генерировать цвет, фон, несколько линий и в хаотичном порядке рисовать цифры, буквы. На мой взгляд этот способ лучше за предыдущие, но распознать код на картинке возможно.
Написание программы по распознаванию каптчи - задача не из лёгких, да и сам интернет-ресурс должен быть крайне популярным, чтобы заинтересовать серьезного хакера, для реализации распознавания проверочного кода.
Проверка форм на сервере
Не доверяйте проверкам форм со стороны браузера с помощью HTML и JavaScript. Простому спамеру это мешает, но не хакеру. Любую форму можно подделать многими способами и отправить галлон некорректных данных на сервер, заставив приложение работать неправильно в своих интересах.
После получения данных из формы на сервере, обязательно нужно проверить:
- Количество переменных из форм. Если количество ел. массива count($_POST) не равно количеству полей из формы - прекратить скрипт. Рекомендую даже вывести сообщение об успешном проведении операции.
- длину данных всех полей и если их меньше / больше нормы — прекратить скрипт, выводя сообщение об успехе.
- Удалить из каждого поля HTML и PHP-теги, ненужные символы, и другие опасные данные. Принимать текстовые поля нужно следующим набором функций:
$login='';if(isset($_POST['login'])){$login=htmlspecialchars (stripslashes(strip_tags (trim($_POST['login']))));}
Для прояснения общей картины, по проверке форм со стороны сервера, приведу пример проверки формы сообщения с сайта:
<?php
$msg='<p class="order_ms">Мы приняли Ваше сообщение!<br> В ближайшое время с Вами свяжется наш менеджер, для ответа!</p>';
if(count($_POST)==3){
$polya=implode('',$_POST);
$c=mb_strlen($polya, 'UTF-8');
if($c>160 || $c<20)){echo $msg;exit;}
$name='';if(isset( $_POST['name'])){$name=htmlspecialchars (strip_tags (trim($_POST['name'])));}
$mess='';if(isset( $_POST['mess'])){$mess=htmlspecialchars (strip_tags (trim($_POST['mess'])));}
if(mb_strlen($name, 'UTF-8')>10 || mb_strlen($mess, 'UTF-8')>120){exit;}
//Когда проверки успешно пройдены — отправляем сообщение из формы связи
echo $msg;
}
Загрузка файлов на сервер
Одна из самых опасных задач с точки зрения безопасности. При отсутствии тщательной проверки злоумышленник загрузив скрипт сможет делать с Вашим сайтом и сервером в своих интересах все, что пожелает. Неважно, какие файлы загружаются. Аватарки это, текстовые, или звуковые файлы. Проверка в несколько этапов обязательна: настройка php.ini → получение файла → проверка безопасности и валидация → перемещение из временной директории в постоянное место.
Какие бы файлы не загружались, обязательно проверьте и измените, при надобности, следующие опции в файле php.ini:
- max_execution_time — максимальное время выполнения скрипта PHP. По умолчанию стоит 30-60 сек. Файл размером в 30 МБ не успеет загрузиться за 30-60 сек, поэтому это время нужно увеличить.
- max_input_time — максимальное время для приема данных на сервер. Обычно 30-60 секунд. Аналогично с max_execution_time, поскольку за 30 сек. данные на сервер не успеют приняться и закачивание файла прервется.
- upload_max_filesize — максимальный размер загружаемого файла.
- post_max_size — максимальный размер отправляемых данных методом POST. Если форма загрузки файла максимальным размером 50 МБ имеет ещё поля "имя", "телефон" - необходимо указать значение 51 МБ, или 55200 КБ. Помимо 50 МБ добавьте максимальный размер данных из текстовых полей.
Все эти опции важны и исправление их обязательно. Если размер загружаемых файлов в разных формах сайта отличается, необходимо изменять опции конфигурации с помощью файла ".htaccess":
php_value max_execution_time 500
php_value max_input_time 500
php_value upload_max_filesize 30M
php_value post_max_size 30M
Файл во время загрузки помещается в оперативную память сервера и если превышает допустимый размер - не будет загружаться. В такой ситуации, максимальный размер файла зависит непосредственно от объема ОЗУ.
Для реализации этапа получение файла, необходима форма загрузки:
<form action="file-handler.php" method="post" enctype="multipart/form-data">
<input type="file" name="avatar">
<input type="submit" name="upload" value="Загрузить">
</form>
В свойствах формы необходимо задать тип кодировки атрибутом enctype. По умолчанию кодировка application/x-www-form-urlencoded т. е. равно текущей кодировке формы. Для бинарных файлов кодировки не должно быть, поэтому указываем multipart/form-data.
По окончанию загрузки файл записывается во временную директорию и данные о файлах помещаются в суперглобальный массив $_FILES. Переменная $_FILES['avatar'] содержит данные:
Array
(
[name] => picture.jpg //оригинальное имя файла
[type] => image/jpeg //MIME-тип файла
[tmp_name] => home\user\temp\phpD07E.tmp //бинарный файл (путь к файлу во временном хранилище)
[error] => 0 //код ошибки
[size] => 178773 //размер файла в байтах
)
Файл на сервер отправлен и на очереди проверка корректности файла. Не всем данным из $_FILES нужно доверять, ведь размер и тип можно подделать и вместо кода картинки может оказаться вредоносный код. Функцией is_uploaded_file() проверим, был ли файл загружен до конца:
if(isset($_FILES['avatar'])){
//Перезапишем переменные для удобства
$filePath=$_FILES['avatar']['tmp_name'];
$errorCode=$_FILES['avatar']['error'];
//Проверим на ошибки
if ($errorCode!==0 || !is_uploaded_file($filePath)){
//Массив с названиями ошибок
$codeErr=[
UPLOAD_ERR_INI_SIZE=>'Размер файла превысил значение upload_max_filesize в конфигурации PHP.',
UPLOAD_ERR_FORM_SIZE=>'Размер загружаемого файла превысил значение MAX_FILE_SIZE в HTML-форме.',
UPLOAD_ERR_PARTIAL=>'Загружаемый файл был получен только частично.',
UPLOAD_ERR_NO_FILE=>'Файл не был загружен.',
UPLOAD_ERR_NO_TMP_DIR=>'Отсутствует временная папка.',
UPLOAD_ERR_CANT_WRITE=>'Не удалось записать файл на диск.',
UPLOAD_ERR_EXTENSION=>'PHP-расширение остановило загрузку файла.',
];
$err=isset($codeErr[$errorCode]) ? $codeErr[$errorCode] : 'При загрузке файла произошла неизвестная ошибка.';
echo $err;
}
}
В ключе $_FILES['avatar']['name'] присутствует изначальное имя и расширение загружаемого файла. Если расширение недопустимо - отбрасываем такие файлы не раздумывая:
$name = $_FILES['avatar']['name'];
if(substr_count($name,'.')!=1){return false;}
$type = mb_strtolower(explode('.', $name)[1],'UTF-8');
if(in_array($type, array('php', 'php3', 'php4', 'html', 'htm', 'exe', 'js', 'tiff'))){return false;}
Значение ключа name формируется браузером и может быть подделан, поэтому нужен второй уровень проверки:
$type=$_FILES['avatar']['type'];
$mime_type = array('image/png', 'image/jpg', 'image/jpeg', 'image/gif');//Массив разрешенных типов файлов
if(!in_array( $_FILES['avatar']['type'], $mime_type) || $_FILES['avatar']['size'] > 1500000 || filesize($patch) > 1500000){return false;}//Если нет в массиве разрешенного типа загружаемого файла.
Вторым этапом вытащим тип файла и пройдясь по массиву разрешенных типов изображений спрашиваем о его присутствии. Так же проверяем размер файла с помощью ключа size и функции filesize(). Так надежнее!
Последним этапом изображения необходимо валидировать с помощью функции getimagesize(), которая вернет массив данных (не более 7-ми), а в случаи неудачи - NULL со сгенерированным предупреждением:
Array
(
[0]=>1280 //ширина
[1]=>768 //высота
[2]=>2 //тип
[3]=>width="1280" height="768" //аттрибуты для HTML
[bits]=>8 //глубина цвета
[channels]=>3 //цветовая модель
[mime]=>image/jpeg //MIME-тип
)
Все файлы изображений измеряются в длинне и высоте. Если загружен вредоносный файл - ширина и высота равна нулю. Для этого необходима проверка функцией getimagesize(). Поскольку в случае неудачи возвращается NULL с предупреждением — оператором @ необходимо подавить ошибку, чтобы её никто не видел. Теперь условие не будет выполнено и загрузка файла будет отклонена.
$image=@getimagesize($filePath);
if (filesize($filePath) > 31457280) {die('Размер изображения не должен превышать 30 Мбайт.');}
if ($image[1] <=0 && $image[0] <=0 $limitWidth) {die('Некорректное изображение');}
Пройдя все проверки можно надеяться, что загружаемый файл безопасен. Финальным этапом послужит проверка существования директории для загрузки файла, проверка и изменение прав на запись файла, генерация имени и расширения файлов:
$dirupload=$root.'/images/';
if(is_dir($dirupload)){
$prava=substr(decoct (fileperms($dirupload)), -3); //права доступа каталога
if($prava!='777') {chmod($dirupload,0777);} //Изменяем права, если недостаточно для загрузки
$name = md5_file($patch); //Сгенерируем новое имя файла на основе MD5-хеша
$extension = image_type_to_extension($image[2]); //Сгенерируем расширение файла на основе типа картинки
$dirupload = $dirupload.$name.$extension;
if(move_uploaded_file( $_FILES['avatar']['tmp_name'], $dirupload)){ chmod($dirupload,0444); return true;}
}
return false;
Важное замечание: после перемещения загруженного файла в постоянное место необходимо выставить ему права только на чтение во избежания выполнения файла хакером.
Права доступа
В веб-программировании и администратировании необходимо отталкиваться от правила: запрещено все, что не разрешено. Во время настройки сервера, или написании программы нужно запретить все, после чего выдавать нужные права доступа на файлы, папки. Определяются 3-мя составляющими: разрешение на чтение, на запись и на выполнение.
Существуют три группы пользователей: владелец файла, группа, к которой принадлежит владелец, другие пользователи. Права состоят из трех цифр с нулем в начале. Первая цифра придает права владельца файла, вторая цифра - группу владельца, а третья цифра - права других пользователей.
Каждая цифра разрешает определенные права:
- 4 - права чтения
- 2 - права записи
- 1 - права выполнения
Максимально возможные права 4+2+1=7 (чтение+запись+выполнение), или 4+1=5 (чтение+выполнение). Предлагаю для примера разобрать права 754:
- 7 - владелец файла может читать (4), записывать (2) и выполнять (1) файл.
- 5 - группа владельца может читать (4) и выполнять (1) файл.
- 4 - все остальные пользователи могут только читать (4) файл.
Рекомендуемые права для каталогов и файлов на сервере:
- Всем файлам выставить права "644".
- Всем директориям выставить права "755".
- На особо важные файлы (как правило, это файлы config.php, или подобные, содержащие пароли и ключи) необходимо выставить права "444".
- Всем директориям, для загрузки файлов на сервер выставить права "777"
Обратите внимание: в ОС Windows вообще отсутствуют права доступа. Они только на Unix-систем. Узнавать и выдавать права доступа на этой ОС бесполезно.
Язык PHP обладает функциями работы с правами. Выше я упоминал, что у файла всегда есть владелец и у каждого файла есть информация о владельце. Каждый пользователь имеет UID (уникальный идентификатор) и этот UID хранится в каждом файле. Функция fileowner() позволяет его узнать:
echo fileowner("files_777.txt");
Для смены владельца, используется функция chown():
chown("new_user", "files_777.txt");
В примере передача прав файла "files_777.txt" пользователю "new_user", но вместо имени владельца можно указать его UID.
Следующие PHP-функции - это filegroup() и chgrp(). Работают аналогично функциям fileowner() и chown(), но отвечают за группу пользователей:
echo filegroup("files_777.txt");
chgrp("mygroup", "files_777.txt");
И последние функции получения и смены прав доступа к файлам и каталогам - это fileperms() и chmod():
echo fileperms("files_777.txt");
chmod("files_777.txt", 0777);
Обращаю Ваше внимание, что права задаются с обязательным указанием ведущего нуля!
Сообщения об ошибках
Такая маленькая мелочь солидно поможет в защите сайта. Если пользователь в форме авторизации указал верно логин, а пароль нет - не нужно сообщать, какие данные неверны. Обойдитесь общей фразой, например: «Неправильное имя пользователя или пароль».
Dos и Ddos-атака на WEB-сайт
Если найти ошибку в сценариях сайта не удается, хакеры зачастую прибегают к DoS-атакам, целью которых есть отправка множества запросов одновременно, что приводит к заполнению ресурсов сервера, а для доброжелательных пользователей очень длительное ожидание, или отказ от выдачи страниц.
Отказаться от CMS-систем, фреймворков, платформ, библиотек. Эти все готовые решения имеют очень низкий уровень безопасности, за счет некачественного кода, множество "дыр" для взломов. В 95% случаев, массовые взломы происходят через эти все готовые решения, взлом которых после 2016 года вырос более, чем на 40%. Поэтому, малое количество программистов во избежания взломов предпочитают писать чистый и качественный код, который не распространяется, и работает в 180-500 раз быстрее, при этом имеет почти нулевую нагрузку на железо сервера, что так же снижает вероятность взломов и отказа работы сайта при очень массовых Dos-атаках на 100%.
На отказоустойчивость при подобных атаках очень сильно влияет сам php код и его скорость работы. Чем быстрее скорость выполнения - тем больше запросов за ед. времени сервер сможет обработать. Но к сожалению, все сайты на CMS-системах и Framework имеют большой риск отказоустойчивости при Dos-атаке и это факт. Причиной этого торжества служит медленное выполнение скриптов этих готовых платформ.
Имя продукта: | Скорость выполнения простой задачи: |
Wordpress | 0.47002696990967 сек. |
Joomla | 0.31301784515381 сек. |
OpenCart | 0.12800693511963 сек. |
YII | 0.29201698303223 сек. |
Наши Веб-сайты на чистом коде | 0.00099992752075195 сек. |
Почти никто не относится к этому серьезно, но применив простую формулу можно посчитать, у сколько раз медленнее работа кода за индивидуально созданные проекты на чистом коде.
Имя продукта: | У сколько раз медленнее: |
Wordpress | у 467-500 раз |
Joomla | у 313 раз |
OpenCart | у 128 раз |
YII | у 292 раза |
Bitrix | у 238 раз |
Для просветления Вашего сознания стоит сказать следующее: пока, например, Wordpress обработает 1 запрос, то в эту ед. времени сайт на чистом коде примерно 380-400 запросов. Из этого вердикт последует таковой: когда безопасность стоит на первом месте - на помощь прибегают программисты чистого кода, которых единицы на рынке IT-индустрии.
Скрипт Apache+PHP против Dos / Ddos-атак
Чтобы не позволять хакеру Dos / DDos-атаки отнимать без надобности ресурсы сервера, можно внедрить работающий способ, написав программу со следующим алгоритмом:
- При любом запросе на сервер, PHP-скрипт записывает IP-адрес в базу и результат функции "time()".
- После повторного захода скрипт получает IP-адрес посетителя и ищет его по базе. Если находит - выбирает поле с сохраненным результатом вызова функции "time()", получает текущее время "time()" и отнимает от текущего сохраненное. Если результат менее 1 (прошло меньше сек.) - необходимо заблокировать IP-адрес, записав его в файл ".htaccess" и сделать остановку скрипта. Во избежание перегрузки файла .htaccess скрипт должен удалять записи после 10-й, например, заменив их новыми.
#ip
Order allow,deny
allow from all
deny from 168.254.26.18
После чего, Apache будет знать IP хакера и его не пропустит. Не рекомендую записывать заблокированные IP в базу, поскольку в такой ситуации сервер пропустит запрос, потратив время на вызов интерпретатора PHP, для проверки по базе блаклиста и остановке скрипта, что требует намного больше ресурсов сервера.
Данный алгоритм скрипта почти ничем не уступает модулю mod-evasive.
Защита Admin-зоны
Устанавливая сложный пароль и изменив название папки админки - это детский лепет для хакера. Мы рекомендуем предпринять следующее:
Уровни защиты авторизации
Яркий пример из жизни - история сообщает, что для защиты городов строили крепости, но одной стены, увы, недостаточно для защиты. Ее можно сломать, перелезть. Но когда на стены навешать колючую проволоку, прокопать глубокий ров, заполненный водой с крокодилами - то это обеспечит защиту от миллиона нападающих. То есть, чем больше уровней защиты - тем сложнее ее обойти.
В нашем случае — это авторизация в несколько уровней. Возможно Вы замечали, что сайты банков после авторизации, требуют ввести код, присланный по СМС. Поэтому авторизация в несколько уровней, с подтверждением через почту, или СМС с ограничением по времени как раз нужное решение. При этом, по умолчанию, папка админ-зоны должна быть закрыта для всех и лишь открываться после успешного прохождения всех уровней авторизации, для конкретных IP-адресов, прошедших проверку.
Admin-зона на флэшке
достаточно хороший способ разгрузить сервер и увеличить безопасность. Кайф этого способа в том, что админ-зоны нет на сервере. Она на флэшке у владельца сайта. Недостаток один: с любого компьютера управлять сайтом не получится. Хотя и хорошо реализованной многоуровневой авторизации более, чем достаточно при условии, если в других частях скриптов отсутствуют слабости.
Общие рекомендации
Доступ к настройкам домена.
При регистрации домена, Вы указываете свои личные данные и привязываете его к своему хостингу (серверу). Имея доступ к настройкам Вашего домена, его можно спокойно забрать, привязав к другому сайту и будет обидно, если Ваш очень известный домен забрали нехорошие люди. Поскольку Вы указали свои паспортные данные, они станут известны нежелательной личности. Много заказчиков жалуются на веб-студии, которые отказываются предоставлять доступ к домену, даже если он куплен за Ваши деньги. Избежать подобного достаточно просто: регистрируйте домен сами и поверьте, это не сложно!
В процессе покупки домена создается учётная запись на сайте регистратора, доступ к которой предоставляется по логину и паролю. Обязательно включите подтверждение входа через СМС во избежания подбора пароля и кражи Вашего домена.
Делать регулярно копии сайтов и хранить у себя на флэшке, не выкладывать на GitHub, т.к. данный сервис принадлежит США. Этот "сыр" уже проплачен, поэтому предоставляет возможность желающим хранить там архивы своих проектов совершенно бесплатно. Вы должны трезво осознавать и понимать, что таким образом отдаете Ваш проект на аудит хакерам, для поиска новых уязвимостей, что очень вероятно может закончится проникновением.
Храните секреты
Это значит не быть многословным, не разглашать принятые меры о безопасности проекта, различного рода доступы, исходный код и архитектуру! Любопытным разведчикам не открывайте секретов. Это залог Вашего успеха!
Заключение
Принимая даже все известные меры по безопасности, нереально обезопасить сайт от взлома на все 100%. Если Ваш код, ОС и программы безопасны — то только сегодня. Может быть завтра хакеры выработают новые и более действующие способы обхода защиты.
Придерживайтесь наших рекомендаций и Вы снизите вероятность взломов. Не слушайте людей, использующие CMS-системы, фреймворки и выдающих себя за программистов. Это системы управление содержимым. Они не для программистов, а для обычных людей, которые не знают программирование, поэтому эти бесплатные решения — для 99% веб-студий лидеры. Программисты — они и архитекторы работающие напрямую с кодом, с серверами и железом, строго придерживаясь стандартов программирования. Не одобряют 99% веб-студий, поскольку они подставляют заказчиков под массовые угрозы взлома, контроля и передачи данных в службы безопасности, делая им сайты на готовых программных продуктах!
Так же хочу предупредить о том, что любой взлом, или попытка — противозаконные действия. Многие хакеры остаются безнаказанными, но если они кого-то достают — веселое лицо хакера превращается в грустную тыкву ;). Из-за лени большинства владельцев взломанных сайтов, создается ложное впечатление, что это ненаказуемо, но уверяю Вас в обратном!
А вот изучать, как мыслят и действуют хакеры — не можно, а нужно! Поэтому лучше семь раз подумайте, чем совершить действия, которые станут интересны кибер-полиции.