До сих пор рассматриваемые нами способы маскировки трафика сводились к сокрытию сетевых соединений, но на физическом уровне весь левый трафик элементарно обнаруживался сниферами и прочими защитными средствами. Вот хакеры и напряглись, решив эту проблему путем создания секретных пассивных каналов, передающих информацию без генерации какого-либо трафика вообще. Исходные тексты движков выложены в Сеть, и все, что нам нужно, - это разобраться, как их прикрутить к нашему кейлоггеру или удаленному шеллу, чем мы сейчас и займемся.
Забросить shell-код на удаленную машину и застолбить там back-door - это только половина дела. А что делать дальше, мы подумали? Необходимо скрыть свой IP-адрес и обойти все брандмауэры, не оставляя никаких следов в логах, анализируемых как вручную, так и автоматизированными системами определения вторжения. Существует множество утилит, прячущих левые сетевые соединения от глаз администраторов, однако на физическом уровне весь «хакерский» трафик элементарно обнаруживается и пресекается практически любым брандмауэром, чего атакующему допускать ни в коем случае нельзя. В идеале необходимо пробить тоннель, открыв секретный канал связи, не создающий никаких дополнительных соединений и не генерирующий никакого избыточного трафика, чтобы даже самый строгий разбор дампов, награбленных сетевым анализатором, не выявил ничего подозрительного.
Над решением этой проблемы бились лучшие хакерские умы. Сначала идея получила чисто теоретическое обоснование (Andrew Hintz, Craig Rowland) с чисто лабораторной реализацией, непригодной для практического использования. Затем к делу подключилась Жанна Рутковская, разработавшая специальный протокол с кодовым названием NUSHU и вполне жизнеспособные модули, ориентированные на работу в Linux Kernel 2.4. Жанна вручила нам мощное средство для управления удаленными shell'ами, от которого практически невозможно разработать адекватную защиту. Осталось только разобраться, как этим средством воспользоваться.
Скрытые пассивные каналы: основные концепции
С недавних пор в хакерском лексиконе появилось понятие «скрытых пассивных каналов» (Passive Covert Channels, или сокращенно PCC). Они представляют собой разновидность обычных скрытых каналов (Covert Channels), однако, в отличие от последних, не только не устанавливают своих соединений, но и вообще не генерируют никакого собственного трафика! Передача информации осуществляется исключительно путем модификации пакетов, пролетающих мимо атакованного узла.
Соль в том, что эти пакеты направляются не к хакеру, а шуруют своими путями на различные узлы интернета, например, wwwgoogle.com, за счет чего достигается высочайшая степень анонимности. Естественно, возникает резонный вопрос: как хакер сможет добраться до содержимого пакетов, идущих мимо него? Для этого необходимо подломать один из промежуточных маршрутизаторов (как правило, принадлежащих провайдеру, обслуживающему атакуемую организацию) и установить на него специальный модуль, анализирующий заголовки TCP/IP-пакетов на предмет наличия скрытой информации или ее внедрения.
Таким образом, хакер организует двухсторонний секретный пассивный канал связи с узлом-жертвой, не только засекретив факт передачи левой информации, но еще и надежно замаскировав свой IP, который может определить только администратор взломанного маршрутизатора, но никак не владелец узла-жертвы!
Прячем трафик: техника сокрытия IP-трафика с помощью секретных пассивных каналов
Рассмотрим схему взаимодействия с целевым узлом (жертвой) по скрытому пассивному каналу. Хакер (обозначенный буквой Х) каким-то совершенно не относящимся к обсуждаемой теме образом забрасывает на целевой узел (обозначенный буквой A) shell-код, захватывающий управление и устанавливающий back-door вместе со специальным модулем, обеспечивающим функционирование PCC-канала. Теперь все TCP/IP-пакеты, отправляемые жертвой во внешний мир, содержат незначительные изменения, кодирующие, например, пароли или другую конфиденциальную информацию.
Часть этих пакетов проходит через внешний маршрутизатор B, заблаговременно взломанный хакером, внедрившим в него PCC-модуль. PCC-модуль анализирует заголовки всех TCP/IP-пакетов на предмет скрытого содержимого, после чего декодирует его и отправляет хакеру по открытому каналу. Передача данных от хакера к жертве осуществляется по аналогичной схеме. PCC-модуль, установленный на маршрутизаторе, выявляет пакеты, направленные на целевой IP-адрес, и модифицирует их заголовки в соответствии с выбранным принципом кодирования информации.
Таким образом, мы получаем защищенный канал A-B и открытый B-X, однако хакеру ничего не стоит общаться с узлом B через анонимный proxy-сервер или даже выстроить цепочку из нескольких защищенных хостов. К тому же, выбор маршрутизатора B необязателен. Главное, чтобы маршрутизатор располагался между целевым узлом А и одним из узлов, с которыми общается жертва.
Во власти протокола IP
Возьмем протокол IP и попробуем создать на его основе скрытый пассивный канал. Среди множества полезных и бесполезных полей заголовка наше внимание привлекает 16-битовое поле Identification, генерируемое операционной системой случайным образом и используемое для идентификации дейтаграммы в случае ее фрагментации. Узел-получатель группирует фрагменты с одинаковыми IP-адресами источника/назначения, типом протокола и, разумеется, идентификатором.
Строгих правил, определяющих политику генерации идентификатора, в RFC нет. Одни операционные системы используют для этого таймер, другие вычисляют идентификатор на основе TCP-пакетов, чтобы при повторной передаче TCP-сегмента IP-пакет использовал тот же самый идентификатор, однако даже если идентификатор окажется иным, ничего ужасного не произойдет. Ну подумаешь, чуть-чуть упадет скорость.
Фишка в том, что PCC-модуль может беспрепятственно модифицировать поле идентификатора по своему вкусу, передавая с каждым IP-пакетом 16 бит полезных данных. Это в теории. На практике же нам потребуется выделить несколько бит для маркировки своих пакетов, иначе PCC-приемник ни за что не сможет отличить их от остальных. Пусть в 12 младших битах передаются полезные данные, а в четырех старших - их контрольная сумма. Тогда PCC-приемнику останется всего лишь взять 12 бит, рассчитать их CRC и сравнить с оставшимися четырьмя битами. Если они совпадут, значит, это наш пакет, если же нет - пускай идет себе лесом.
Также следует позаботиться о нумерации пакетов, поскольку порядок следования IP-пакетов в общем случае не совпадает с порядком их отправки. А для этого также требуются биты, в результате чего реальная информационная емкость IP-заголовка стремится к одному байту, что, в общем-то, не так уж и плохо. Для передачи небольших объемов данных (типа паролей) вполне сойдет. Главное - не забывать о том, что идентификатор должен: а) быть уникальным; б) выглядеть случайным. Поэтому необходимо прибегнуть к скремблированию, то есть к наложению на передаваемый текст некоторой псевдослучайной последовательности данных (известной как PCC-отправителю, так и PCC-получателю) через оператор XOR.
Кроме идентификатора, можно (с некоторой осторожностью) менять поля TTL (Time To Live – максимальное время жизни пакета), тип сервиса (TOS) и протокола (protocol). Однако это слишком заметно и легко обнаруживается просмотром дампов, полученных любым снифером.
Наш извозчик - протокол TCP
При установке TCP-соединения передающая сторона (узел A) устанавливает флаг SYN и выбирает произвольный 32-битный номер последовательности (Sequence Number, или сокращенно SEQ). Если принимающая сторона (узел B) согласна принять узел А в свои объятия, она отправляет ему пакет с установленным флагом ACK и номером подтверждения (Acknowledgment Number), равным SEQ+1, а также генерирует свой собственный номер последовательности, выбираемый случайными образом. Узел A, получив подтверждение, поступает аналогичным образом, что наглядно демонстрирует следующая схема:
узел A ------ SYN(ISN) -----------> узел B
узел A <----- SYN(ISN+1)/ACK ------ узел B
узел A ------ ACK ----------------> узел B
ISN – это начальный номер последовательности (Initial Sequence Number), уникальный для каждого TCP/IP-соединения. С момента установки соединения номера последовательности планомерно увеличиваются на количество принятых/отправленных байт. Впрочем, не будем углубляться в теорию. Остановимся на том факте, что 32-битное поле ISN можно изменять псевдослучайным образом, «промодулированным» секретными данными и... никто ничего не заметит! Конечно, пропускная способность упадет до четырех байт на каждое TCP-соединение, устанавливаемое узлом-жертвой, а TCP-соединений устанавливается не так уж и много (особенно если мы имеем дело не с нагруженным сервером, а с рабочей станцией). Тем не менее, для перекачки паролей и удаленного управления через командную строку даже такой скромной пропускной способности вполне достаточно.
Жанна Рутковская, решив не ограничивать себя лабораторными опытами, разработала протокол NUSHU, создающий скрытые пассивные каналы посредством модификации ISN с последующим шифрованием последнего алгоритмом DES на основе идентификатора IP-пакета (IP.id), порта-источника (TCP.sport) и IP-адреса назначения (IP.daddr).
Сеанс практической магии
Идем на сайт Жанны Рутковской - invisiblethings.org, видим раздел с инструментами tools, находим в нем «NUSHU - passive covert channel engine for Linux 2.4 kernels» и качаем архив исходных текстов - invisiblethings.org/tools/nushu/nushu.tar.gz (всего 18 Кб). Распаковываем, компилируем. Компиляция осуществляется стандартно. Просто запускаем утилиту make и получаем три модуля ядра: nushu_receiver.o (приемник), nushu_sender.o (передатчик) и nushu_hider.o.
Прячем трафик: техника сокрытия IP-трафика с помощью секретных пассивных каналов
Приемник устанавливается на поломанный маршрутизатор, передатчик - на целевой узел жертвы. Для организации двухсторонней связи приемник и передатчик устанавливаются на оба узла. Модуль nushu_hider.o в организации скрытого канала не участвует и предназначен для обмана штатных анализаторов (типа tcpdump), не позволяя им обнаруживать факт изменения ISN.
Из readme следует, что модуль-передатчик обрабатывает следующие параметры командной строки:
* dev=, где device – сетевое устройство, с которым предполагается работать (например, eth0);
* cipher=[0|1], где 0 означает передачу без шифрования, а 1 предписывает использование DES;
* key="string", где string - произвольная строка-маркер, идентичная строке-маркеру, установленной на модуле-приемнике (используется только в том случае, если шифрование выключено, иначе игнорируется);
* src_ip= - IP-адрес узла, на котором установлен передатчик.
Модуль-приемник, помимо описанных выше ключей dev, cipher и key, обрабатывает аргумент exclude_ip=, задающий список неприкосновенных IP-адресов, при отправке пакетов на которые протокол NUSHU задействован не будет, поскольку ISN останется неизменным (этот параметр является опциональным).
Модуль nushu_hider.o загружается без каких-либо параметров и только в том случае, если в этом возникает необходимость.
Хорошо, все модули успешно загружены, ядро функционирует нормально и в панику, судя по всему, впадать не собирается. Что делать дальше? А ничего! Ведь это только движок, обеспечивающий функционирование PCC-каналов. К нему можно прикрутить кейлоггер или удаленный shell, но это уже придется делать самостоятельно. А как?! Ни readme, ни сопроводительные презентации не дают ответа на этот вопрос, поэтому приходится зарываться в исходные тексты и разбирать их на отдельные байты.
Начнем с передатчика, реализованного в файле sender.c. В процедуре init_module(), отвечающей за инициализацию модуля, сразу же бросаются в глаза следующие строки:
struct proc_dir_entry *proc_de = proc_mkdir ("nushu", NULL);<br />
create_proc_read_entry ("info", 0, proc_de, cc_read_proc_info, NULL);<br />
struct proc_dir_entry * wpde = create_proc_entry ("message_to_send", 0, proc_de);
Все ясно! Модуль использует псевдофайловую систему /proc, создавая директорию nushu, а в ней - два файла: info и message_to_send, с которыми можно работать с прикладного уровня, как с обычными устройствами (если быть точнее, псевдоустройствами). Аналогичным образом обстоят дела и с приемником, реализованным в файле receiver.c, ключевой фрагмент которого приведен ниже:
struct proc_dir_entry *proc_de = proc_mkdir ("nushu", NULL);<br />
create_proc_read_entry ("message_received", 0, proc_de, cc_read_proc_message, NULL);<br />
create_proc_read_entry ("info", 0, proc_de, cc_read_proc_info, NULL);
Как видно, вместо устройства message_to_send на этот раз создается message_received, из которого можно читать получаемые сообщения через стандартные функции ввода/вывода. В общем, имея на руках исходные тексты, со всеми этими причиндалами совсем несложно разобраться, тем более что их суммарный объем составляет всего 69 Кб.
Заключение
Помимо описанных, существуют и другие транспортные средства, пригодные для передачи скрытого трафика, например, опция штампа времени в TCP-заголовке. HTTP-протокол дает еще большие возможности, поскольку включает в себя множество факультативных полей, которые можно безболезненно модифицировать в весьма широких пределах. Однако все это слишком заметно, и наиболее стойким к обнаружению на сегодняшний день остается протокол NUSHU, работающий с ISN.
Может ли атакованный администратор обнаружить скрытые пассивные каналы хотя бы теоретически? Скрупулезный анализ сетевого трафика позволяет выявить некоторую ненормальность распределения ISN, но для этого требуется обработать сотни тысяч «хакнутых» пакетов, сравнивая их с оригиналами. Потому намного проще выявить посторонний ядерный модуль, отвечающий за создание и поддержку PCC-каналов, используя общие методики верификации целостности системы. Однако это уже совсем другой разговор, к которому мы еще вернемся.