Безопасность cерверных web-приложений

Автор работы: Пользователь скрыл имя, 22 Декабря 2010 в 00:53, реферат

Описание работы

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

Успешно же проведенная подобная атака вполне может оказаться первым шагом на пути ко взлому всей корпоративной сети.

Файлы: 1 файл

Безопасность cерверных приложений.doc

— 80.50 Кб (Скачать файл)

Авторам анализаторов статистики, программ администрирования  форумов, чатов и т.п., показывающих ip-адрес клиента, адрес страницы, с которой он пришел, и прочую служебную информацию, не стоит забивать о том, что, в отличие от переменной окружения REMOTE_ADDR, переменные HTTP_REFERER и HTTP_X_FORWARDED_FOR формируются клиентом либо прокси, которые могут подставить туда не только «правильную» информацию, но и любой текст. Понятно, к чему может привести появление постороннего html-кода на странице администратора.

Расчет  на значения, заданные в полях формы

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

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

Использовать HTTP_REFERER эффективно в борьбе со спаммерами, засоряющими гостевые книги, доски объявлений и т.п. Конечно, в большинстве случаев помогает блокировка соответствующего IP-адреса, сочетающаяся с установкой cookie, однако более настойчивый пользователь может подготовить html-код с формой, вызывающей ваш скрипт гостевой книги, и пару строк на JavaScript, автоматически отправляющих эту форму, после чего разместить html-код в чужих гостевых книгах, разослать его по телеконференциям и т.п. При отсутствии проверки на HTTP_REFERER несколько веселых дней вам гарантировано.

К сожалению, не все так хорошо и с проверкой. Переменная HTTP_REFERER получает свое значение из http-заголовка Referer, передаваемого клиентом. Если в роли клиента выступает обычный браузер, этот заголовок действительно заполняется так, как мы и предполагали. Но проблема в том, что никто не помешает воспользоваться клиентом, ведущим себя менее добросовестно, к примеру, вот таким скриптом, подделывающим заголовок Referer:

#!/usr/bin/perl -w

use Socket;

$proto = getprotobyname('tcp');

socket(Socket_Handle, PF_INET, SOCK_STREAM, $proto);

$port = 80;

$host = "www.victim.com";

$sin = sockaddr_in($port,inet_aton($host));

connect(Socket_Handle,$sin);

send Socket_Handle,"GET /cgi-bin/env.cgi?".

          "param1=val1&param2=val2 HTTP/1.0\n",0;

send Socket_Handle,"Referer: any referer you wish\n",0;

send Socket_Handle,"User-Agent: my agent\n",0;

send Socket_Handle,"\n",0;

while (<Socket_Handle>)

{

    print;

}

close (Socket_Handle);

В нашем случае имитируется отправление данных формы методом GET, но для имитации метода POST, как мы помним, тоже нет серьезных препятствий. С точки зрения безопасности эти методы примерно равнозначны. Некоторое предпочтение можно отдать POST, поскольку GET передает всю информацию непосредственно в URL, что делает ее более доступной для перехвата. Представим ситуацию, когда некоторая форма требует ввода имени и пароля и передает их методом GET. Далее динамически формируется страница, имеющая ссылку на другой сервер. Если посетитель уйдет по этой ссылке, то в качестве Referer в log-файл сервера будет записан тот самый URL, в котором открыто прописаны имя пользователя и его пароль. Опять же GET легче поддается имитации – для его подделки необязательно копировать и модифицировать код формы, достаточно набрать в адресной строке браузера подходящий URL.

Наиболее эффективный  способ борьбы с подделкой hidden-полей – передача в отдельном поле их контрольной суммы в зашифрованном виде, возможно, в сочетании с полным шифрованием всех значений.

Хранение  критичной информации в открытых для  доступа файлах

Можно, конечно, утешать себя мыслью, что адреса файлов еще надо определить, но в  любом случае это решение считается  неудачным: всегда есть шанс, что из-за плохой конфигурации сервера станет возможным просмотр списка файлов в каталоге и наша информация будет выставлена на всеобщее обозрение; нельзя исключать возможность распространения нашего скрипта – он завоюет популярность, его исходные тексты станут доступными по всей сети, и месторасположение секретных файлов опять-таки перестанет быть тайной.

Источником утечек могут служить включаемые файлы (.INC в ASP, .PL в Perl’е), часто не являющиеся исполняемыми сами по себе и отдающиеся веб-сервером в виде простого текстового файла.

Поэтому файлы  с критичной информацией желательно располагать в местах, по возможности  вынесенных за пределы дерева каталогов  web-сервера, или хотя бы защищенных от чтения (например, при использовании  Apache этого можно добиться, разместив в защищаемом каталоге файл .htaccess со строкой deny all внутри).

Передача  web-клиентам нефильтрованного пользовательского ввода

Источник многих проблем для сайтов с установленными гостевыми книгами (или аналогичными скриптами) – html-тэги. Разрешив пользователю ввод тэгов, вы тем самым провоцируете атаку и на других пользователей, и на сервер. Последнее возможно в случае, если сервер сконфигурирован таким образом, что файлы, создаваемые скриптом, допускают использование SSI (Server Side Includes – директивы включения на стороне сервера). SSI позволяют вставить в html-документ результат выполнения некоторой программы, содержимое другого файла, значение переменной окружения и т. д. Директивы SSI имеют следующий вид:

