Написание безопасных web-приложений

Статус
В этой теме нельзя размещать новые ответы.
Защита через файл ".htaccess"

Для чего служит файл ".htaccess":
Файлы .htaccess позволяют изменить некоторые настройки веб-сервера Apache применительно к отдельному каталогу и его подкаталогам. Например, если разместить в каталоге logs файл .htaccess со строчкой Options +Indexes, можно будет по адресу Для просмотра ссылки Войди или Зарегистрируйся получить полный список содержащихся там файлов (в случае, если там не присутствует ни одного из возможных файлов индекса). Если в logs есть подкаталоги, например, mail и ftp, индексирование будет проводиться и в них тоже; чтобы избежать этого, нужно разместить в них файлы .htaccess с запретом индексации – строчкой Options -Indexes.

Блокировка по IP адресам:
Средствами файла .htaccess можно ограничить доступ к ресурсам сайта по IP адресам; например, разрешить доступ к медиа-архиву только пользователям из локальной сети, или запретить какому-либо хосту или сети доступ к какому-либо контенту.

Синтаксис для этих директив таков:

CODE
Order Deny, Allow (или Allow, Deny – в зависимости от того, что требуется)
Deny from all (или адрес хоста)
Allow from all (или адрес хоста)


Например,
CODE
Order Deny, Allow
Deny from all
Allow from 192.168.0.
Allow from .localnet
Allow from admin.somewhere.in.the.net

вызывает отказ в доступе для всех, кроме сети 192.168.0.0/24, всех хостов, DNS имя которых содержит .localnet, а также хоста, DNS имя которого admin.somewhere.in.the.net.

Если нужно запретить доступ группе хостов, используется Allow,Deny:
CODE
Order Allow, Deny
Allow from all
Deny from 192.168.1.
Deny from hackers.are.everywhere.in.the.net


Принцип прост. По Order определяется порядок обработки правил allow/deny; если мы возьмем второй пример, то сначала сервер обработает правило allow from all, а затем хосты, которые прошли это правило, подвергаются проверке правилом deny; при этом все хосты из сети 192.168.1.0/24 и хост hackers.are.everywhere.in.the.net не проходят эту проверку и не получают доступа.

Более сложные применения:
CODE
<FilesMatch "\.(txt|dat)$">
Order Deny, Allow
Deny from all
</Files>

– данное правило запретит любым хостам доступ к файлам с расширениями .txt и .dat (например, в них могут храниться внутренние данные скриптов).

Запрет обращений к файлу ".htaccess":
Защитить их можно следующим образом, однако, это по умолчанию уже есть в httpd(2).conf, то есть в самой конфигурациии веб-сервера.

CODE
<Files ~ "^\.ht">
Order allow, deny
Deny from all
</Files>


Запрет вывода списка файлов:
Apache (при включении соответствующих опций) умеет отображать список файлов в каталоге, если в нем нет ни одного из перечисленных в DirectoryIndex файлов. Часто эта опция включена по умолчанию, что может быть неприемлемо.
Строчка
CODE
Options -Indexes

отключит этот режим.

Однако иногда может, наоборот, понадобиться разрешить просматривать список файлов, при этом исключив из него их часть. Для этого служит IndexIgnore.
Например,
CODE
IndexIgnore *.php* *.pl *.html *.shtml

разрешает вывод списка всех файлов, кроме PHP и Perl скриптов, а также HTML документов.


Подробно о защите скриптов можно прочитать здесь: Часть I Часть IIДалее краткая заметка:

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

1. Итак, для начала неплохо было бы ограничить поступающие в скрипт входные данные. Никогда нельзя доверять данным, пришедшим в скрипт извне.
CODE
substr($str, 0, 10);


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

2. Также очень важно проверять поступающие данные на достоверность.

CODE
empty($str);


Функция возвращает true, если переменная $str пустая [не содержит данных], false - в противном случае.

CODE
trim($str);


Функция возвращает строку, очищенную от пустых символов вначале и конце строки [пробелы, символы табуляции, перевода строки].

CODE
strip_tags($str);


