девушка евгения савина

PHP - Статьи - Примеры обороны ПХП

Несоблюдение некоторых элементарных правил может свести на ноль все старания по защите от взлома сайта через PHP скрипты.Итак, что же я там нашел? В принципе, ничего особенного за исключением того, что в некоторых, в том числе и "секретных" директориях отсутствовали файлы index.html (или другие index.*, интерпретируемые как стартовые). Кроме того, не было соответствующих настроек прав доступа. Что из этого следует? При наборе в адресной строке такого адреса на директорию без index.* файла, злоумышленнику прямо в браузере откроется все содержимое папки со всеми возможными последствиями (это уже в зависимости от того, что там храниться).Как этого не допустить? Достаточно в каждую папку на сервере, если там нету файла index.*, поместить его туда. В самом файле можете писать, что вам угодно - от "Вход запрещен" или пустого файла до перенаправления, например на стартовую страницу сайта. Второй вариант предпочтительнее опять же с заботливого взгляда вебмастера в сторону добросовестных посетителей. Если кто подзабыл, напомню, как осуществить ридерект:<html><head><META HTTP-EQUIV="Refresh" CONTENT="0; URL=http://syte.com"></head><body></body></html>

Ну, конечно еще оформить можно по своему усмотрению и т.д. и т.п.Теперь пора занятся настройкой прав доступа (не путать с просто правами файла - тем что можно делать с файлом). Для их настройки существует простое и одновременно мощное средство. Настройка осуществляется путем размещения на сервере файла .htaccess. Можно создавать несколько файлов .htaccess - по одному в разных папках вашего сайта. Действие файла распространяется на все вложеные папки, кроме папок в которых имеется другой файл .htaccess. Данный файл является служебным файлом, вследствии чего он недоступен посетителям сайта даже для чтения.Мы небудем рассматривать все свойства данного файла конфигурации, так как нас интересует только одно - защита файловой системы сервера (для тех, у кого жажда познаний неиссекаема, специально нашел неплохое описание данного файла настроек на русском языке: http://www.kokos.ru/?nma=catalog&fla=stat&cat_id=8&page=1&num=16 ).Для запрета или разрешения доступа нужно использовать директивы Deny или Allow соответственно. Перед данными директивами идет директива Order, указывающая порядок следования директив Deny и Allow. Для лучшего понимания, давайте рассмотрим пример:Order Deny,AllowDeny from allAllow from syte.comAllow from 10.25.0.55Поместив данные директивы в файл .htaccess, мы запретим доступ ко всем ресурсам в этой и сложеных папках всем, кроме компьютеров с адресами syte.com и 10.25.0.55.Ну вот, для понимания и устранения проблемы вполне достаточно. Можно было бы еще много хорошего о данных настройках сказать не только по поводу защиты, но и по поводу улучшения работы сайта. Но это уже выходит далеко за рамки данной статьи.Сессии в PHPНет, студенты, не пугайтесь J сессии в PHP намного более приятные процедуры, чем привычные для вас, зимние или лентие.Когда были выпущены первые версии PHP, программисты столкнулись с серьезной проблемой, а именно с отсутствием глобальных переменных - т.е. все результаты работы скрипта, хранимые в переменных, после его исполнения уничтожались и небыли доступны в дальнейшем (наподобие того как в Паскале и других языках программирования, после завершения работы функции, уничтожаются переменные, объявленные внутри этой функции). Легче всего для понимания примеры, что ж, давайте, рассмотрим пример:Пусть файл index.php содержит:<?php$test="Этот текст задается в файле index.php";echo $test;?>И есть файл test.php, содержащий следующий код:<?phpecho $test;?>Если выполнить данные скрипты, то в результате работы первого скрипта мы получим надпись "Этот текст задается в файле index.php". Второй же скрипт выдаст нам пустоту, так как значение переменной $test не передалось второму скрипту (и небыло в нём задано).Тогда программисты и начали использовать Cookies для хранения глобальных переменных. Однако у этого метода есть большие недостатки. Начиная от громоздкости и заканчивая, наверное самым неприятным - все хранится на стороне пользователя (читать - хакера). Да и в конце концов, у пользователя может быть попросту отключены Cookies. Много программистов в те времена перестали использовать PHP.Однако, появление сессий все изменило. Теперь вся информация хранилась на сервере, а идентификация пользователя проходила по уникальному идентификатору сесси. Но обовсем по порядку.Поскольку далеко не но всех случаях скрипту нужно использовать сессии, то их использование нужно указывать явно. Для этого существует команда session_start();, вызов которой говорит серверу что данная страинца нуждается во всех переменных, связаных с пользователем. Сессию нужно открывать до того как какие-либо данные будут отправлены пользователю так что желательно вызывать ее в самом начале скрипта.После начала сессии можно задавать глобальные переменные с помощью функции session_register("var_name"). После этого переменная $var_name становиться доступной на всех страницах сессии. Давайте модифицируем представленный выше пример:Файл index.php:<?phpsession_start();$test="Этот текст задается в файле index.php";session_register("test");echo $test;?>Сессия запущена<br>Теперь перейдем и посмотрим результат:<br><a href="test.php">работа сессии</a>И файл test.php:<?phpsession_start();echo $test;?>Открываем index.php, кликаем на ссылку и видим что открывшийся test.php получил значение переменной $test. Обратите внимение что в функции session_register("test") имя переменной нужно передавать без знака $. Таким образом, после задания переменной $test как глобальной для сессии, она будет доступна во всех дальнейших скриптах данной сессии.Если переменная больше непонадобиться, ее можно удалить функцией session_unregister();Также можно уничтожить саму сессию: session_destroy();Теперь у нас достаточно знаний чтобы написать механизм авторизации. Исполним его тремя файлами: index.php, auth.php и done.php. Файл index.php будет содержать форму для ввода логина и пароля. Данные из этой формы будут переданы для проверки файлу auth.php, который в случае удачной авторизации, даст пользователю доступ к файлу done.php.Файл index.php:<html><body><form action="auth.php" method="post">Логин <input type="text" name="user_name"><br>Пароль <input type="password" name="user_pass"><br><input type="submit" name="submit" value="вход"></body></html>Файл auth.php:<?phpsession_start();if ($submit){if (($user_name=="login")&&($user_pass=="password")){$login_user=$user_name;session_register("login_user");header("location: done.php");exit;}}?><html><body>Неверный логин или пароль</body></html>Тут, давайте разберемся с кодом. Итак, с начала мы открываем сессию: session_start(); далее проверяем были ли отправлены данные из формы: if ($submit) - это поможет избежать атаки на перебор примитивных брутфорсов (программ и скриптов переборщиков паролей). Проверяем введенные логин и пароль: if (($user_name=="login")&&($user_pass=="password")) в данном случае для простоты у нас только одна пара логин-пароль, в действительности же логина и пароли хранятся в файлах или базах данных, но я не стал приводить такой пример чтобы не усложнять понимание сути авторизации и ее потенциально опасных мест. Позже мы обязательно рассмотрим, как и где хранить логины и пароли. Итак, если были введены правильный логин и пароль, объявляем глобальную переменную $login_user и перенаправляем броузер на страницу done.php: header("location: done.php");И файл done.php

<?phpsession_start();if (!isset($login_user)){header ("location: index.php");exit;}?><html><body>Вы залогинены под логином:<?phpecho "$login_user";?></body></html>С данным скриптом все уже намного понятнее. После открытия сессии, проверяем залогинен ли пользователь: if (!isset($login_user)) если да, то выводим сообщение в котором указываем его логин: Вы залогинены под логином: <php echo "$login_user"; ?>, в противном же случае, перенаправляем его на страницу ввода логина и пароля: header ("location: index.php");Теперь, зная принцип механизмов авторизации с использованием сессий, рассмотрим и исправим узкие места представленных скриптов. Идентификатор сессии, который дает доступ к самой сессии и хранится в броузере на стороне пользователя узким местом считать не будем. Причин тому масса - начиная от того что идентификатор, действует непродолжительное время, в частности если пользователь ушел с сайта, закрыл броузер или долго не проявлял активности, сессия уничтожается, и, заканчивая тем что обычно идентификатор является уникальным 128-битным кодом, как правило, сложнее любого пароля пользователя.А потенциально опасными являются следующие моменты:- несмотря на наличие проверки того что, данные отправлены из формы, можно спокойно сымитировать это и попытаться перебрать пароль через скрипт auth.php- скрипт done.php можно обмануть так: done.php?login_user=loginДля устранения первой уязвимости желательно проделать все что было описано в предыдущей статье, а именно - жесткий приме переменной только из массива POST, проверка $HTTP_REFERER, проверка и урезка переменной. Также, раз нам нужно защититься от многочисленных атак, можно записывать IP посетителя и, скажем после 3 неудачных попыток блокировать его на 15 минут. Однако я бы посоветовал не применять блокировку IP - ее можно элементарно обойти, а многие пользователи прокси серверов могут страдать из-за нее. Гораздо разумнее применить задержку авторизации. Т.е. непосредственно перед проверкой корректности логина и пароля делаем задержку, скажем на 1 секунду. Пользователи ее скорее всего даже не заметят, а вот у хакеров скорость перебора упадет ниже 1 комбинации в секунду, что фактически полностью исключает возможность перебора пароля даже по специальному словарю. Осуществить задержку можно так:sleep(1); //задержка на 1 секундуЧто же касается второй проблемы с защитой, там все еще легче. Несмотря на то что любой желающий может передать переменную $login_user, содержащую произвольный логин скрипту done.php, все же кое-что можно сделать. А именно удалить переменную (в PHP нет нужды объявлять переменные, поэтому и понятие удаления переменной можно сравнить скорее с очисткой переменной) с помощью функции unset(); после чего откроем сессию, в которой хранится значение переменной $login_user, взятое с сервера, т.е. истинное значение, на которое хакер никак не может повлиять. Сделать это можно так:<?phpunset($login_user);session_start();if (!isset($login_user))...Как видите, если переменная $login_user и была передана взломщиком скрипту, мы очищаем ее, а далее уже открываем сессию и если там содержится переменная $login_user - т.е. если была произведена успешная проверка логина и пароля то даем посетителю доступ к странице.Теперь вы уже знаете немало о методах защиты своего сайта, в частности о закрытии лазеек для хакеров в PHP скриптах. В следующей, заключительной статье, мы рассмотрим другие проблемы защиты скриптов на PHP, а также, как я и обещал, способы безопасного хранения логинов и паролей на сервере.
Автор: Владислав Путяк, www.docs.com.ru
Copyright © 2006-09.