Статьи Защита Php-скриптов

Discussion in 'Статьи' started by Zitt, 11 Sep 2007.

  1. Zitt

    Zitt Elder - Старейшина

    Joined:
    7 May 2006
    Messages:
    736
    Likes Received:
    268
    Reputations:
    59
    В этой статье представлены элементарные принципы защиты PHP-скриптов, которые должен знать каждый веб-программист.

    Сейчас всё чаще защита веб-скриптов сводится к проверке и ограничению их входных данных. Делается это для ограничения возможностей зловредных пользователей или просто для защиты от неправильных данных. Такая защита от кулхацкеров, не от хакеров, т.к. последние редко ищут дыры в скриптах с целью дефейса или по каким-либо другим своим личным надобностям, атака чаще сводится к взлому сервера, к получению привилегированных учетных записей на нем, с которых можно сделать запланированное. Но защита "от дурака" тоже важна, даже если у себя на сайте вы и не храните секретные коды запуска ракет или планы эвакуации для пентагона. Об элементарной, но эффективной защите и пойдет речь.


    1. Итак, для начала неплохо было бы ограничить поступающие в скрипт входные данные. Никогда нельзя доверять данным, пришедшим в скрипт извне.
    PHP:
    substr($str010);
    Так можно ограничить длину строки. К примеру, ограничить длину ника, вводимого в форме. Функция возвращает часть переменной $str. В данном случае функция вернет строку длинной не более 10 символов, начиная с нулевого, т.е. отбросит все символы, после десятого символа, если таковые имеются. Последний параметр функции является опциональным, т.е. необязательным, можно просто задать substr($str, 5) - в таком случае возвратом функции будет строка, часть переменной $str начиная с пятого символа.
    Не стоит надеяться только на атрибут size в полях формы, не забывайте, что данные в ваш скрипт могут прийти откуда угодно, а не только из предусмотренной вами формой.

    2. Также очень важно проверять поступающие данные на достоверность.
    PHP:
    empty($str);
    Функция возвращает true, если переменная $str пустая [не содержит данных], false - в противном случае.
    PHP:
    trim($str);
    Функция возвращает строку, очищенную от пустых символов вначале и конце строки [пробелы, символы табуляции, перевода строки].
    PHP:
    strip_tags($str);
    Функция возвратит строку, очищенную от html и php тегов. В качестве второго параметра, начиная с версии PHP 3.0.13, можно задавать разрешенные теги, т.е. те теги, которые не будут вырезаться из строки. Например:
    PHP:
    $strstrip_tags($str'<a><i><b>' );
    htmlspecialchars$str);
    Функция заменяет символы в строке $str, имеющие специальное значение в html, на их безопасные эквиваленты:
    PHP:
    на &amp;
    на &lt;
    на &gt;
    " на &quot;
    ' на '
    В качестве второго параметра можно задавать способ интерпретации кавычек. По умолчанию стоит ENT_COMPAT - преобразует только двойные кавычки, не трогая одиночные. ENT_QUOTES - преобразует оба типа кавычек. ENT_NOQUOTES - никакие кавычки не преобразуются.
    Например:
    PHP:
    $str htmlspecialchars'<a href="test">Test</a>' ENT_QUOTES);
    С помощью регулярных выражений можно (нужно!) многое. Часто требуется заменять какие-либо символы в тексте вручную. Например:
    PHP:
    $strereg_replace"n"'&lt;br&gt;'$str);
    Данное выражение заменит в $str все символы с кодом 10 ["n" - перевод строки] на строку
    PHP:
    &lt;br&gt;
    Очень желательно чтобы в поля e-mail и url были введены именно адрес электронной почты и адрес сайта соответственно, а не то, что душе угодно:
    PHP:
    preg_match'/^([a-z0-9_-.])+@([a-z0-9_-])+(.([a-z0-9])+)+$/' ,$email);
    Такая запись устанавливает условие на содержимое переменной $email. Функция вернет true, если данные в переменной похожи на адрес электронной почты, false - в противном случае.
    PHP:
    preg_match'/^([a-z0-9_-.])+(.([a-z0-9/])+)+$/' ,$url);
    Таким регулярным выражением можно проверить и url на правильность

    3. Всегда желательно прятать структуру скриптов, чтобы об их работе пользователю было известно как можно меньше.

    Первым делом скрипты не должны выдавать предупреждения [warning] и тем более ошибки [error] в браузер, и вообще не должны их выдавать.

    Много предупреждений возникает по поводу undefined variable - то бишь при попытке использования несуществующей переменной. Почему переменная может не существовать это отдельный вопрос, но всегда лучше это предупредить функцией isset().
    PHP:
    isset( $var);
    Функция возвращает true, если переменная определена, false - в противном случае.

    Использование get-метода передачи данных в скрипт, на мой взгляд, не желательно. Во-первых, эстетическая сторона - выглядит адресная строка отвратительно и непонятно для пользователя. Во-вторых, частично открывает структуру работы скрипта. Если метод get у вас нигде не используется, то лучше вообще абстрагироваться от него.

    С методом post ситуация похожая:

    register_globals

    - директива, которая задает возможность (или невозможность) регистрации глобальных переменных, т.е. при получении данных из формы [post] или из адресной строки [get], по умолчанию создаются глобальные переменные с соответствующими именами [имя поля или имя параметра в адресной строке]. Это естественно, но безобразно.. (парадокс!) и вообще в некоторых случаях ведет к дырам в скриптах. Желательно так писать сценарии, чтобы они по возможности старались обходиться без директивы register_globals. Отключить это безобразие в .htaccess файле можно следующим образом:

    php_flag register_globals Off

    В таком случае данные get и post будут храниться в глобальных ассоциативных массивах
    PHP:
    $HTTP_GET_VARS
    и 
    $HTTP_POST_VARS
    Для отключения неиспользуемых возможностей или их детальной кофигурации также могут пригодиться следующие директивы:
    track_vars - доступность глобальных ассоциативных массивов переменных среды, сервера, get, post и cookie.
    variables_order - порядок регистрации переменных среды, сервера, get, post и cookie.
    register_argc_argv - переменные $argv и $argc на основе информации, поступившей методом get.
    file_uploads - возможность обрабатывать закачку файлов.
    Подробнее об этих и других директивах - мануал по Apache [php.ini, .htaccess].

    4. Никогда не бывает лишним удостовериться в том, что данные в скрипт пришли именно с вашего сайта.
    PHP:
    if(ereg'^http://' .$HTTP_HOST ,getenv ('HTTP_REFERER' )));
    Регулярное выражение проверяет, содержится ли в HTTP_REFERER имя хоста вашего сайта. Если нет, то можно послать деморализующее сообщение в браузер и завершить работу скрипта. Но не стоит 100%но доверять такой проверке, т.к. HTTP_REFERER при большом желании злоумышленник может подделать и законспирироваться под имя хоста.

    5. Ну и последний совет касается авторизации. Если кто не знает, есть программы-переборщики паролей и ими можно пытаться подобрать пароль к интерфейсу авторизации на вашем сайте. Явный тому пример - программа
    Brustus AET-2. Замечательная вещь и даже во многих случаях результативная [выделенный канал + большая база словарей + несложный пароль].
    Так вот, от подобных переборов в большинстве случаев тоже можно оградиться - все зависит от конкретной реализации. В любом случае защита сводится к ведению лога неудачных попыток авторизироваться. В
    код авторизации добавляется следующее:
    PHP:
    if( file_exists'log.txt') &amp;&ampfilesize'log.txt')&gt1024) exit;
    Т.е. до авторизации делается проверка - если существует лог неудачных авторизаций и его размер [в байтах] больше 1024, то скрипт прекращает свою работу [или выдает деморализующее сообщение :)], не доходя до
    самого процесса авторизации. На этом перебор у злоумышленника завершится.

    Ну вот, используя перечисленные принципы элементарной защиты, кулхацкер, встретившись с ней, будет злостно деморализован. Приведенные методы много раз опробованы и до сих пор не подводили.

    (c) www.zeosmaster.com/
     
  2. Sn@k3

    Sn@k3 Elder - Старейшина

    Joined:
    13 Apr 2006
    Messages:
    1,000
    Likes Received:
    437
    Reputations:
    90
    всё знакомо =) правда я обычно на достоверность провеяю if =)
     
  3. madnet

    madnet Умиротворенный

    Joined:
    9 Dec 2004
    Messages:
    868
    Likes Received:
    343
    Reputations:
    423
    блин зачем мусор собирать в разделе =(
     
    _________________________
  4. n1†R0x

    n1†R0x Elder - Старейшина

    Joined:
    20 Jan 2007
    Messages:
    728
    Likes Received:
    376
    Reputations:
    235
    На самом-то деле, как мне кажется для фильтрации:
    1. XSS достаточно использовать striptags/htmlspecialchars/htmlentities
    2. SQL достаточно испольльзовать mysql_escape_string/mysql_real_escape_string
    3. PHP-Include достаточно создать массив нужных файлов и / или осуществлять выборку через case.

    Регулярки тоже вариант.

    Кстати, во 2ом случае можно использовать функции проверки содержимого переменной, например, на присутствие только цифровых символов (is_int).

    Помогает присутствие magic_quotes_gpc, фильтрацию нужно также употреблять с учетом результата выполнения функции get_magic_quotes_gpc
    Защититься от заливки шелла? хм.. регулярка на расширения + список разрешенных. Ну и .htaccess настроить, запретить выполнение php для папок вроде uploads.

    По поводу ошибок: error_reporting(0) спасает, хотя при грамотном стиле программирования ошибки не должны появляться.

    ps: перевод строки - "\n", фильтрация "n" затронет все вхождения этого символа и слово "antichat" превратится в "atichat".

    pps: все, что выше - сугубо мое личное мнение. я не претендую на звание php-программиста, занимаюсь изучением сравнительно недавно и, скорее всего, многого не знаю) Если я где-то не прав и вы меня поправите, я буду только рад)
     
  5. Helios

    Helios Elder - Старейшина

    Joined:
    14 Jan 2007
    Messages:
    414
    Likes Received:
    180
    Reputations:
    103
    2 n1†R0x

    Мало того, что прав, так еще и в одном посте обобщил большую половину той кучи статей и талмудов, которые на эту тему написаны.
     
  6. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    хм... не очень понял про
    PHP:
    if( file_exists'log.txt') &amp;&ampfilesize'log.txt')&gt1024) exit; 
    где и как должен быть создан log.txt и если его размер дойдет до 1024, остальные юзеры тоже не смогут заходить...? поясните плз
     
  7. n1†R0x

    n1†R0x Elder - Старейшина

    Joined:
    20 Jan 2007
    Messages:
    728
    Likes Received:
    376
    Reputations:
    235
    в папке со скриптом, строчку из которого ты продемонстрировал

    "если размер лога больше 1024 байт то скрипт завершается."
    exit() - аналог die()
     
  8. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    а вторая часть вопроса?
     
  9. VDShark

    VDShark Elder - Старейшина

    Joined:
    1 Feb 2007
    Messages:
    260
    Likes Received:
    158
    Reputations:
    62
    естественно ответ положительный :) или ты где то видиш там работу с ip, идентификаторами или что нибудь подобное? Никто не сможет заходить, пока лог не почистить.
     
  10. n1†R0x

    n1†R0x Elder - Старейшина

    Joined:
    20 Jan 2007
    Messages:
    728
    Likes Received:
    376
    Reputations:
    235
    что значит "как"?
    если лог используется скриптом, в нем должно быть предусмотрено создание текстового файла. следовательно, программно.


    упс, я туплю.
    да. читай ман по die / exit, работа скрипта завершается.
     
    #10 n1†R0x, 12 Sep 2007
    Last edited: 12 Sep 2007
  11. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    вторая часть вопроса была про юзеров)
     
  12. DRON-ANARCHY

    DRON-ANARCHY Отец порядка

    Joined:
    4 Mar 2005
    Messages:
    716
    Likes Received:
    142
    Reputations:
    50
    а чо такое php-теги? :)
     
  13. SkvO

    SkvO Member

    Joined:
    8 May 2005
    Messages:
    17
    Likes Received:
    53
    Reputations:
    13
    мдяя....
    даже не учебничек а статейку популярную о php открываем, находим там знакомые буковки и читаем

    Программу на PHP, подобно скрипту на JavaScript, VBScript или ASP, надо вставлять в HTML-файл. Начало и конец программы отмечаются специальными тегами <?php и ?>. Текст вне этих тегов PHP не воспринимает - он передается Web-браузеру "как есть". Сами скрипты находятся на сервере, и их содержимое посетителю сайта просмотреть невозможно (теоретически невозможно, а практически, особенно хацкеру, возможно все =)). Файлы скриптов должны иметь расширение *.phpX (где X - это номер версии php) или *.phtml, иначе сервер проигнорирует все php-вставки в html-документе. При активизации скрипта серверная программа выполняет все команды php, не трогая html-код, и возвращает результат браузеру юзера. В итоге пользователь имеет обычную страницу, отличающуюся от привычных HTML`ов - лишь расширением.

    Источник http://www.sdteam.com/?tid=653

    грубо говоря это php вставка в html документе с исполняемой функцией между символами <? и ?>, которая возвращает юзеру результат этой функции.

    Примеры php-тегов

    http://sensor.wml.su/master/sozdanie/1.html