<!--#команда параметр="аргумент"-->

Например:

<!--#include virtual="/some.html"-->

<!--#exec cgi="/cgi-bin/some.cgi"-->

<!–exec cmd="/bin/somecommand"-->

Чтобы не допускать  к использованию SSI всех посетителей  сервера, можноразрешить SSI-директивы только в файлах с определенным расширением (обычно *.shtml), тогда в файлах *.html, создаваемых скриптами, команды SSI будут восприниматься как простой комментарий. Однако подобное решение далеко не всегда устроит разработчика сайта.

Следующий способ – полная фильтрация тэгов. Самое простое – заменить все символы «<» и «>» на коды «&lt;» и «&gt;» соответственно:

$string =~ s/</&lt;/g;

$string =~ s/>/&gt;/g;

Другой вариант – удалить все, что находится внутри угловых скобок:

$string =~ s/<([^>]|\n)*>//g;

Опять же не все  web-мастера желают лишать своих посетителей возможности вставки кодов для красивого оформления текста. Тогда последнее, что остается сделать, – фильтровать часть кодов, оставляя лишь самые «безопасные». Это наиболее трудоемкий и потенциально опасный путь:

@BADTAG = (

"applet",

"script",

"iframe",

#и т. д., все "опасные" тэги

"img"

);

foreach $t(@BADTAG)

{

      $string =~ s/<$t/<none/gi;

    $string =~ s/</$t/</none/gi;

}

Такой подход чреват некоторыми опасностями. Например, известный  скрипт formmail Мэтта Райта в последнее  время фильтрует SSI следующим образом:

value =~ s/<!--(.|\n)*-->//g;

Это несомненный  прогресс по сравнению с первыми  версиями, просто пропускавшими SSI. Однако проблема в том, что Apache, по крайней  мере, не требует присутствия закрывающих  символов «-->» для выполнения указанной директивы, поэтому злоумышленник может добиться своего, просто введя строку <!--#include virtual="some.html".

Казалось бы, можно справиться с проблемой, «выкусывая» <!– (value =~ s/<!--//g;), но и в этом случае остается обходной маневр: строка <<!--!--#include virtual="some.html" в итоге преобразуется в <!--#include virtual="some.html".

Достаточно безопасной можно считать конструкцию while(s/<!--//g){}, хотя и у нее есть свои минусы.. Похожие проблемы возникают на серверах, использующих ASP, PHP и т. д., причем большинство свободно распространяемых скриптов их просто игнорирует. Будьте крайне осторожны, адаптируя готовый скрипт к своему серверу, если он (сервер) умеет чуть больше, чем просто возвращать html-документы.

Принудительное  создание безопасных CGI-приложений на Perl

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

Perl, запущенный  в так называемом зараженном режиме (tainted mode), позволяет снять часть этого гнета. Чтобы попасть в такой режим, достаточно указать параметр «–T».

После этого  работа Perl приобретает несколько параноидельный характер. Все переменные, проинициализированные за пределами программы, считаются зараженными и не могут быть переданы в качестве параметров потенциально опасным функциям, таким как system, exec, eval, unlink, rename и т. д. Попытка использовать их таким образом прервет выполнение скрипта с выдачей соответствующего предупреждения.

Переменные, инициализированные вне программы, – это переменные, значения которых получены из параметров программы, со стандартного входа, из переменных среды. Причем эта «зараза» распространяется –  так, если использовать зараженную переменную для инициализации другой переменной, та тоже станет зараженной. «Зараза» остается, даже если мы проверили переменную на отсутствие всех спецсимволов либо очистили ее от них.

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

Единственный  способ «обеззаразить» переменную – воспользоваться регулярными выражениями и применить извлечение совпадающей подстроки при поиске по маске. Это не слишком удобно, зато торжествует принцип "все, что не разрешено - запрещено".. Заодно приобретете опыт использования регулярных выражений, что наверняка пригодится в будущем.

$address =~ /(\w[\w\-.]*)\@([\w\-.]+)/;

$cleanaddress = $1.’@’.$2;

Все, что сопоставится выражению в первых круглых скобках, будет занесено в переменную $1, во вторых – в $2, и т. д. Переменные $1 и $2 будут уже считаться обеззараженными, и мы можем смело конструировать из них наш искомый адрес. Да, эти переменные тоже были получены из пользовательских данных, но Perl считает, что раз их значение было получено из регулярного выражения, значит, они прошли нашу проверку и можно о них не беспокоиться.

Чтобы быть уверенными до конца, можно вставить в наш  код проверку:

if($address =~ /(\w[\w\-.]*)\@([\w\-.]+)/)

{

    $cleanaddress = $1.’@’.$2;

}

else

{

    #выдавая сообщение об ошибке на stderr

    warn "Wrong address: $address";

    $cleanaddress = "";

}

Тем самым, правда, отсекаются вполне законные имена типа mama&papa@home.org. Менее строгая проверка вида address=~/(\S+)\@([\w.-]+)/ пропустит и метасимволы, сведя на нет все наши усилия по обеззараживанию.

У вас может  возникнуть желание обеззаразить переменную следующим образом:

$address =~ (.*);

$cleanaddress = $1;

Что ж, вольному – воля. Вы только что отключили  все проверки и взяли всю ответственность на себя.

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

  1. $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
  2. $ENV{'PATH'} = '';

Информация о работе Безопасность cерверных web-приложений