Защита от хакеров корпоративных сетей
Шрифт:
/* Handle ICMP ECHO (Ping) */
} else if (!memcmp(eth->ether_dhost, user_mac,
ETHER_ADDR_LEN) &&
ntohs(eth->ether_type) == ETHERTYPE_IP &&
memcmp((u_char *) & ip->ip_dst, user_ip,
IPV4_ADDR_LEN) &&
ip->ip_p == IPPROTO_ICMP &&
icmp->icmp_type == ICMP_ECHO) {Ах, утилита ping! Как автор по тебе тоскует! Без всякого сомнения, это лучшее средство определения, в каком режиме работает хост: в сети или автономно. Пытаясь достичь хоста, утилита не ищет сведений о нем в ARP-кэше. В процессе работы утилита отображает результат обработки текущих запросов. Фактически утилита ping является эхо-сигналом подканала ICMP протокола IP, направленного к адресуемому хосту с параметром IP ethertype и верным аппаратным адресом. Для того чтобы удостовериться в том, что полученный пакет является пакетом утилиты ping, проверяются пять условий. Несколько необычный способ принятия решения используется для проверки протокола IP, но он работает:
/* Swap Source and Destination MAC addresses */
memcpy(test_mac, eth->ether_dhost, ETHER_ADDR_LEN);
memcpy(eth->ether_dhost, eth->ether_shost, ETHER_ADDR_LEN);
memcpy(eth->ether_shost, test_mac, ETHER_ADDR_LEN);Алиса посылает пакет Бобу… Боб отвечает Алисе пакетом с инвертированными значениями полей. Все, что делается в приведенном ниже примере, – это инвертирование значений полей отправителя и получателя, для того чтобы сформировать ответ:
/* Swap Source and Destination IP addresses */
test_ipa = ip->ip_dst;
ip->ip_dst = ip->ip_src;
ip->ip_src = test_ipa;То же самое, что было сделано для MAC-адресов, теперь делается на сетевом уровне для IP-адресов:
/*
* Change the packet to a reply, and decrement time
* to live
*/
icmp->icmp_type = ICMP_ECHOREPLY;
ip->ip_ttl—;Системы, подверженные какому-либо
/* Recalculate IP and TCP/UDP/ICMP checksums */
libnet_do_checksum(packet + LIBNET_ETH_H, IPPROTO_IP,
LIBNET_IP_H);
libnet_do_checksum(packet + LIBNET_ETH_H, IPPROTO_ICMP,
pkthdr.caplen – LIBNET_ETH_H – LIBNET_IP_H);Поскольку данные пакета были модифицированы (было уменьшено значение предписанного времени жизни пересылаемого пакета TTL), то следует откорректировать контрольные суммы, гарантируя тем самым целостность пакета при воздействии на него шума, помех или чего-то еще. Способ формирования контрольных сумм применяется на транспортном уровне (протоколы TCP/UDP/ICMP), который обеспечивает доставку между конечными точками сети. Контрольные суммы обычно применяются в протоколе ICMP. Для протоколов TCP и UDP метод контрольных сумм не применяется из-за сложностей успешного его применения в протоколе IP. В данном примере использование контрольной суммы рассматривается только для примера. В реальных условиях приведенный алгоритм маршрутизации работает гораздо лучше. При вызове алгоритма маршрутизации для указания длины обрабатываемых данных используется поле ip->ip_len, что, возможно, приводит к уязвимости этого способа к некоторым типам атак (из-за излишнего доверия к значению переменной, представляющей фактическую длину полного набора данных). Так что будьте внимательны:
i = libnet_write_link_layer(l, dev, packet, pkthdr.caplen);
if (verbose)
fprintf(stdout, “ICMP: Wrote %i bytes\n”, i);
/* Route Packet */
} else if (!memcmp(eth->ether_dhost, user_mac,
ETHER_ADDR_LEN)) {
memcpy(eth->ether_dhost, upstream_mac,
ETHER_ADDR_LEN);
memcpy(eth->ether_shost, user_mac, ETHER_ADDR_LEN);После того что пришлось сделать для протокола ICMP, самостоятельно реализовать функции маршрутизатора не очень сложно. Следует только выбрать любой, не предназначенный программе пакет, передающийся по фальсифицированному адресу аппаратных средств, и отослать его другому MAC-адресу. Вполне возможно, что придется еще раз уменьшить значение предписанного времени жизни пересылаемого пакета TTL:
if (do_checksum == 1) {
ip->ip_ttl—;
libnet_do_checksum(packet + LIBNET_ETH_H, IPPROTO_IP,
LIBNET_IP_H);
libnet_do_checksum(packet + LIBNET_ETH_H, ip->ip_p,
ntohs(ip->ip_len) – LIBNET_IP_H);
}Обратите внимание, что, по всей видимости, нет особой необходимости принимать какие-либо меры по поводу странных пакетов, которые передаются по отличающимся от IP протоколам и создают помехи для контрольных сумм. Ведь только хосты, посылающие по протоколу IP ARP-запросы, интересуют фальсифицированные MAC-адреса. Но, на всякий случай, будет лучше, если дополнительно ввести проверку на попытку маршрутизации пакета IP. То, что программа предоставляет больше свободы действий, чем ядра современных операционных систем, означает, что в большинстве случаев ядра операционных систем предполагают, что они поддерживают работу с дружественным TCP/IP-стеком. В этом заключается клад возможностей спуфинга. Независимо от причин, почему так происходит, в интересующих исследователя случаях почти всегда попытки спуфинга могут быть повторно проанализированы и найдены способы противодействия им. Если для этого появятся достаточные основания, то можно случайным образом создать шумовые помехи, изменить представляющие интерес специфические строки, по требованию отослать пакеты, ограничить полосу пропускания, создать новые IP-адреса для хостов своей и даже чужой подсети. Это всего лишь инфраструктура. Дело в том, что нет никакой необходимости даже в небольшой части аппаратных средств для осуществления действительно интересных вещей. Некоторые вполне прилично кажущиеся программы будут фальсифицировать то, что нужно злоумышленнику, а сети окажутся недостаточно мудрыми, чтобы противостоять этому. Все, что злоумышленник может сделать, – это отослать следующее:
i = libnet_write_link_layer(l, dev, packet, pkthdr.caplen);
if (verbose)
fprintf(stdout, “DATA: Sent %i bytes to %s\n”, i,
inet_ntoa(ip-
>ip_dst));
}}}
/* Enough for now ... */
pcap_close(pcap);
return EXIT_SUCCESS;
}
void
print_ip(FILE * stream, u_char * ip)
{
fprintf(stream, “%i.%i.%i.%i\n”, ip[0], ip[1], ip[2],
ip[3]);
}
void
print_mac(FILE * stream, u_char * mac)
{
fprintf(stream, “%X:%X:%X:%X:%X:%X\n”, mac[0], mac[1],
mac[2], mac[3], mac[4], mac[5]);
}Осталось сказать несколько слов об очистке ресурсов. Большинство систем имеют ограничение на число одновременно захваченных пакетов как следствие ограничений ядра операционной системы, которые задаются во время компиляции. У программы имеется дескриптор файла захваченных пакетов, который закрывается при ее завершении. Обработка захваченных пакетов ведется в бесконечном цикле. В случае аварийного завершения программы код обработки никогда не будет выполнен. Прежде чем приложение завершится, будущему коду пользователя может потребоваться цикл обработки захваченных пакетов. Убедитесь, что по завершении работы все будет закрыто!
void usage
{
fprintf(stderr, “DoxRoute 0.1: Userspace TCP/IP Router, by
Dan Kaminsky (dan@doxpara.com)\n”);
fprintf(stderr, “
Usage: doxroute [-i interface] [-m userspace_mac]\n”);
fprintf(stderr, “
[-r/R upstream_ip/mac] [-cv] userspace_ip\n\n”);
fprintf(stderr, “
Example: doxroute -r 10.0.1.254 10.0.1.169\n”);
fprintf(stderr, “
Options: \n”);
fprintf(stderr, “
– i [interface] : Select the interface to be used.\n”);
fprintf(stderr, “
– r [upstream_ip] : MAC Address of upstream router\n”);
fprintf(stderr, “
– R [upstream_mac] : MAC Address of upstream router/
gateway.\n”);
fprintf(stderr, “
– m [userspace_mac]: MAC Address for this software.\n”);
fprintf(stderr, “
– c : Verify Checksums(and decrement IP
TTL).\n”);
fprintf(stderr, “
– v : Verbose Mode.\n”);
fprintf(stderr, “
Notice: This is just a proof of concept. Useful stuff
later.\n”); exit(1);
}В конечном итоге была разобрана вся внутренняя часть программы DoxRoute. Вовсе не предполагается, что читатель попытается понять всю программу. Пусть он просто перепишет ее исходный текст с www.doxpara.com/tradecraft/doxroute. Следующая команда компиляции построит doxroute:
gcc “libnet-config —defines” -O3 -Wall -funroll-loops -
fomit-frame-pointer -pipe -I/usr/local/include -L/usr/local/
lib -lpcap -o doxroute doxroute.c /usr/local/lib/libnet.aМожно найти копии libnet и libpcap на их домашних страничках www.packetfactory.net/Projects/Libnet и www.tcpdump.org respectively соответственно. В особых случаях при мониторинге DoxRoute или при простой попытке изучить работу нового протокола потребуется Ethereal. По-видимому, Ethereal является лучшей системой снифинга, разработанной для UNIX. Ее можно найти по адресу www.ethereal.com. Просмотрите еще раз главу 10 для уяснения деталей снифинга более подробно.
Малоизвестное: спуфинг через асимметричные межсетевые экраны
В идеальном мире сеть является прозрачной абстракцией. Одна система хочет переговорить с другой. Для этого ей достаточно послать пакет по нужному адресу и знать, что он будет доставлен. По разным причинам вопросы адресации и ответа на полученные пакеты будут изложены в следующей главе.
Сеть стала менее прозрачной. Чаще, чем что-либо, межсетевые экраны размещаются вне защищаемой сети, и если больше нет иных средств, то они предотвращают прием данных по всем входящим соединениям, кроме явно разрешенных. К выходящим соединениям применяются более либеральные правила. В этом проявляется очень сильное свойство асимметричных систем защиты. Входящие соединения доступны только в том случае, если они явно разрешены, а все выходящие соединения, кроме явно запрещенных, разрешены.
Предположение состоит в том, что входящие соединения установлены с плохим большим внешним миром, где никому нельзя верить. А выходящие соединения инициированы из относительно небольшой локальной сети, где большинству хостов в разумной степени можно доверять. Как правило, подобное предположение справедливо, хотя и чревато проблемами в случае опутывания клиентов различными шпионскими программами. Особенно если пользователи искушены в вопросах запуска программ, которые открывают сетевые подключения от их имени. Фактически это означает, что программные обманы – не такая уж редкость в сети.
К сожалению, существует главная проблема использования межсетевых экранов. Она очевидна для сети, в которой разрешены только выходящие соединения для подключения
Сказанного уже достаточно для обозначения проблемы, которой посвящена следующая глава. В главе 13 описаны методы ее решения при помощи запутанных способов безопасного туннелирования трафика. Ранее эти способы были проклятием для проектировщиков сети.
Хотя есть другое мнение по данному вопросу. Выберем находящиеся под защитой межсетевого экрана два хоста и, возможно, незащищенный межсетевым экраном, третий хост, который может тайно послать ограниченное число данных обоим хостам. Межсетевой экран разрешает только выходящие соединения. Можно ли в этом случае так обмануть расположенные между двумя сетями межсетевые экраны, чтобы каждый из экранов думал, что другой принимает входящие соединения?
Можно. Межсетевые экраны используют соединения асимметрично, различая входящие и выходящие соединения. Но большинству соединений присуща внутренняя двусторонность, что является сетевым проявлением двунаправленных сокетов UNIX. Фактически двусторонность присутствует только во время инициализации соединения. Фальсифицируя правильный инициализирующий пакет от «правильного» хоста в правильный момент времени, вполне возможно сделать соединение симметричным во время попытки установления соединения и вынудить два межсетевых экрана установить соединение друг с другом.
Симметричное выходящее соединение по протоколу TCP: продуманная экспериментальная оболочка брокера соединения TCP с квитированиемДопустим, что нужно рассмотреть в замедленном темпе следующую ситуацию и выявить все сопутствующие ей события. Два хоста предпринимают попытки установить выходящее TCP-соединение друг с другом. Каждый из хостов находится под защитой межсетевого экрана, настроенного на пропуск только выходных данных. Рассматриваемая ситуация в первую очередь касается межсетевых экранов с возможностью трансляции сетевых адресов. Алиса при инициализации TCP-соединения начала бы с посылки пакета SYN. Отправленный Алисой пакет SYN поступает к ее межсетевому экрану, который в своей таблице состояний отмечает попытку Алисы установить соединение с Бобом. Также он запоминает, что отформатированный соответствующим образом ответ Боба должен поступить обратно Алисе. Далее пакет SYN пересылается через Интернет тому, кого Алиса увидела как Боба. Возможно, что в пакете в качестве адреса отправителя был указан адрес межсетевого экрана Алисы.
Конечно, Боб никогда не получит этот пакет, потому что на самом деле в сети в качестве Боба выступает его межсетевой экран. Межсетевой экран Боба доверяет Алисе не больше, чем ее межсетевой экран Бобу. Поэтому межсетевой экран Боба отвечает на запрос Алисы отказом в установке соединения, посылая ей пакет RSTIACK. Конечно, когда межсетевой экран Алисы получает этот пакет, он знает, что он и не собирался получать от Боба положительный ответ на запрос подключения в виде пакета SYNIACK. Поэтому он затирает входы в своей таблице состояний, огорчая тем самым Алису.
У Боба сходная проблема. Он также не может вызвать Алису. Межсетевой экран Алисы сбрасывает его запросы точно так же, как его экран сбрасывает запросы Алисы.
Если читатель задумывался о приведенном примере, то время от времени вещи выглядят не так уж плохо. Выясняется, что каждая сторона может получить у собственного межсетевого экрана достаточно прав для того, чтобы разрешить другой стороне послать пакет с кодом возврата. Проблема состоит в том, что приходящий пакет содержит отрицательный ответ. Это происходит непреднамеренно. Ни один из межсетевых экранов не захочет пропускать приходящие извне пакеты. В данном случае запрет на пропуск приходящих пакетов предотвращает внутренний мир от выведывания его тайн. Хотелось бы добиться записи служебной информации в таблицу состояний, но при этом не сбрасывать соединение. Существует ли какой-либо способ восстановления предшествующего, но не последнего состояния?
Да, существует.
«Сейчас я спою песню судьбе!» Применение пакетов с обреченным временем жизни TTL для манипуляций с таблицей локальных состояний. По существу протокол IP очень похож на протокол Lilypad, который позволяет пакетам блуждать от маршрутизатора к маршрутизатору, пока он не достигнет своего адресата. Одна очень серьезная проблема, которая может произойти при ретрансляции пакета в сети (точнее, графе сети), заключается в возникновении по различным причинам бесконечного цикла маршрутизации. Последовательность маршрутизаторов может породить круговую траекторию (цикл), которая никогда не приведет отдельно взятый пакет к адресату. Это подобно езде по кругу, когда потеряна дорога к нужному городу, а водитель находится в слишком затуманенном сознании, чтобы осознать, что он уже тридцать раз проехал мимо одного и того гипермаркета быстрого обслуживания.
В реальном мире нельзя кружить вечно. В конечном счете закончится бензин. Но у пакетов нет бензобаков. Поскольку очень важно, чтобы пакеты не передавались по внутреннему циклу, то для предотвращения этого в каждый пакет включен счетчик предписанного времени жизни пересылаемого пакета TTL. Эта величина уже обсуждалась во время построения эффективного маршрутизатора в пространстве пользователя. Клиент определяет максимальное число «прыжков», которое данный пакет может осуществить при следовании по своему маршруту до адресата (обычно эта величина равна 256). Затем каждый маршрутизатор, через который проходит пакет, уменьшает счетчик предписанного времени жизни пакета TTL на 1. Если маршрутизатор получает пакет с нулевым значением счетчика TTL, то он удаляет его из потока передачи пакетов. Возможно, что при этом по протоколу ICMP будет послано сообщение о превышении времени существования пакета. Подобные сообщения используются для трассировки маршрута. Пакету разрешается сначала осуществить один прыжок, затем другой, третий и т. д.
В сказанном скрыты очень интересные вещи. Межсетевые экраны всегда позволяют проходить через них наружу пакетам с небольшим значением счетчика предписанного времени жизни TTL. Также они пропускают назад сообщения по протоколу ICMP для их оценки клиентом. Это относится и к пакетам, которые направляются законному адресату, но из-за недостаточного значения счетчика TTL обречены на уничтожение раньше, чем достигнут его. Пакет послан с соблюдением всех правил и ограничений, но он никогда не будет получен. Это именно то, что мы ищем! Для законно посланного пакета заводится запись в таблице состояний. Но поскольку адресат этого пакета никогда не получит его, то никогда не будет получен обратный пакет с установленным признаком сброса соединения RST, который удалил бы эту запись из таблицы состояний…
По крайней мере, ни Алиса, ни Боб никогда не пришлют такой ответ.
Поборник сетевого равноправия: пакеты SYMIACK в игре. Алиса и Боб могут оба инициализировать соединение с помощью пакетов SYN. Они даже могут преобразовать предназначенный для сброса состояния пакет RST в невинное ICMP-сообщение о превышении предписанного времени жизни пакета путем посылки обреченного SYN-пакета. Но, несмотря на сказанное, в таблице состояний останется запись, ожидающая подтверждения попытки подключения. Это своего рода проблема, поскольку нет готового механизма, при помощи которого Алиса и Боб смогли бы непосредственно послать пакет SYNIACK. Подобный механизм относится к внутренним элементам принятия входящего соединения, а межсетевой экран разрешает только исходящие соединения.
В соответствии с ранее описанным алгоритмом работы возможность ответа была заблокирована.
Но только то, что Алиса не может послать пакет, еще не означает, что Боб не сможет принять его. Это лишь означает, что кто-то должен отправить пакет для Алисы. Этот кто-то, известный как брокер подключения, мог бы получить от Алисы пакет SYNIACK, который она ожидала получить от Боба, если только его межсетевой экран позволил бы ему отправить сообщение. (Подобное сообщение брокер мог бы получить от Боба, и оно содержало бы все сведения, которые он хотел бы получить от Алисы.) Посредник мог не знать о первоначальном пакете SYN, затерявшемся где-то в сети посередине между Бобом и Алисой. Но если бы оба клиента смогли предоставить достаточно информации о посланных ими пакетах SYN и сути ожидаемого от брокера ответа, то брокер соединения смог бы фальсифицировать посланные Алисе от Боба и Бобу от Алисы пакеты SYNIACK.
Автор назвал эти пакеты SYMIACK (Ack nowledgements both Sym metric and Sim ulated) ввиду того, что они являются подтверждением симметричности и имитации. Брокер имитирует передачу двух почти идентичных пакетов, но направленных в разные стороны сети. Эти специальным образом сформированные пакеты совместно используют не только одни и те же сходные структуры. Они позволяют обоим межсетевым экранам обслуживать симметричные состояния посредством цельного процесса подтверждения установления (квитирования) связи. Оба клиента посылают пакеты SYN, оба межсетевых экрана ожидают пакеты SYNIACK, оба клиента отправляют эти пакеты SYNIACK и одновременно предоставляют возможность послать пакеты-подтверждения ACK друг другу. (Конечно, поскольку ни один из межсетевых экранов не ожидает получения пакета подтверждения ACK, то есть необходимости в его уничтожении.) После того как две стороны будут удовлетворены процессом квитирования связи, будет установлена прекрасная двухсторонняя симметричная связь между двумя хостами, которые ранее не смогли переговорить друг с другом. Начиная с этого места брокеру нет необходимости что-либо делать. И действительно, как только две стороны (Алиса и Боб) обменяются несколькими первыми пакетами, брокер не сможет вторгнуться в сеанс, если даже он попробует это сделать (хотя, вероятно, он сможет послать фальсифицированное сообщение о недостижимости хоста по протоколу ICMP (ICMP Host Unreachable message) обеим сторонам, разрывая их связь).