Случайный апокалипсис: Как 99 строк кода Роберта Морриса навсегда изменили интернет

от автора

Введение

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

Именно в этой ламповой атмосфере абсолютного доверия 2 ноября 1988 года разверзся локальный ад.

23-летний аспирант Корнеллского университета Роберт Тэппан Моррис решил запустить программу, чтобы просто «измерить» размер интернета. Его код должен был тихо проникать на машины, рапортовать о своем присутствии на контрольный сервер и ползти дальше. Но из-за одной математической ошибки в логике размножения безобидный исследовательский зонд превратился в неуправляемого монстра.

За считанные часы червь Морриса парализовал около 6 000 серверов — 10% всего тогдашнего интернета.

Электронная почта перестала ходить, терминалы намертво зависали под 100% нагрузкой на процессор, а системные администраторы по всей территории США в панике физически выдергивали кабели из маршрутизаторов, дробя сеть на изолированные островки.

Дискета с оригинальным кодом червя Морриса (Музей компьютерной истории). Источник: Kaspersky

Дискета с оригинальным кодом червя Морриса (Музей компьютерной истории). Источник: Kaspersky

Этот день стал точкой невозврата. Интернет навсегда потерял свою академическую невинность, а на свет появилась индустрия кибербезопасности в том виде, в котором мы знаем её сегодня.

И всё это началось с кода, который умещается на одной дискете. Давайте разберем по косточкам, как именно 99 строк кода смогли поставить на колени самую защищенную сеть планеты.

1. Мир до червя

Чтобы понять масштаб и феномен червя Морриса, нужно забыть всё, что вы знаете о современном интернете. Забудьте про файрволы, двухфакторную аутентификацию, принципы Zero Trust и параноидальный мониторинг трафика.

Добро пожаловать в 1988 год.

Архитектура доверия: Сеть для «своих»

В конце 80-х глобальная сеть всё ещё находилась в переходной фазе от военной и академической ARPANET к тому, что мы сегодня называем интернетом. Узлов было около 60 000, и принадлежали они в основном американским университетам (MIT, Berkeley, Stanford), исследовательским центрам и правительственным учреждениям (включая Министерство обороны США).

Эта сеть строилась вокруг одной фундаментальной идеи: отказоустойчивость важнее безопасности.

Создатели протоколов TCP/IP (Винт Серф и Боб Кан) решали задачу маршрутизации пакетов таким образом, чтобы при выходе из строя одного или нескольких узлов данные всё равно достигали адресата. Проблема была в том, что в этой архитектуре напрочь отсутствовала концепция «внутреннего врага».

Предполагалось, что если вы смогли подключиться к магистрали NSFNET или ARPANET, значит, вы — уважаемый ученый, студент или военный. Зачем вам ломать сеть, в которой вы сами работаете? Это было похоже на небольшую деревню, где никто не запирает двери на замок, потому что все друг друга знают.

Дефолтные настройки и беспечность

Отсутствие концепции «злого умысла» напрямую отражалось на системном администрировании серверов (в основном это были машины на базе UNIX, такие как SunOS или VAX 4.3BSD).

  1. Права root по умолчанию: Многие сетевые демоны (системные службы, ожидающие соединений) запускались с наивысшими привилегиями — правами суперпользователя (root). Если злоумышленник находил способ заставить этот демон выполнить произвольную команду, он мгновенно получал полный контроль над всем сервером.

  2. Открытый текст и доверительные отношения: Пароли передавались по сети без шифрования (протоколы вроде Telnet или FTP). Но что еще хуже, в UNIX-системах активно использовались механизмы доверия — файлы .rhosts и hosts.equiv. Они позволяли пользователям логиниться на соседние серверы вообще без пароля, если эти серверы находились в списке «доверенных». Стоило скомпрометировать одну машину на кафедре — и соседние сдавались без боя.

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

В этом академическом Эдеме безопасность не была даже вторичной — она попросту отсутствовала в менталитете разработчиков и администраторов. Роберт Моррис не взламывал системы в современном понимании этого слова. Он просто постучал в незапертые двери, которые услужливо распахнулись сами.

2. Анатомия угрозы

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

Код червя состоял из двух частей: крошечной программы-загрузчика (написанной на C) и основного тела, которое перетягивалось на зараженную машину, компилировалось под архитектуру жертвы (VAX или Sun-3) и запускалось.

Интерфейс командной строки UNIX. Источник: Yurich84 / Getty Images

Интерфейс командной строки UNIX. Источник: Yurich84 / Getty Images

Чтобы внедрить этот загрузчик, Моррис использовал три совершенно разных механизма.

1. Бэкдор в sendmail: Отладка, которая вышла боком

В те годы стандартом для пересылки электронной почты в UNIX-системах был демон sendmail. Его автор, Эрик Оллман, оставил в коде небольшую «закладку» для себя и других разработчиков — режим отладки (DEBUG).

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

Червь подключался к почтовому серверу и передавал следующую последовательность команд:

DEBUGMAIL FROM:<nobody>RCPT TO:<"| sed -e '1,/^$/d' | /bin/sh; exit 0">DATA

Конструкция RCPT TO с пайпом (|) заставляла sendmail передать тело письма не в почтовый ящик пользователя, а напрямую интерпретатору командной строки /bin/sh. В теле этого «письма» лежал скрипт, который компилировал и запускал тот самый загрузчик. Сервер сам скачивал тело червя, собирал его и запускал.

2. Переполнение буфера в fingerd: Классика жанра

Если почтовый сервер был пропатчен или недоступен, червь переключался на 79-й порт — службу fingerd. Протокол Finger использовался для того, чтобы узнать информацию о пользователях в системе (кто залогинен, когда читал почту и т.д.).

Уязвимость скрывалась в исходном коде демона fingerd (в файле fingerd.c из состава 4.3BSD). Он использовал стандартную функцию ввода gets(), которая исторически является одной из самых опасных в языке C.

Выглядело это примерно так:

#include <stdio.h>main(argc, argv)    int argc;    char **argv;{    char line[512]; // Буфер на 512 байт    // Функция gets читает данные из потока до переноса строки,    // но вообще не проверяет, поместятся ли они в массив line!    gets(line);         // ... дальнейшая обработка}

В чем была суть атаки? Червь отправлял демону fingerd строку длиной 536 байт (400 байт NOP-инструкций, сам шелл-код и перезаписанный адрес возврата). Поскольку gets() не проверяла границы, введенные данные выходили за пределы выделенных 512 байт и перезаписывали стек вызовов. В том числе перезаписывался адрес возврата функции — то место в памяти, куда программа должна вернуться после завершения текущих операций.

Моррис ювелирно подменил этот адрес так, чтобы он указывал на код, который червь только что загрузил в этот же буфер. Процессор послушно переходил по новому адресу и выполнял машинный код (шелл-код), который сводился к простому вызову: execve("/bin/sh", ...)

Учитывая, что fingerd часто работал с правами root, червь моментально получал командную оболочку с максимальными привилегиями. Это была одна из первых в истории успешных и массовых эксплуатаций уязвимости типа Buffer Overflow в дикой природе.

3. Подбор паролей и «доверенные» сети: Когда подвела беспечность

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

Моррис встроил в червя компактный, но дьявольски эффективный словарь всего из 432 популярных паролей (вроде qwerty, guest, aaa, имен из словаря и т.д.). Логика подбора была следующей:

  1. Попробовать логин в качестве пароля.

  2. Попробовать логин, написанный задом наперед.

  3. Пройтись по встроенному словарю из 432 слов.

  4. Пройтись по локальному файлу словаря /usr/dict/words (если доступен).

Но самое интересное начиналось после того, как червь подбирал пароль хотя бы к одному пользователю. В дело вступали утилиты rsh (Remote Shell) и rexec, а также файлы конфигурации .rhosts и /etc/hosts.equiv.

В академической среде серверы часто объединялись в группы доверия. Если вы залогинились на сервере кафедры физики (Server A) и он доверяет серверу кафедры математики (Server B), вы можете зайти на Server B без ввода пароля. Червь читал файлы .rhosts, находил все «доверенные» машины и мгновенно расползался по ним, словно лесной пожар по сухой траве. Захватив одну учетную запись обычного студента с плохим паролем, червь мог за несколько минут инфицировать десятки серверов университетского кампуса.

3. Фатальная ошибка: Правило «1 к 7»

Самая большая трагедия инцидента 1988 года заключается в том, что Роберт Моррис не был киберпреступником, и его творение не несло деструктивной нагрузки. В коде не было функций удаления файлов, шифрования данных или кражи секретов. Червь задумывался как тихий, невидимый исследовательский зонд, который должен был мягко расползтись по ARPANET и измерить её реальные масштабы.

Но благие намерения разбились об одну фатальную ошибку в логике.

Искусство маскировки

Чтобы зонд мог существовать в сети долго и собирать данные, Моррису нужно было спрятать его от глаз системных администраторов. Программа использовала несколько изящных техник скрытности:

  • Подмена имени процесса: При запуске червь перезаписывал свой аргумент argv[0] (имя, под которым программа отображается в системе) на безобидное sh. Для администратора, запустившего утилиту ps или top, это выглядело как обычный системный командный интерпретатор, которых на любом UNIX-сервере крутятся десятки.

  • Отвязка от терминала (Daemonization): Сразу после запуска червь вызывал функцию fork(), создавая свою точную копию в памяти, а затем убивал родительский процесс. Это отвязывало его от терминала жертвы и превращало в фоновый процесс (демон), который жил своей жизнью.

  • Шифрование строк в памяти: Все пароли, имена файлов и критические строки в скомпилированном бинарнике были зашифрованы простейшим XOR-алгоритмом, чтобы их нельзя было прочитать банальной утилитой strings.

Логика проверки и умные админы

Любой сетевой червь сталкивается с фундаментальной проблемой: как понять, что машина уже заражена, чтобы не тратить на неё ресурсы повторно?

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

Однако Моррис был слишком умен и понимал, с кем имеет дело. Системные администраторы университетов — народ сообразительный. Если бы алгоритм проверки был стопроцентным, админы мгновенно бы разобрали код, поняли логику и написали «вакцину» — простенький скрипт-заглушку, который просто слушал бы нужный порт и отвечал всем входящим червям: «Да-да, я уже заражен, уходи».

Фатальное правило «1 к 7»

Чтобы обмануть потенциальную «вакцинацию», Моррис внедрил в код одно маленькое, но катастрофическое условие: Даже если машина отвечает, что она уже инфицирована, с вероятностью 1 к 7 (около 14%) новая копия всё равно должна остаться в памяти и продолжить работу.

Это была главная математическая ошибка в истории интернета. Моррис катастрофически недооценил плотность связей в сети и скорость распространения своего детища.

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

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

Произошел эффект неуправляемой цепной реакции. Серверы один за другим уходили в жесткий отказ в обслуживании (Denial of Service). У них заканчивалась оперативная память, процессорное время и лимиты на количество процессов в ОС. Эксперимент по измерению интернета превратился в первую в мире глобальную DDoS-атаку, обрушившую сеть под тяжестью собственного кода.

4. Утро 3 ноября: Коллапс и ликвидация

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

Симптомы: Эпидемия отказа в обслуживании

Системные администраторы, пришедшие на работу в MIT, Стэнфорд, Беркли и исследовательские центры Пентагона, увидели одну и ту же пугающую картину. Терминалы либо намертво висели, либо реагировали на нажатие клавиш с задержкой в несколько минут.

Попытки вызвать системный монитор показывали, что загрузка процессоров (Load Average) улетела в космос. В списке процессов висели десятки, а иногда и сотни загадочных процессов с именем sh, которые пожирали всю доступную оперативную память, плодили дочерние клоны и без устали стучались на случайные IP-адреса.

Электронная почта — главная артерия общения того времени — легла полностью. Почтовые шлюзы задохнулись от попыток червя передать свой код через sendmail. Это был классический отказ в обслуживании (Denial of Service), но вызванный не внешней атакой, а внутренним паразитом. Паника нарастала: никто не знал, стирает ли вирус данные, ворует ли секретные разработки или просто ломает системы.

Карантин: Руби рубильник

Отключение кабелей стало единственным способом остановить заражение. Источник: panumas nikomkai / Getty Images

Отключение кабелей стало единственным способом остановить заражение. Источник: panumas nikomkai / Getty Images

Единственным способом остановить распространение инфекции оказался самый радикальный — физическая изоляция. Поскольку интернет-каналы забиты, а почта не работает, админы начали звонить друг другу по обычным стационарным телефонам. Из уст в уста, от университета к университету передавалась одна команда: «Отключайтесь от магистрали».

Сисадмины спускались в серверные и в прямом смысле слова выдергивали толстые Ethernet-кабели из маршрутизаторов. Сеть ARPANET/MILNET начала распадаться на куски. Глобальный интернет искусственно раздробили на сотни изолированных «островков» (кампусов и лабораторий), чтобы не дать червю перепрыгивать между ними. Это остановило внешнее заражение, но внутри отсеченных зон червь продолжал бушевать, пока машины не вычищали вручную.

Декомпиляция на скорость: Как спасали сеть

Пока одни рубили кабели, другие начали препарировать угрозу. В центре сопротивления оказались команды энтузиастов из Беркли (в частности, Computer Systems Research Group — CSRG), MIT и Университета Пердью, где находился профессор Юджин Спаффорд.

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

Исследователи из Беркли смогли отловить бинарный файл червя (он удалял себя с диска после загрузки в память, но оставлял следы, если сервер падал в процессе). Закипела работа по реверс-инжинирингу. Команды дизассемблировали код под архитектуры VAX и Sun, шаг за шагом восстанавливая логику Морриса.

Счет шел на часы. Вскоре были найдены те самые векторы атаки в sendmail и fingerd. Команды оперативно выпустили «рецепты первой помощи»:

  1. Заплатки: Временные фиксы для sendmail (отключение режима DEBUG) и перекомпиляция fingerd.

  2. Прививки: Так как червь проверял наличие процесса на определенном порту и создавал временные файлы в директории /usr/tmp/, админам советовали создать пустую директорию sh по нужному пути, чтобы скрипт Морриса не мог записать туда свой бинарник и аварийно завершался.

К вечеру 3 ноября рецепты лечения были разосланы (где почтой, где факсами) по всем крупным узлам. Интернет начал медленно приходить в себя, восстанавливая линки между «островками». Но мир, который проснулся утром 4 ноября, был уже совсем другим.

5. Наследие Роберта Морриса

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

Рождение CERT (Координация вместо хаоса) До инцидента с Моррисом ликвидация угроз напоминала тушение пожара ведрами, когда соседи просто кричат друг другу через забор. Не было ни единого центра, ни протоколов реагирования, ни защищенных каналов связи для обмена патчами. Агентство DARPA быстро усвоило урок: уже через несколько недель после инцидента на базе Университета Карнеги-Меллона был создан первый CERT/CC (Computer Emergency Response Team). По сути, это прадедушка всех современных SOC (Security Operations Center) и команд быстрого реагирования (CSIRT), без которых сегодня немыслима работа любой крупной корпорации.

Современный Security Operations Center (SOC). Источник: kjekol / Getty Images

Современный Security Operations Center (SOC). Источник: kjekol / Getty Images

Индустрия ИБ: от академической блажи к необходимости Инцидент 1988 года наглядно показал бизнесу и государству, что программные уязвимости — это не просто «баги», влияющие на стабильность, а векторы атак, способные парализовать инфраструктуру. Появился спрос на превентивную защиту. За считанные годы сформировался рынок коммерческих межсетевых экранов (firewalls), систем обнаружения вторжений (IDS), сканеров уязвимостей и антивирусных решений. Информационная безопасность перестала быть факультативом.

От зонда до прото-ботнета и APT Если посмотреть на архитектуру червя Морриса современным взглядом, мы увидим в нём классический прото-ботнет с зачатками автономного горизонтального перемещения (Lateral Movement). Идеи, заложенные в те 99 строк загрузчика, живут и процветают:

  • Mirai (2016): Точно так же, как Моррис использовал словарь из 432 популярных паролей, ботнет Mirai ставил на колени интернет, массово брутфорся IoT-устройства по крошечному словарю дефолтных логинов и паролей от заводских прошивок.

  • WannaCry / NotPetya (2017): Их разрушительная сила крылась не столько в самом шифровальщике, сколько в червеобразной природе. Эксплуатация уязвимости EternalBlue в протоколе SMB позволяла заразе бесконтрольно расползаться по локальным сетям без малейшего участия пользователя — точная копия поведения Морриса с демонами sendmail и fingerd.

  • Современные APT-группировки: Многовекторность (использование сразу нескольких уязвимостей для надежного проникновения) и маскировка в памяти (бесфайловые угрозы, переименование процессов) стали золотым стандартом для серьезных хакеров.

Преступление и наказание: Правовой прецедент До 1988 года правоохранительные органы с трудом понимали, как судить за компьютерные инциденты, если физически ничего не украдено и не сломано. В США с 1986 года существовал закон Computer Fraud and Abuse Act (CFAA), но он был скорее теорией, чем практикой. Роберт Тэппан Моррис стал первым человеком в истории, осужденным по этому акту.

Учитывая отсутствие злого умысла (Моррис не пытался ничего сломать) и тот факт, что он сам попытался анонимно разослать инструкцию по остановке червя, а позже признался властям под давлением отца (работавшего криптографом в АНБ), суд был относительно мягок.

В 1990 году Моррис получил 3 года условно, 400 часов общественных работ и штраф в размере $10 050. Однако этот приговор создал важнейший юридический прецедент: несанкционированный доступ, написание и запуск саморазмножающегося кода официально стали уголовным преступлением, независимо от изначальных мотивов автора.

6. Заключение: Ирония, длиною в сорок лет

За прошедшие десятилетия глобальная сеть проделала огромный путь. Мы навсегда распрощались с уютной архитектурой доверенных узлов и пришли к параноидальной концепции Zero Trust (нулевого доверия). Сегодня безопасники исходят из презумпции виновности: мы по умолчанию не доверяем ни пользователям, ни устройствам, ни даже собственному внутреннему трафику. И первый, самый важный шаг на этом пути заставил нас сделать именно 23-летний аспирант с его 99 строками кода.

Но во всей этой истории есть одна невероятно горькая ирония.

Мы живем в эпоху нейросетей, облачных вычислений, квантовой криптографии и многоуровневых песочниц. Однако если вы откроете отчеты о расследовании крупнейших инцидентов последних лет, вы увидите до боли знакомую картину. Спустя почти сорок лет индустрия всё ещё отчаянно борется с уязвимостями управления памятью (переполнения буферов остаются главной головной болью кода на C/C++), учетками с паролями из топ-100 и выставленными голой спиной в интернет сервисами с дефолтными конфигурациями. Технологии изменились до неузнаваемости, а вот векторы атак, как и человеческая беспечность, остались прежними.

Червь Морриса стал первым инцидентом, который потряс основы интернета и породил индустрию ИБ. Но история на этом не закончилась.

Анонсы новых статей, полезные материалы, а так же если в процессе у вас возникнут сложности, обсудить их или задать вопрос по этой статье можно в моём Telegram‑сообществе. Смело заходите, если что‑то пойдет не так, — постараемся разобраться вместе.

ссылка на оригинал статьи https://habr.com/ru/articles/1042476/