Как многие из читателей блога Qrator Labs, вероятно, уже знают, DDoS-атаки могут быть нацелены на разные уровни сети. В частности, наличие у злоумышленника крупного ботнета позволяет ему осуществлять атаки на уровень L7 (application/прикладной) и пытаться мимикрировать под нормального пользователя, в то время как без оного атакующий вынужден ограничиваться пакетными атаками (любыми, позволяющими подделывать адрес источника на том или ином этапе) на нижележащие уровни транзитных сетей.
Естественно, и для первой, и для второй задачи атакующие обычно стремятся использовать какой-то уже существующий инструментарий – ровно так же, как, например, разработчик веб-сайта не пишет его полностью с нуля, а использует распространённые фреймворки вроде Joomla и Bootstrap. Например, популярным фреймворком для организации атак с Интернета вещей уже полтора года является Mirai, чей исходный код был выложен в открытый доступ его авторами в попытке стряхнуть с хвоста ФБР еще в октябре 2016-го.
А для пакетных атак таким популярным фреймворком является встроенный в Linux модуль pktgen. Его туда встраивали не для этого, а для вполне легитимных целей сетевого тестирования и администрирования, однако, как писал Исаак Азимов, «атомный бластер — хорошее оружие, но он может стрелять в обе стороны».
Особенность pktgen в том, что он «из коробки» умеет генерировать только UDP-трафик. Для целей сетевого тестирования этого достаточно, а упрощать беспорядочную стрельбу в обе стороны разработчики ядра Linux особо не хотят. В итоге это (несколько) упрощало борьбу с DDoS-атаками, поскольку ряд злоумышленников хоть и прописывал правильные порты в pktgen, но не обращал внимание на получающиеся на выходе значения IP protocol, и заметная доля пакетных атак таргетировала TCP-сервисы (например HTTPS, использующий порт 443/TCP) UDP-датаграммами. Такой паразитный трафик раньше можно было легко и дёшево отбрасывать ещё на дальних подступах (на основе BGP Flowspec в том числе), и «последней мили» до атакуемого ресурса он бы не достигал никогда.
Но всё меняется, когда приходит Google.
Рассмотрим спецификацию разрабатываемого с 2013 года на замену TCP протокола QUIC. QUIC позволяет мультиплексировать несколько потоков данных между двумя компьютерами, работая поверх протокола UDP и содержит возможности шифрования, эквивалентные TLS и SSL. Имеет более низкую задержку соединения и передачи, чем TCP. Хорошо переносит потерю части пакетов путём выравнивания границ криптографических блоков по границам пакетов. В протокол заложена возможность коррекции ошибок (FEC) на уровне пакетов, но на практике она отключена. Ⓒ Википедия
Google за последние несколько лет разработал связку протоколов, предназначенную для замены старого стека протоколов World Wide Web. QUIC работает поверх всем известного транспортного протокола UDP, а в настоящий момент мы видим отдельные случаи интеграции QUIC в проекты индивидуальными «энтузиастами». Google Chrome, как и серверы приложений Google, уже поддерживают QUIC, так что энтузиазм объясним. По отзывам некоторых операторов связи протокол, впервые выпущенный в 2013 году, уже составляет большую долю в их трафике, чем внедряемый с 90-х годов IPv6.
Однако на данный момент все попытки реализации QUIC, в основном, являются user space-программами, а с точки зрения ядра, не говоря уже про все транзитные устройства и Flowspec, это (барабанная дробь) UDP на 443 порт.
С одной стороны, это в каком-то смысле иллюстрирует уязвимость подхода, когда пакетные атаки фильтруются на одном оборудовании, а атаки на вышележащие уровни – на другом (как правило, кумулятивно намного более слабом). Понятно, что строить такие решения дёшево и приятно, но они по сути фиксируют исторически сложившуюся ситуацию в World Wide Web, а понятие «исторически сложившейся ситуации» в отношении индустрии, которой всего лет 25, звучит несколько смешно. Представим, что завтра ситуация изменится – скажем, придёт бизнес и потребует внедрить новомодный протокол QUIC, потому что Google пообещал QUIC-enabled-сайты ранжировать в выдаче выше – этого пока не произошло, но вполне может произойти году в 2020-м. В результате такого внедрения, как в старом анекдоте про кремлёвского сантехника, всю систему потребуется менять.
В тюрьме сидят двое и разговаривают
— Ты по политической или по уголовной статье?
— По политической. Я сантехник. Вызвали в Кремль. Я осмотрел и сказал: «Тут всю систему менять надо!»
С другой стороны, конкретно протокол QUIC разработан достаточно разумно – он, в частности, по дизайну не позволяет, в отличие от многих других основанных на UDP протоколов типа DNS, amplification-атаки, то есть гарантированно не увеличивает трафик ответов на запросы от неподтверждённого источника, в результате наличия в спецификации рукопожатия (оно же handshake или «хендшейк»).
Основная задача рукопожатия — как можно проще и эффективнее убедиться, что запросы действительно приходят с того IP-адреса, который написан в поле источника IP-пакета. Это необходимо, чтобы не тратить ограниченные вычислительные мощности сервера и сети на общение с множеством поддельных клиентов. Вдобавок, это позволяет избавиться от использования сервера как промежуточного звена в amplification-атаке, когда сервер будет отправлять в адрес жертвы (поддельный в поле источника) значительно больше данных, чем потребуется сгенерировать злоумышленнику от имени жертвы.
Адам Лэнгли и компания могут выступать примером для всех, кто пытается создавать свои собственные UDP-based-протоколы (привет, игроделы!). В текущей версии черновика стандарта QUIC рукопожатию посвящён целый раздел. В частности, первый пакет QUIC-соединения не может быть меньше 1200 байт, поскольку именно такой размер может иметь ответ сервера на рукопожатие. QUIC-клиент вплоть до момента установления соединения (то есть до момента, когда подлинность IP-адреса клиента подтверждена) не может заставить сервер передать больше байт ответа или сгенерировать больше пакетов, чем передаёт сам клиент.
Естественно, механизм рукопожатия представляет собой очень удобную цель для злоумышленников. Знаменитая атака SYN flood, например, нацелена именно на механизм тройного рукопожатия в протоколе TCP. Поэтому важно, чтобы любое рукопожатие было спроектировано наиболее оптимальным образом и реализовывалось без значительной алгоритмической сложности, в идеале — как можно ближе к железу. В протоколе TCP, например, это изначально было не так — эффективный хендшейк (SYN cookies) был спроектирован значительно позже знаменитым Дэниелом Бернштайном и основывается, по сути, на «хаках», чтобы работать с этим механизмом могли даже устаревшие клиенты.
Смешно, но, как можно видеть из первой части поста, по факту протокол QUIC является целью злоумышленников ещё до своего полноценного релиза. Поэтому при внедрении QUIC в бой критично важно проследить, чтобы QUIC-хендшейк был реализован как можно более эффективно и близко к железу. В противном случае те атаки, с которыми раньше могло справиться ядро (а Linux поддерживает SYN cookies уже очень давно), придётся обрабатывать в каком-нибудь Nginx или, того гляди, IIS. Нужно ли говорить, что он с ними навряд ли справится.
С каждым годом сеть становится всё сложнее и сложнее. На этот вызов приходится отвечать всем, а в особенности инженерам, занимающимся разработкой и внедрением новых сетевых протоколов. В процессе такого внедрения следует в первую очередь учитывать вопросы безопасности и решать их заранее, не дожидаясь фактической реализации угрозы. Заметим, что эффективную поддержку того же QUIC на уровне, близком к «железу», еще необходимо обеспечить.
Защиту системы, проектируемой поверх протокола QUIC, осуществлять будет очень сложно до момента, пока все подобные вопросы не будут обнаружены, проанализированы и решены. Это же касается остальных новомодных вещей типа HTTP/2, DNS-over-TLS и даже IPv6.
В будущем мы увидим ещё большее количество интересных примеров атак на протоколы нового поколения. Непременно будем держать вас в курсе.