Содержание статьи
Компрометация гипервизора или связанной с ним инфраструктуры может поставить под угрозу целую экосистему серверов, баз данных и бизнес‑приложений. Неудивительно, что хакерские группы все чаще фокусируют свои атаки на VMware ESXi, создавая специализированные программы‑шифровальщики, нацеленные на файлы виртуальных машин, такие как *.
, *.
, *.
, *.
, *.
и другие. Сегодня мы рассмотрим конкретный случай, в котором был обнаружен бинарный ELF-файл с именем encrypt
и сопровождающий его Bash-скрипт encrypt.
. Я подробно опишу этапы атаки: от проникновения в сеть и получения доступа к ESXi до запуска файлов, шифрования виртуальных дисков и устранения следов, что оставляет жертву перед выбором — заплатить выкуп или потерять данные.
Уязвимость и общая схема атаки
Чтобы понять всю глубину этого инцидента, нужно рассмотреть последовательность действий атакующих от момента эксплуатации уязвимости CVE-2021-44228 на VMware Horizon до непосредственного запуска шифрования на ESXi. Уязвимость, получившая название Log4Shell, стала широко известна зимой 2021–2022 годов и давала возможность злоумышленникам выполнять произвольный код в контексте сервера, где используется логирующая библиотека Log4j уязвимых версий. VMware Horizon, будучи сложным продуктом, базирующимся на Java и в прошлом включавшим уязвимые компоненты, иногда оставался непропатченным, что открывало возможность провести RCE-атаку (remote code execution).
Злоумышленник, имея специальный эксплоит, мог переслать серверу Horizon пакет, включавший вызов к JNDI с вредоносным классом. Библиотека Log4j динамически загружала его и исполняла. Как только этот класс попадал в среду исполнения, он раскрывал перед атакующим безграничные возможности — от установки дополнительного malware-инструментария до внедрения скриптов и эскалации на уровень локального администратора. Именно так, согласно собранным данным, в ряде случаев удавалось проникнуть в корпоративную сеть и скомпрометировать сервер Horizon.
После эксплуатации уязвимости CVE-2021-44228 атака не останавливается на одной машине, ведь обычно злоумышленникам интересны более масштабные цели. Поэтому они анализируют сетевую среду, отыскивают уязвимые узлы и, самое важное, осуществляют атаку SAM-хранилища в попытке извлечь NTLM-хеш локального администратора. Если в компании на многих серверах используется один и тот же пароль локального админа (или хотя бы на нескольких ключевых машинах), это дает атакующим возможность перемещаться по сети (lateral movement) при помощи pass-the-hash.
Когда обнаруживается узел, где запущена сессия пользователя из группы «Администраторы домена», то дамп lsass.
или аналогичное средство позволяет получить NTLM-хеш доменного админа, после чего злоумышленники могут выполнить любые действия от имени доменного администратора, в том числе получить доступ к ESXi, если настроена аутентификация через доменные учетные записи.
Если учетка Domain Admin без жесткой изоляции тоже имеет право подключаться к ESXi, то злоумышленники этим непременно воспользуются, ведь, овладев доменными привилегиями, они без труда загрузят нужную вредоносную программу в /
или другой каталог на гипервизоре (с помощью SCP или иным способом). В нашем случае атакующие загружают файлы encrypt
и encrypt.
— двух компонентов, которые действуют в связке.
Анализ вредоносных файлов
Анализ показал, что ELF-бинарь encrypt
представляет собой модуль‑вымогатель, написанный под 64-битную Linux-платформу. В ESXi внутренне используется Linux-образ, поэтому запуск ELF-файла напрямую там возможен, особенно если установлен параметр execInstalledOnly
(или скомпилированы нужные shared-библиотеки).
Логика запуска файла encrypt
— обработка ошибки, когда нет ссылки на файл для шифрования. Если ссылка присутствует, то запускается процесс шифрования.
Бинарь при старте ждет от пользователя аргумента — пути к файлу, который будет шифроваться. При этом, если верить дизассемблеру, в коде реализованы криптопримитивы Curve25519 (для обмена или генерации ключей) и Sosemanuk (для быстрого шифрования). Давай разберем всю последовательность действий этой софтины.
Вот примерный пошаговый алгоритм выполнения функции.
-
Открытие файла. Файл открывается для чтения и записи в бинарном режиме. Если открыть файл не удалось (
fopen64
вернулNULL
), функция возвращает 1. -
Выделение памяти под ключ и инициализация базы данных значениями.
-
Декодирование строки Base64 и генерация ключа.
В коде можно найти вот такие константы:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Они используются для Base64 в процессе декодирования встроенной строки‑ключа, «вшитой» прямо в бинарь. Исходная длина decoded_length
записывается сюда же, прочитанная строка используется для генерации нового ключа функцией generate_key
.
Функция generate_key
принимает шесть аргументов:
-
_int64
— первый приватный ключ для Curve25519;privateKey1 -
_int64
— второй приватный ключ для Curve25519;privateKey2 -
_BYTE
— указатель на буфер состояния Sosemanuk (поточного шифра);*sosemanukStateBuffer -
_BYTE
— указатель на 32-байтовый массив для работы с Curve25519;*curve25519PrivateArray -
_int64
— буфер для результата первого вызова функции curve25519_donna;sharedSecret1 -
_int64
— буфер для результата второго вызова функции curve25519_donna.sharedSecret2
Шаги выполнения этой части вредоносного приложения.
- Очистка памяти. На этом этапе очищаются массивы для последующего использования, чтобы гарантировать отсутствие остаточных данных.
- Модификация битов (в первом и последнем байтах массива). Это стандартная процедура для корректной настройки закрытого ключа для алгоритма Curve25519.
- Генерация общего секрета с использованием алгоритма Диффи — Хеллмана посредством Curve2579. Функция
curve25519_donna
задействована для выполнения операций Диффи — Хеллмана с использованием алгоритма Curve25519. ЗначенияsharedSecret1
иsharedSecret2
генерируются с помощью закрытого ключаcurve25519PrivateArray
и двух разных открытых ключейprivateKey1
иprivateKey2
. - После вычислений закрытый ключ
curve25519PrivateArray
очищается с помощью функцииsecure_memset
, чтобы предотвратить утечку чувствительной информации. - Создается хеш SHA-256 от
sharedSecret2.
иsha256_init( ) sha256_hash(
, подготавливается и вычисляется хеш.) -
secure_memset()
очищает память, использованную для вычисления SHA-256, чтобы удалить промежуточные данные.; -
sosemanuk_schedule(
готовит внутренние состояния для шифра Sosemanuk на основе ключа (результата SHA-256).) -
sosemanuk_init(
завершает инициализацию шифра, передавая подготовленный контекст.) - После использования ключа из SHA-256 он очищается с помощью
secure_memset
.
На следующем этапе выполняется инициализация списка разделов и проверка файловой системы.
Эта часть кода, как можно понять из названия функций, отвечает за создание списка разделов init_partition
, а также за добавление нового раздела, если таковых нет или получено неверное значение функции check_file_system
.
Затем программа проверяет, является ли входная структура валидной MBR или GPT.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее