Формат фильтра Фильтра BPF состоит из одного или нескольких примитивов. В свою очередь каждый примитив состоит из одного или нескольких спецификаторов и значения. Существует три типа спецификаторов (указаны в порядке применения):протокол, направление и тип. Спецификатор протокола может принимать значения ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp и udp. Если спецификатор протокола пропущен, то под фильтр попадают все протоколы соответствующие спецификатору типа. Спецификатор направления указывает движения трафика относительно значения. Допустимые значения src, dst, src or dst, src and dst, addr1, addr2, addr3 и addr4. Для некоторых протоколов, например SLIP, могут использоваться ключевые слова inbound и outbound. В случае если спецификатор не указан, то по умолчанию считается src or dst, то есть трафик в обоих направлениях. Спецификатор типа указывает на, то как надо интерпретировать значение. Допустимые типы host, net , port и portrange. При этом идентификатор распознается как адрес хоста, сети, номер порта или диапазон портов соответственно. По умолчанию используется тип host. Примитивы логически комбинируются с помощью and, or и not. С целью экономии места на экране и если объединяемые примитивы используют одинаковые спецификаторы, то они могут быть объединены. Например запись `tcp dst port ftp or ftp-data or domain' эквивалентна `tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'. Кроме перечисленных также можно выделить спецификаторы не попадающие ни под один тип: gateway, less, greater. Спецификаторы less, greater относятся к размеру пакета. С их помощью можно пропускать только пакеты длинна которых меньше или больше заданного значения соответственно. Спецификатор gateway указывает на то, что необходимо пропускать только пакеты идущие через указанный шлюз, то есть межсетевой трафик. Его действие аналогично 'ether host ehost and not host host'. При его использовании необходимо чтобы указанное значение могло успешно разрешиться в IP-адрес, а он в свою очередь мог разрешиться в адрес канального уровня. Использование указанных примитивов позволяет определить общие параметры сетевого трафика. Например, могут быть созданы следующие фильтры: весь трафик от хоста VENUS: src VENUS весь ICMP трафик от хоста PLUTO: icmp src PLUTO Использование приведенных спецификаторов позволяет идентифицировать в фильтрах предопределенные поля протоколов, однако, с их помощью невозможно фильтровать пакеты по содержимому полей данных или по не определенным полям протоколов. Для решения этой проблемы используется следующая конструкция: proto [ expr : size ] В ней proto это один из следующих указателей ether, fddi, tr, wlan, ppp, slip, link, ip, arp, rarp, tcp, udp, icmp, ip6 или radio. С его помощью идентифицируется протокол в котором осуществляется сравнение данных. Сравнение данных производится по блокам байтов. Начало блока, относительно начала заголовка объявленного протокола, указывается числовым параметром expr (нумерация с 0), а его длинна — числовым параметром size. На выбранный таким образом блок данных может быть наложена маска, а также он может быть сравнен с определенным значением или над ним может быть выполнена арифметическая операция. Например: Определение длинны IP заголовка: ( ip[ 0 ] & 0x0f ) * 4 Определение длинны IP-датаграммы: ip[ 2 : 2 ] Сравнение порта получателя UDP ( альтернатива udp port): udp[ 2 : 2 ] = 33000 Приведенные правила и перечень ключевых слов не полные, однако достаточные для того чтобы написать большинство фильтров. Исчерпывающее руководство по фильтру BPF может быть получено из MAN pcap-filter (7). Полезные фильтры В этом разделе собраны фильтры которые могут оказаться для вас полезными. Внеся в них небольшие изменения или объединив несколько штук с помощью and или or, вы можете легко адаптировать их под свои задачи. Фильтры сгруппированы по протоколам. Фильтры IPv4 Общее описание протокола IPv4 дано, например в WiKi, а полное описание следует искать в RFC 798. Определение длинны заголовка IP В большинстве случаев приходится работать со стандартными протоколами транспортного уровня вроде TCP и UDP и нет необходимости определять длину заголовка IP. Однако если вам необходимо разобрать свой транспортный протокол или отфильтровать пакеты с опциями IP, то этот раздел для вас. Длинна заголовка IP как правило равна 5 четырехбайтным блокам (то есть 20 байтам, говоря нормальным языком). Однако, в отдельных случаях в заголовок могут включаться параметры, в результате чего, он увеличивается. По этому, для обращения к блоку данных IP необходимо динамически определять длину заголовка IP и нельзя использовать статическую конструкцию типа ip[ 20 ]. Поле длинны заголовка расположено в четырех младших битах первого октета заголовка. Для того, чтобы его идентифицировать необходимо использовать маску 0x0f. Длинна заголовка указывается в четырехбайтных блоках, по этому значение поля надо умножать на 4. Таким образом, фильтр получения длинны заголовка выглядит следующим образом: ( ip[ 0 ] & 0x0f ) * 4 Длинна поля данных IP: ip[ 2 : 2 ] - ( ip[ 0 ] & 0x0f ) * 4 Фильтрация фрагментированного трафика Как правило датаграммы IP не фрагментируются, и их размер регулируется с помощью DF-флага и ICMP-сообщений. Однако в некоторых случаях, по тем или иным причинам, трафик все же фрагментируется. Фрагментация обнаруживается по содержимому MF-флага и полю Смещение фрагмента (Fragment Offset). Их значения могут сочетаться следующим образом: MF = 1, Fragment Offset >= 0: первый и последующие фрагменты, исключая последний. MF = 0, Fragment Offset > 0: последний фрагмент. Таким образом для работы с фрагментированным трафиком могут использоваться следующие фильтры: Первый фрагмент большой IP-датаграммы: ip[ 6 ] & 0x20 = 0x20 and ip[ 6 : 2 ] & 0x1fff = 0 Весь фрагментированный трафик: ip[ 6 ] & 0x20 = 0x20 or ip[ 6 : 2 ] & 0x1fff > 0 Фильтрация по вложенному протоколу В IP-датаграммах могут передаваться различные протоколы. В открытых сетях их количество ограничено 256-ю наименованием, однако, без сохранения совместимости их может быть намного больше. Каждому протоколу присвоен уникальных номер, который передается в поле Протокол (Protocol). Известные номера протоколов могут быть получены здесь. Для фильтрации наиболее распространенных из них могут использоваться следующие фильтры: ICMP: ip[ 9 ] = 1 TCP: ip[ 9 ] = 6 UDP: ip[ 9 ] = 17 ESP: ip[ 9 ] =50 AH: ip[ 9 ] = 51 GRE: ip[ 9 ] = 47 EIGRP: ip[ 9 ] = 88 OSPF: ip[ 9 ] = 89 Фильтры TCP Общая информация о TCP может быть получена из WiKi, а более подробная из RFC 793. Определение длинны заголовка TCP Аналогично IP длинна заголовка TCP может меняться. В нее могут входить различные опции, и это в отличии от IP встречается не так редко. По этому определение смещения поля данных TCP является актуальной задачей. Длинна заголовка TCP расположена в поле Смещение данных (Data Offset). Аналогично IP оно представлено в количестве 32-х битных блоков, и в байтах может быть получено следующим фильтром: ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 Примечание. Операция типа «( X >> 4) * 4» эквивалентна «X >> 2», однако я любитель явных, хоть и более длинных, форм представления. Определение срочных данных TCP Кроме обычных данных, которые передаются по мере их поступления в буфер, TCP также позволяет передавать срочные данные. Они не ставятся в буфер передачи, а передаются вне очереди «смешиваясь» с обычными данными. Типичное применение срочных данных это сигнализация или PING на уровне приложения. Однако, насколько мне известно, эта возможность TCP используется редко. О наличии в пакете срочных данных сигнализирует URG-флаг, они размещаются в начале области данных TCP, а их длинна (и соответственно смещение обычных данных) определяется соответствующим полем Urgent Pointer. Таким образом, для работы со срочными данными могут использоваться фильтры: Проверка наличия срочных данных (URG-флаг) tcp[ tcpflags ] & tcp-urg = tcp-urg Длинна срочных данных tcp[ 18 : 2 ] Начало данных tcp[ ( ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 ) + tcp[ 18 : 2] ] Примечание. Фильтры срочных данных не проверенны в работе. Если вы готовы выполнить их проверку, то просьба сообщить о результатах по адресу указанному в контактах. Фильтры данных TCP Располагая фильтрами определенными ранее, а также минимальными знаниями о прикладных протоколах можно осуществлять более точную фильтрацию необходимых вам данных. Определение не защищенного SMTP обмена Не зашифрованные SMTP сообщения начинаются с текстовой строки «MAIL», которая в ASCII коде будет выглядеть как «0x4d41494c». Таким образом, для идентификации таких потоков может быть использован фильтр: port 25 and tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 : 4 ] = 0x4d41494c HTTP потоки HTTP запросы начинаются с ключевого слова GET или POST. Таким образом фильтр для их идентификации выглядит следующим образом: port 80 and ( tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 : 4 ] = 0x47455420 or tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 : 4 ] = 0x504F5354 ) Каналы управления SSH Каналы SSH шифруются с помощью SSL. Однако при подключении клиентов сервер выдает строку в открытом тексте типа «SSH-1.99-Cisco-1.25». Как видно, в ней указывается собственно тип сервиса SSH, а тек же его версия. Для идентификации SSH могут использоваться фильтры: Определение сервера SSH, по строке «SSH-» tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 :4 ] = 0x5353482D Определение сервера SSH заданной версии, конкретно «1»: ( tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 :4 ] = 0x5353482D ) and ( tcp[ ( (tcp[ 12 ] & 0xF0) >> 4 ) * 4 + 4 ] = 0x31 ) Поиск скрытых каналов передачи данных Если вы уберете из предложенных фильтров SMTP, HTTP примитив port, то фильтры будут срабатывать на указанные строки в любых потоках TCP. В случае если вы замените port на not port, то могут быть обнаружены указанные приложения используемые на нестандартных портах (скрытые каналы передачи данных). Хотя конечно, такой подход может вызывать и ложные срабатывания.
Источник: http://sec7x24.net/arts/002_use_bpf.html |