Функция возвратит строку, очищенную от html и php тегов. В качестве второго параметра, начиная с версии PHP 3.0.13, можно задавать разрешенные теги, т.е. те теги, которые не будут вырезаться из строки. Например:

CODE
$str= strip_tags($str, '<a><i><b>' );
htmlspecialchars( $str);


Функция заменяет символы в строке $str, имеющие специальное значение в html, на их безопасные эквиваленты:

CODE
& на &
< на <
> на >
" на "
' на '


В качестве второго параметра можно задавать способ интерпретации кавычек. По умолчанию стоит ENT_COMPAT - преобразует только двойные кавычки, не трогая одиночные. ENT_QUOTES - преобразует оба типа кавычек. ENT_NOQUOTES - никакие кавычки не преобразуются.

Например:
CODE
$str = htmlspecialchars( '<a href="test">Test</a>' , ENT_QUOTES);


С помощью регулярных выражений можно (нужно!) многое. Часто требуется заменять какие-либо символы в тексте вручную.

Например:
CODE
$str= ereg_replace( "n", '<br>', $str);


Данное выражение заменит в $str все символы с кодом 10 ["n" - перевод строки] на строку

CODE
<br>


Очень желательно чтобы в поля e-mail и url были введены именно адрес электронной почты и адрес сайта соответственно, а не то, что душе угодно:

CODE
preg_match( '/^([a-z0-9_-.])+@([a-z0-9_-])+(.([a-z0-9])+)+$/' ,$email);


Такая запись устанавливает условие на содержимое переменной $email. Функция вернет true, если данные в переменной похожи на адрес электронной почты, false - в противном случае.

CODE
preg_match( '/^([a-z0-9_-.])+(.([a-z0-9/])+)+$/' ,$url);


Таким регулярным выражением можно проверить и url на правильность

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

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

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

CODE
isset( $var);


Функция возвращает true, если переменная определена, false - в противном случае.

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

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

register_globals

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

php_flag register_globals Off

В таком случае данные get и post будут храниться в глобальных ассоциативных массивах

CODE
$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. Никогда не бывает лишним удостовериться в том, что данные в скрипт пришли именно с вашего сайта.

CODE
if(ereg( '^http://' .$HTTP_HOST ,getenv ('HTTP_REFERER' )));


Регулярное выражение проверяет, содержится ли в HTTP_REFERER имя хоста вашего сайта. Если нет, то можно послать деморализующее сообщение в браузер и завершить работу скрипта. Но не стоит 100%но доверять такой проверке, т.к. HTTP_REFERER при большом желании злоумышленник может подделать и законспирироваться под имя хоста.

5. Ну и последний совет касается авторизации. Если кто не знает, есть программы-переборщики паролей и ими можно пытаться подобрать пароль к интерфейсу авторизации на вашем сайте. Явный тому пример - программа
Brustus AET-2. Замечательная вещь и даже во многих случаях результативная [выделенный канал + большая база словарей + несложный пароль].
Так вот, от подобных переборов в большинстве случаев тоже можно оградиться - все зависит от конкретной реализации. В любом случае защита сводится к ведению лога неудачных попыток авторизироваться. В
код авторизации добавляется следующее:

CODE
if( file_exists( 'log.txt') && filesize( 'log.txt')> 1024) exit;


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

Ну вот, используя перечисленные принципы элементарной защиты. Приведенные методы много раз опробованы и до сих пор не подводили.
 
Согласен. Поэтому этот материал был изначально размещен в faq для начинающих программистов.
Да, здесь ничего нет такого, что не узнает программист за первые пол года работы junior. Эта статься рассчитана была изначально на тех, кто начинает. Даже с простыми детскими примерами. А по поводу профи не нужно далеко идти, профи писали vbulletin, который от версии к версии латает xss. Странно да, ведь профессионалы? И это не касается только воблы. Хотя с другой стороны есть 10 ки реально работающих опенсорс проектов, для которых таких новостей нет годами о xss и прочем. Просто хочется чтобы люди не спотыкались на одном и том же.
Для написания безопасных приложений нужно знать только теоретические методы проведения атак, т.к. они не типизированы и полиморфны. Лучше не приводить сложные примеры - начинающему программисту будет самому интересно проверить свой проект на уязвимости :) .
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху