mirai

Mirai

По данным исследователей Сэма Эдвардса и Иоанниса Профетиса из Rapidity Networks, в 2016 году Linux.Mirai заразил более 380 тысяч умных устройств по всему миру, став причиной множества нашумевших DDoS-атак. После того как исходники этого трояна были выложены в паблик, изучением принципов его работы тут же заинтересовались не только специалисты по информационной безопасности, но и тысячи анонимных вирусописателей.

Сам по себе исходный код Mirai тоже имеет ряд заимствований из других источников и во многом базируется на архитектуре одного из DDoS-ботов, распространявшихся весной 2016 года. Этот бот, в свою очередь, имеет схожие черты с троянами семейства Fgt, известного аж с 2014 года, — оттуда была явно скопирована функция флуда и генератор псевдослучайных данных для заполнения пакетов, отсылаемых на атакуемые хосты. Такое «перекрестное опыление», в целом характерное для разработчиков open source софта для Linux, по всей видимости, прижилось и в среде ориентирующихся на эту платформу вирмейкеров.

Все ранние версии Mirai для разных аппаратных архитектур были статически скомпилированы и использовали стандартную библиотеку uClibc.so, предназначенную для встраиваемых систем на базе uCLinux. При запуске троян выделял область памяти, в которую загружал необходимый для его работы конфиг.

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

Еще одна примечательная функция ранних версий Mirai — способность трояна в отдельном потоке убивать работающие процессы других конкурирующих ботов, читая в непрерывном цикле содержимое папки /proc/. Список названий процессов хранился в конфиге. А вот в обработчике конфига авторы Mirai допустили небольшой баг: список процессов читался блоками по 2048 байт, после чего поиск названия выполнялся внутри этого буфера. Если искомое значение располагалось на границе блока, оно игнорировалось, и такой процесс избегал общей печальной участи.

Чтобы предотвратить случайную выгрузку собственного процесса, троян размещал в его папке файл .shinigami — при обнаружении файла с этим именем процесс автоматически исключался из «расстрельного списка». Однако в самом коде зловреда был зашит лимит жизнедеятельности на зараженном устройстве: по истечении недели непрерывной работы процесс Mirai автоматически завершается.

Описываемая здесь ранняя версия Mirai умела выполнять с десяток команд, среди которых — команды на установку и завершение TCP-соединения с указанным хостом и различные виды флуда по протоколам HTTP, UDP и UDP over GRE. Также с помощью этого трояна можно было организовать DNS flood и TSource Query Flood, то есть целый комплекс атак на отказ в обслуживании.

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

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

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

С помощью специального набора команд оператор мог очень гибко настраивать параметры атаки: определять значения TCP-флагов, указывать такие характеристики пакетов, как maximum segment size и timestamp, отправлять пустые пакеты, пакеты со случайными значениями или информацией из конфигурации трояна, задавать целевой порт и размер отсылаемых данных, а также управлять прочими TCP-параметрами.

Кроме всего прочего, Mirai позволял флудить на заданный узел инкапсулированными пакетами GRE с использованием Transparent Ethernet Bridging. В этом случае встроенный пакет включал в себя полноценный Ethernet-фрейм, в котором MAC-адреса как получателя, так и отправителя Mirai генерировал случайным образом.

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

Один из важных функциональных модулей Mirai — сканер уязвимых хостов, с которыми можно соединиться по протоколу Telnet. Этот сканер был практически полностью позаимствован из исходников Linux-трояна Fgt.

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

А теперь по порядку. Для начала сканер создает 256 структур данных, содержащих случайный IP-адрес, параметры сокета и другую полезную информацию. Из списка генерируемых адресов исключаются все локальные и частные диапазоны. Затем с каждым из них трой пытается установить соединение, при возникновении ошибки отсылая на собственный управляющий сервер сообщение.

В ответах атакуемого узла сканер ищет строки user, login, pass, dvrdvs или name, указывающие на требование передачи логина, который он и отправляет, воспользовавшись словарем из конфига.

Если логин успешно угадан, на управляющий сервер уходит сообщение login prompt found с указанием номера структуры и порядкового номера задачи, в противном случае троян рапортует об ошибке или тайм-ауте.

Затем в ответе хоста ищутся строки, указывающие на запрос пароля. Если они обнаружены, хосту передается строка из словаря, а полученный ответ проверяется на наличие значений invalid, incorrect, fail, again, wrong, accessdenied, error, bad, success, busybox, shell или dvrdvs. Они свидетельствуют об успехе или провале авторизации.

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

Если авторизация прошла успешно, на взломанный хост отправляется команда wget, которая выкачивает с управляющего сервера и сохраняет в папку /tmp/ sh-скрипт. Он, в свою очередь, загружает из сети бинарный файл трояна, соответствующий архитектуре устройства. С помощью этого нехитрого алгоритма организуется автоматическое распространение Mirai и заражение новых умных устройств, из которых впоследствии формируется ботнет.

Show must go on

Любой программный продукт эволюционирует со временем: его создатели устраняют выявленные ошибки и понемногу добавляют новые функции. Это в полной мере относится и к Mirai.

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

Был полностью переписан генератор псевдослучайных значений, а при запуске Mirai определял IP-адрес зараженного девайса, постучавшись на DNS-сервер Google (раньше он обращался для этого к собственному управляющему серверу). Троян научился взаимодействовать с обработчиками сигналов и игнорировать SIGINT посредством sigprocmask с очевидной целью не дать пользователю принудительно остановить вредоносный процесс.

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

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

Если вредоносу не удавалось создать сокет и подключиться к нему, троян находил владеющий сокетом процесс и убивал его: таким образом исключалось зависание программы при циклических попытках установить связь посредством функции bind с занятым сокетом. Вот почему для защиты от Mirai некоторые специалисты по информационной безопасности рекомендовали заблокировать на устройстве TCP-порт 48101, если он не используется, — это нарушало нормальную работу встроенного в троян сервера.

В обновленной версии была полностью пересмотрена самозащита: вместо костыля с файлом .shinigami троян научился определять PID и не убивал процесс, идентификатор которого совпадал с текущим. И без того богатые функции Mirai пополнились возможностью устраивать атаки типа DNS Amplification, зато в списке исчез флуд по протоколу HTTP — впрочем, в одной из следующих версий он вернулся на свое законное место.

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

Еще один интересный момент: сразу после запуска Mirai удалял с диска собственный исполняемый файл. Наконец, при обнаружении процесса с именем .anime троян не просто выгружал его из памяти, но еще и уничтожал соответствующий исполняемый файл — чем-то создатели этого бота явно насолили разработчикам.

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

Наследники империи

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

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

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

Менялись используемые Mirai порты, чтобы обеспечить дальнейшую работу трояна, если владелец устройства заблокирует ранее известные. Затем Mirai начал использовать эксплоиты для известных уязвимостей в Linux-прошивках IoT-устройств.

На основе кода Mirai некоторые энтузиасты попытались разработать собственные версии троянов для Linux вроде широко известного в узких кругах изделия мексиканских программистов под названием BrickBot, таскавшего с собой эксплоиты для уязвимостей CVE-2018-10561 и CVE-2018-10562. Этот трой получил заслуженную популярность тем, что скачивал и запускал на зараженном девайсе shell-скрипт, который порой благополучно «окирпичивал» устройство.

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *