В данной статье рассматривается, каким образом поток траффика, взятый из общей очереди пакетов, может быть использован как сторонний канал, через который нарушитель может получить конфиденциальную информацию.
В комментарии к исходному коду netfilter сказано:
«Наше подключение может не быть синхронизировано, поэтому игнорируйте пакеты, которые могут сигнализировать о настоящем подключении между клиентов и сервером» (игнорировать, в данном случае, не значить отбрасывать)
Проблема заключается в том, что netfilter и TCP стек Linux являются разными, несвязанными элементами. Netfilter не имеет доступа к состоянию TCP подключению, но может воссоздавать его на основе сегментов, рассмотренных ранее. В данном случае не подразумевается, что защищаемая конечная точка находится на той же машине, и что принятые ей сегменты достигли цели.
Необходимые шаги для определения SND.NXT значительно различаются для двух проведенных экспериментов. В обоих случаях используются ACK-сегменты и одноразовый порт, определенные на предыдущем шаге. При установленном соединении (корректные IP-адреса и порты) межсетевой экран Windows никогда не отбрасывает ACK-сегменты, поэтому при анализе ответов Windows необходимо принимать во внимание только правила, установленные документом RFC 793. NetFilter применяет более строгие правила фильтрации. В следующем подразделе демонстрируется, что более строгие правила фильтрации значительно уменьшают количество ресурсов, необходимых для атаки.
В первую очередь необходимо определить номер последовательности на узле сети жертвы. Если окно содержит номер последовательности следующего ACK-сегмента, и значение поля “номер подтверждения” принимается, то сегмент не вызывает никакого ответа. В противном случае, в ответ высылается ACK-сегмент. Согласно RFC 793, номер подтверждения принимается, если его значение равно или меньше не более чем на 231 номера следующего отсылаемого октета. Другими словами, принимаемое значение номера подтверждения лежит в промежутке [SND.NXT - 231; SND.NXT] (в терминах “арифметики последовательностей”). Поэтому одно из двух значений поля “номер подтверждения”, различающихся на 231, гарантировано будет приниматься. Нарушителю необходимо послать
запросов, чтобы найти номер последовательности, содержащийся в окне. Риск случайно внести в сессию искажения пренебрежимо мал. Сессия будет искажена, только если нарушитель подтвердит получение данных, потерянных при передаче. В этом случае данные повторно передаваться не будут.
Нарушителю не нужно в точности знать размер окна жертвы, хотя этот размер очень часто можно c легкостью определить (см. [11]). Сначала нарушитель может предположить, что размер окна максимальный (1 ГБ) и проверить номера последовательности, отличающиеся на 230. Если ни один из таких номеров последовательности в окне не содержится, то нарушитель может разбить предыдущий промежуток поиска пополам и проверить уже другие номера последовательности. Так если жертва использует окно размером 0.5 ГБ, то один из полученных номеров последовательности окажется внутри окна. Шаги можно повторять, каждый раз уменьшая размер окна в два раза, до тех пор, пока не будет найден номер последовательности, содержащийся внутри окна. Подобный поиск более подробно описан в [8].
Из N запросов необходимо выделить единственный, который не вызывает положительного ответа. Ситуация противоположна сканированию портов, где, наоборот, производится поиск запроса, вызывающего положительный ответ. В действительности, поиск отрицательного ответа более сложен. Это вызвано следующими возможными проблемами:
Из рис. 4 видно, как уменьшается время RTT, когда номер последовательности находится внутри окна. В таблице 2 показано, что даже в случае простоя, для полного сканирования требуется значительное время. В экспериментальное среде PoC коду потребовалось примерно 36 часов, чтобы провести сканирование при закачивании данных.
Зная номер последовательности внутри окна, нарушитель может найти SND.NXT узла сети жертвы. Для этого нужно найти минимальный номер последовательности, который не генерирует ответ. Значение SND.NXT не превосходит размера окна, меньше номера последовательности, и может быть найдено с помощью бинарного поиска за логарифмическое относительно размера окна число запросов.
Кроме того, если требуется найти значение SND.NXT жертвы, то теперь это можно легко сделать. Для наибольшего номера подтверждения, который не генерирует ответа (если принимается), необходимо сделать 31 запрос в бинарном поиске. Полученное число равно значению SND.NXT жертвы.
Благодаря этому можно найти подходящий номер подтверждения за 232/ max(66000, максимальный размер видимого окна отправителя) попыток. Если жертва отвечает на сегмент с неправильным номером последовательности, то это означает, что номер подтверждения был принят Netfilter’ом. Поиск подходящего номера подтверждения аналогичен поиску одноразового порта. Необходимо проверить по крайней мере 232/ 66000 = 65075 значений, и только одно из этих значений вызывает генерацию положительного ответа, поэтому также за один запрос можно проверять несколько значений. Для оценки необходимых ресурсов можно вновь обратиться к таблице 1.
Таблица 1. Поиск одноразового порта. Поиск осуществлялся на всем пространстве из 65К одноразовых портов.
Тип соединения |
Время сканирования |
Количество запросов |
Пинг |
Максимальное число проверенных портов за запрос |
Поддельные сегменты |
Отраженные сегменты |
бездействие |
35 |
592 |
2960 5 за запрос итого: 0,25 МБ среднее RTT: 22мс |
200 |
2202780 30 портов за запрос итого: 171 МБ |
330 25 КБ |
скачивание |
852 |
849 |
8490 10 за запрос итого: 0,7 МБ среднее RTT: 749мс |
100 |
73614000 1000 портов за запрос итого: 5741 МБ |
12000 0,9 МБ |
закачивание |
690 |
852 |
8520 10 за запрос итого: 0,7 МБ среднее RTT: 656мс |
100 |
74013000 1000 портов за запрос итого: 5773 МБ |
10000 0,8 МБ |
Таблица 2. Поиск номера последовательности, находящегося внутри окна, в случае строгого следования RFC 793. Размер окна: 65 КБ.
Тип соединения |
Время сканирования |
Количество запросов |
Пинг |
Поддельные сегменты |
Отраженные сегменты |
бездействие |
16860 ~5 ч. |
131338 |
394014 3 за запрос итого: 32 МБ среднее RTT: 85мс |
3940140 30 за запрос итого: 307 МБ |
3939930 |
Таблица 3. Поиск подходящего номера подтверждения. Нарушитель обманывает Netfilter, увеличивая окно отправителя до 8.3 МБ, это позволяет проверить всё возможное пространство номеров подтверждения за небольшое количество запросов.
Тип соединения |
Время сканирования |
Количество запросов |
Пинг |
Максимальное число проверенных номеров подтверждения за запрос |
Поддельные сегменты |
Отраженные сегменты |
бездействие |
3.4 |
60 |
300 5 за запрос итого: 24 КБ среднее RTT: 21мс |
25 |
20520 30 номеров подтверждения за запрос итого: 1.6 МБ |
240 18 КБ |
скачивание |
61 |
51 |
510 10 за запрос итого: 42 КБ среднее RTT: 866мс |
25 |
627000 1000 номеров подтверждения за запрос итого: 49 МБ |
4000 0,3 МБ |
закачивание |
59 |
56 |
560 10 за запрос итого: 45 КБ среднее RTT: 602мс |
25 |
728000 1000 номеров подтверждения за запрос итого: 57 МБ |
6000 0,5 МБ |
результаты сканирования номера последовательности (нормализация: 0 внутри окна)
(а) бездействие, 5 пинг на каждый номер последовательности, 30 поддельных сегментов на каждый номер последовательности
результаты сканирования номера последовательности (нормализация: 0 внутри окна)
(а) закачка, 10 пинг на каждый номер последовательности, 1000 поддельных сегментов на каждый номер последовательности
Рисунок 4. Измерено наименьшее среднее время RTT и количество потерь, в случае, когда поддельный сегмент находится внутри окна. Время RTT и количество потерь для других замеров достаточно велико и поэтому, длительность сканирования увеличивается. Естественные скачки трафика могут маскировать минимумы. Пинг считается потерянным, если ответ не получен по прошествии двух интервалов RTT с момента последнего пинга для того же номера последовательности.
Существует уловка, которая позволяет улучшить эффективность поиска. Netfilter можно легко обмануть, установив максимально возможный размер окна отправителя. Точное значение максимума определяется во время установки сессии. Для того чтобы обойти фильтр потребуется отослать 65075 ACK-пакетов, покрывающих все пространство в 232 номеров подтверждения, причем значения номеров будут отличаться на 66000. Для всех таких ACK-сегментов устанавливается максимально возможный размер окна: 0xFFFF. Один из ACK-сегментов должен приниматься Netfiltr’ом и устанавливать максимальный размер видимого окна в (заметим, что это не повлияет на реальный размер окна, протокол TCP в конечной точке отбросит ACK-сегмент, поскольку он содержит неправильный номер последовательности). Во время эксперимента, отправитель устанавливал размер окна равным 114, а коэффициент масштабирования равным 7, следовательно, размер видимого окна устанавливается в
. Последовательная отправка поддельных ACK-сегментов обманывает Netfilter и увеличивает размер видимого окна до
. С помощью окна такого размера можно покрыть все пространство в 232 номеров подтверждения, задействовав всего 512 значений. Если бы целью атаки являлся хост, работающий строго по RFC 793, то нарушителю можно было бы обойтись без знания размера окна жертвы и масштабирующего множителя. Можно предположить, что размер окна максимальный (1 ГБ), и путем последовательного деления пополам найти номер подтверждения.
Сводная информация о необходимых для атаки ресурсах приведена в таблице 3.
Зная подходящий номер подтверждения, с помощью бинарного поиска легко находится номер последовательности следующего октета, отсылаемого жертвой. Для этого необходимо log(max(66000, максимальный размер видимого окна отправителя)) запросов.
У нарушителя есть несколько способов узнать значение SND.NXT сетевого узла жертвы:
Метод также подходит для обнаружения номера одноразового порта хоста, который не отфильтровывает сегменты, принадлежащие несуществующему соединению, а вместо этого отвечает RST-сегментом на каждый такой сегмент. Последовательность поддельных сегментов, направленная на некорректный номер порта вызывает генерацию последовательности RST-сегментов, отбрасываемых на другом конце соединения без каких-либо дополнительных действий. Последовательность поддельных сегментов, направленная на корректный номер порта вызывает генерацию последовательности ACK-сегментов, которая, в свою очередь, вынуждает другую сторону выслать полное окно данных. Если нарушитель заметит скачок трафика, причиной которого служит отправка полного окна данных, то он также сможет определить порт.
На практике такой метод не проверялся.
Если аутентификация основывается на номерах последовательности, то иногда бывает сложно убедиться в том, что протокол никогда не отвечает на отброшенные сегменты. Номера последовательности предназначены для решения двух задач. В первую очередь они нужны для обнаружения дубликатов, потерянных и поврежденных сегментов. Но в дополнение к этому номера последовательности стали выступать в качестве защитного механизма от атаки, и такая функция не упоминается даже в исходной документации. Если Netfilter отфильтрует SYN-ACK сегменты, направленные на установленное соединение, и отбросит ACK-сегменты c некорректными номерами последовательности, то атака на систему, защищенную Netfilter’ом, вероятнее всего, окажется неудачной. Но составлять более строгие правила фильтрации нужно с особой аккуратностью, так как в противном случае иногда такие правила могут привести к зависанию соединения.
Выборочный пропуск ответов на отброшенные сегменты не должен делать утечку информации возможной на практике. Метод выборочного пропуска ответов для ACK-сегментов, генерируемых в ответ на RST и SYN-ACK сегменты, находящихся внутри окна, был предложен в работе [3]. Этот механизм эффективен только тогда, когда ACK-сегменты будут выборочно пропускаться в ответ и на другие отброшенные сегменты.
Атака упрощается, если нарушитель находится по ту же сторону от пограничного маршрутизатора, что и жертва. Расстояние в несколько близлежащих хопов также идеально подходит для фильтрации подмененных IP пакетов. Сеть, сконфигурированная отбрасывать подобный трафик, защищена, по крайней мере, от внутренней атаки.
Политика постановки в очередь, позволяющая изолировать трафик, идущий от различных пользователей, также может усложнить реализацию атаки. В работе [15] изучается политика диспетчеризации и защиты конфиденциальности. Авторам удалось значительно снизить влияние видов трафика различных пользователей в очереди друг на друга, не налагая дополнительных ограничений на производительность. Разработанная политика снижает утечки информации в зависимости от конкретного вида трафика, но поток трафика по-прежнему остается высоким из-за увеличения времени обработки пакета. Для реализации атаки, описанной в настоящей статье достаточно обнаружить увеличение потока трафика, когда как знать конкретный вид трафика необязательно. В дальнейших исследованиях необходимо оценить влияние различных политик постановки в очередь на эффективность атаки.
Автор не ставит перед собой цель определить в работе практические ограничения для атаки. Осталось еще множество проблем для дальнейшего исследования, например в контексте ситуаций более неблагоприятных для нарушителя (низкая полоса пропускания между нарушителем и жертвой, постоянно загруженное “бутылочное горлышко”, разделяемое несколькими пользователями, различные политики постановки в очередь). Проведенные эксперименты могут послужить в качестве отправной точки для дальнейших исследований. В работе также не делается попыток провести детальное изучение эффективности атаки по отношению к распространенным реализациям протокола TCP. И наконец, работа в центр внимания ставит компрометацию TCP сессий, хотя предложенная атака может быть использована и для других случаев.