Глибоке занурення в TCP, розбираємось із SYN-flood атаками

8 березня 2024 1 хвилина Автор: Cyber Witcher

Ми розглянемо будову протоколу TCP, зосередимо увагу на найбільш розповсюдженій атаці проти нього – SYN-flood а також вивчимо методи протидії цій загрозі. Також ми детально проаналізуємо ключові аспекти протоколу TCP, що роблять його вразливим до SYN-flood атак, і обговоримо, як ці особливості впливають на загальну безпеку мережі.

  • Дисклеймер: Ця стаття створена з ознайомлювальною метою. У ній розглядається принцип роботи TCP та механізм SYN-flood атак, щоб показати, як вони впливають на мережі, і допомогти читачам зрозуміти способи захисту від таких загроз.

Частина 1. Що таке TCP і навіщо він потрібний?

TCP розшифровується як Transmission Control Protocol  – протокол контролю передачі. Як зрозуміло з назви, він використовується для того, щоб контролювати дані, що передаються по мережі: попереджати і виправляти різні казуси, які можуть виникнути при передачі даних по мережі.

Але що ж такого може статися під час відправлення пакетів по мережі?

1. Порушення порядку прямування пакетів

Дані, які ми надсилаємо, розбиваються на пакети і маршрутизуються за допомогою протоколів динамічної маршрутизації, але може статися так, що частина пакета йде швидшим маршрутом, а інша відправляється маршрутом з меншою пропускною здатністю і прибуває пізніше. Наприклад, припустимо, що нам потрібно відправити чотири пакети на вузол мережі послідовно: a, b, c і d. Ми очікуємо, що вузол мережі отримає їх у тій самій послідовності, в якій вони були відправлені, але з огляду на вищесказане, цілком можливо, що одержувач отримає послідовність ACBD або, наприклад, DACB. Тому TCP повинен якимось чином відновити початкову послідовність отриманих пакетів.

2. Втрата пакетів

Через помилку маршрутизації або погано конфігуровану мережу наші пакети можуть передаватися дуже повільним шляхом, або потрапити в петлю, в якій вони будуть блукати, поки не вичерпають свій запас хопів і не знищаться. У такому випадку TCP повинен мати можливість вимагати втрачені або занурені в пакетній пробці дані.

Якщо ми спілкуємося з кимось аудіо або відеозв’язку, то такі результати нас мало хвилюють, але якщо ми завантажуємо, наприклад, iso-образ якоїсь ОС, то подібні ситуації ми повинні повністю виключити.

Також TCP (як і інші протоколи транспортного рівня) використовується для того, щоб перенаправляти дані з одного порту на інший порт, тобто від одного прикладного процесу до іншого.

TCP-сегменти

Робота TCP із сегментами

Для передачі даних мережею TCP отримує дані від протоколу прикладного рівня, буферизує їх і, коли готовий передати нову порцію даних, “відокремлює” потрібну частину байта, незалежно від її значення або внутрішньої структури. Кожна така частина називається сегментом TCP; важливо зазначити, що TCP розглядає дані як неструктурований потік байтів. Цим він відрізняється від протоколу UDP, який створює дейтаграми на основі логічно відокремлених блоків даних (повідомлень, згенерованих додатком). На приймальному боці модуль TCP буферизує пакет, отримує його і передає протоколу прикладного рівня.

Зазначимо, що сегментом називають як одиницю даних в цілому (поле даних і заголовок протоколу TCP), так і окремо поле даних.

Заголовок TCP-сегменту

Структура TCP-сегменту

У наступному викладі нам знадобиться знання полів заголовка, тому викладемо їх короткі описи, до яких читач може повернутися будь-якої миті:

  • Source Port та Destination Port (16 біт кожен) – порт відправника та одержувача відповідно.

  • Sequence number (32 біта) – номер першого байта в сегменті, що вказує на його зміщення щодо всього потоку байт.

  • Acknowledgment number (32 біта) – номер останнього байта, отриманого у сегменті, збільшеного на одиницю.

  • Data Offset (4 біта) – вказує на довжину заголовка (зміщення даних від початку сегмента)

  • Reserved (3 біти) – зарезервовані біти, які можуть бути використані надалі.

  • Flags (9 біт) – прапори, які вказують те, яку інформацію у собі несе сегмент.

  • Window (16 біт) – розмір вікна, що показує скільки байт даних одержувач готовий прийняти.

  • Checksum (16 біт) – контрольна сума. Деяке значення, розраховане за набором даних шляхом застосування хеш-функції та використовується для перевірки цілісності даних.

  • Urgent Pointer (16 біт) – порядковий номер байта, яким закінчуються важливі дані (береться до уваги лише за встановленого прапора URG)

  • Options (12 біт) – опції, які містять параметри з’єднання.

  • Padding – фіктивне поле змінної довжини, використовуване доведення розміру заголовка до 32-бітних машинних слів.

  • Data – поле змінної довжини, в якому безпосередньо містяться дані, що передаються.

Встановлення TCP-з’єднання

Встановлення TCP-з’єднання

Перш ніж розпочнеться передача даних, відправник і одержувач повинні встановити з’єднання, через яке буде відбуватися передача даних. Під час встановлення з’єднання відправник і одержувач обмінюються параметрами з’єднання, вказуючи номер ACK, розмір вікна, тип підтвердження і т.д. (всі ці параметри обговорюються нижче). Все це відбувається в три етапи:

  1. Відправник посилає на сервер TCP-сегмент зі своїми параметрами, встановлюючи прапорець SYN (від англ. synchronization ) і переходить у стан SYN-SENT .

  2. Сервер, отримавши SYN-прапор починає готувати інфраструктуру підтримки з’єднання, запитуючи в ОС різні ресурси (лічильники, таймери, буфера тощо.) Після відправляє TCP-сегмент зі своїми параметрами і прапорами SYN і ACK (від англ. acknowledgement ) , переходячи в стан SYN-RECEIVED .

  3. Відправник, отримавши від сервера SYN-ACK-сегмент, надсилає йому сегмент з прапором ACK і переходить у стан ESTABLISHED . Сервер, отримавши даний сегмент, також переходить у цей стан, і починається надсилання даних.

Методи квитування

Щоб вирішити проблеми, пов’язані з TCP, було вирішено використовувати підтвердження пакетів. Відправник надсилає дані, а одержувач підтверджує їх отримання за допомогою підтвердження. Якщо відправник не отримав підтвердження вчасно, він надсилає дані повторно; TCP реалізує два методи підтвердження пакетів, використовуючи концепцію ковзного вікна.

Концепція ковзного вікна

Ковзне вікно

Відправник має серію пронумерованих пакетів, для яких визначено вікно певного розміру, щоб контролювати процес передачі пакетів. Перший пакет, що потрапляє у вікно, називається базовим. Все, що знаходиться зліва від нього, вважається переданим. Пакети, що знаходяться в межах вікна, дозволяється передавати. Пакети, які виходять за правий край вікна, не можуть бути передані. При отриманні базового пакету вікно зсувається вліво на один пакет. Коли вікно передачі вичерпується, відправник припиняє передачу і чекає на отримання. Одержувач також може мати вікно, яке обмежує кількість пакетів, що можуть бути прийняті.

На наступному малюнку представлений ідеалізований приклад, який показує роботу вікна, що ковзає, на стороні відправника.

Ідеалізований приклад “ковзання” вікна

Для чого взагалі потрібне вікно? Чому не передавати всі пакети разом?

Припустимо, ви вирішили завантажити GTA San Andreas, яка важить 1,4 ГБ, на свій смартфон. За відсутності розсувного вікна всі 1,4 ГБ будуть відправлені з серверів Google на TCP-модуль вашого смартфона.

По-перше, зрозуміло, що якби всі дотримувалися цієї концепції, весь інтернет був би заполонений величезною кількістю TCP-сегментів, що в рази зменшило б пропускну здатність каналу зв’язку.

По-друге, в цьому випадку смартфону довелося б виділяти буфер необмеженого розміру (оскільки він не знав би заздалегідь, скільки даних отримає); оскільки розмір буфера, що виділяється операційною системою, обмежений, в цьому випадку сегменти, що не увійшли в буфер, будуть відкидатися. Сервер помилково вважатиме, що з пакетом щось сталося, і повторно передасть його, в результаті чого пакети знову і знову бомбардуватимуться смартфонами, які ще не обробили отриманий сегмент.

Тепер, коли ми познайомилися зі ковзним вікном, перейдемо до розгляду методів квитування, на ньому заснованих.

Повернення N пакетів (Go-Back-N)

Для початку розглянемо алгоритм роботи із сегментами на стороні-одержувачі. При надходженні нового пакета одержувач перевіряє дві речі:

  1. Чи є пакет неспотвореним

  2. Чи є він наступним по порядку у послідовності вже отриманих пакетів

Якщо обидва ці кроки виконано, отримувач надсилає квитанцію з номером останнього надісланого пакета. Варто зазначити, що квитанції в цьому методі передачі є кумулятивними. Це означає, що якщо відправник отримує квитанцію з номером n-го пакета, це означає, що всі попередні пакети також були отримані. Це пов’язано з тим, що приймач буде приймати неспотворені пакети, якщо вони не вийшли з ладу (можна сказати, що приймач має однопакетне вікно).

Тепер давайте подивимося на алгоритм з боку відправника. Відправник надсилає пакети, які не виходять за межі вікна, і встановлює таймер зі значенням таймауту, що дорівнює максимальному часу очікування прийому базового пакета. Після закінчення тайм-ауту відправник вважає, що пакет або підтвердження було втрачено, і повторно передає цей пакет і всі інші надіслані пакети.

Може статися так, що базовий пакет і деякі наступні пакети були успішно отримані, але їх було втрачено. У цьому випадку приймач повторно передає деякі пакети. Коли приймач бачить дублювання, він розуміє, що відбувається, і відправляє останній отриманий пакет (пам’ятаючи про накопичення). Цей метод менш ресурсоємний, ніж наступний, але має очевидні недоліки. Оскільки одержувач може відкинути весь пакет просто тому, що він несправний, відправник змушений надсилати пакети щоразу після закінчення таймауту, заповнюючи канал зв’язку зайвими пакетами.

Вибіркове квитування (Selective acknowledgement)

Вибіркове підтвердження, як випливає з назви, дозволяє одержувачу надсилати підтвердження для певного пакета. У цьому випадку отримані пакети потрібно десь зберігати. Це пов’язано з тим, що отримані пакети не можуть бути негайно відправлені до протоколу вищого рівня, оскільки пакети можуть надходити в невпорядкованому порядку або між пакетами можуть бути проміжки. Тому на приймальній стороні також організовується ковзне вікно. Залежно від помилок, які виникають під час передачі пакетів і підтверджень, вікно прийому може передувати вікну передачі.

Вікна передачі та прикладу при вибірковому квитуванні

Одержувач у разі вже не відкидає пакети лише оскільки вони вибиваються з послідовності. Змусити відкинути пакет одержувача може його спотворення, або за межі вікна.

Сторона-відправник у разі організує таймер як на базовий пакет, але в всі відправлені пакети і після закінчення тайм-аута для конкретного пакета відправляє його знову.

Можлива і ситуація, в якій пакет благополучно було прийнято, але квитанція на нього загубилася. Тоді до отримувача прийде дублікат пакету. Одержувач не повинен його ігнорувати – йому слід підтвердити квитанцією прийом дублікату.

Даний метод хоч і трохи ресурсозатратніший, ніж попередній, але дозволяє суттєво збільшити швидкість передачі та зменшити надмірну передачу пакетів. На даний момент більшість вузлів мережі, що працюють на транспортному рівні, використовують саме цей метод квітування пакетів.

Нумерація байтів

Для простоти, у прикладах, які ми бачили досі, пакети нумеруються натуральними числами, починаючи з 1, але насправді все набагато складніше: у протоколі TCP при встановленні з’єднання кожна сторона повідомляє свій початковий порядковий номер (поле порядкового номера), з якого він нумерується байтами. Процес продовжується. Номер кожного сегмента в цьому випадку дорівнює зміщенню першого байта сегмента відносно всього потоку байт + ISN.

Нумерація байтів

Розглянемо приклад. Припустимо, відправник обирає ISN 32600. Номер першого сегмента, природно, дорівнює 32600. Це тому, що зміщення початкового байта першого сегмента дорівнює нулю. Зсув початкового номера від початку потоку байт дорівнює 1460, тому номер другого сегмента буде 34060; зверніть увагу, що 32600 плюс 1460 – це не кінцева кількість байт першого сегмента, а початкова кількість байт другого сегмента. Це те саме, що і для масивів.

Нумерація сегментів

Також варто зазначити, що для квитування використовується поле Acknowledgment Number, в якому вказується номер останнього байта, збільшеного на одиницю.

Для кращого розуміння роботи протоколу читачеві рекомендується самостійно просніффить трафік і подивитися, як відбувається процес рукостискання та обміну інформацією.

Частина 2. Атака SYN-flood

Суть атаки

Syn-flood атака – це один з різновидів DoS-атак. Принцип наступний: зловмисник посилає величезну кількість запитів встановлення з’єднання на сервер, що атакується. Сервер, бачачи сегменти з прапором SYN, виділяє необхідні ресурси підтримки з’єднання і відправляє у відповідь сегменти з прапорами SYN і ACK, переходячи у стан SYN-RECEIVED (такий стан ще називають напіввідкритим з’єднанням). Зловмисник, не шле відповідні ACK сегменти, а продовжує бомбардувати сервер SYN-запитами, тим самим змушуючи сервер створювати все більше і більше напіввідкритих з’єднань. Сервер, зрозуміло, має обмеженими ресурсами, і тому має ліміт на кількість напіввідкритих з’єднань. Зважаючи на цю обмеженість, при досягненні граничного числа напіввідкритих з’єднань сервер починає відхиляти нові спроби з’єднання; таким чином і досягається відмова в обслуговуванні (Denial of Service).

Принцип SYN-flood атаки

Реалізація атаки

Для проведення атаки нами буде використано дві віртуальні машини. В якості жертви виступатиме LMDE 6, а як зловмисник Kali 6.1.

Для початку встановимо ліміт на кількість напіввідкритих з’єднань на машині жертви 5 (за замовчуванням 1024). Для цього потрібно скористатися утилітою sysctl, яка дозволяє вносити зміни в ядро, що працює.

Завдання максимальної кількості з’єднань

IP-адреса жертви – 192.168.31.175.

IP-адреса жертви

Для проведення атаки скористаємося утилітою hping3, яка встановлена ​​в дистрибутиві Kali. У цьому випадку ми надіслали 15 пакетів на 23 порт (telnet) з увімкненим прапором SYN, використовуючи спуфінг IP-адрес.

Проведення атаки

Після проведення атаки подивимося інформацію з відкритих сокетів жертви за допомогою утиліти ss; -a показує всі сокети, -t – TCP-сокети, -o – інформацію про таймери.

Стан сокетів жертви

Як ми бачимо, наша машина підтримує лише 5 сокетів у напіввідкритому стані, хоча ми надіслали 15 запитів на з’єднання. Якби серед них був законний користувач, то він би отримав відмову в обслуговуванні, чого ми і домагалися.

Відмова в обслуговуванні з боку клієнта

Давайте вивчимо трафік, який був спійманий під час атаки.

Спійманий трафік

Як ми бачимо, нами дійсно було надіслано 15 SYN-запитів, але лише на 5 із них жертва відповіла. До речі, зверніть увагу на червоно-чорні рядки: наша машина повторно відправляє SYN,ACK відповіді, тому що думає, що вони були втрачені або спотворені.

Методи захисту від SYN-flood атак

Як же захищатись від SYN-flood атак? Тут є два підходи, які можна поєднувати між собою.

По-перше, можна збільшити кількість напіввідкритих TCP-з’єднань та зменшити час, в якому сокет може перебувати у стані SYN-RECEIVED .

По-друге, можна використовувати SYN-cookie.

Ідея SYN-файлу дуже проста: при отриманні SYN-запиту він не створює нове з’єднання, а надсилає клієнту відповідь SYN-ACK і кодує дані про це з’єднання в полі Sequence Number (Порядковий номер). Якщо від клієнта отримано відповідь ACK, дані про з’єднання відновлюються з поля Acknowledgment Number. Це хороший метод, оскільки він дозволяє уникнути виділення ресурсів одразу після отримання SYN-запиту. Однак він також має очевидні недоліки. Якщо пакет втрачено або спотворено, він не може бути переданий знову, оскільки інформація про з’єднання не зберігається.

Для того, щоб увімкнути SYN-cookie, потрібно скористатися утилітою sysctl і встановити значення параметра net.ipv4.tcp_syncookies 2. До цього даний параметр дорівнював нулю.

Установка SYN-cookie

Спробуємо провести атаку ще раз та засниффити трафік.

Трафік після включення SYN-cookie

Як ми бачимо, наша машина відповіла вже на всі запити, але повторного відправлення не було. Якщо ми подивимося на стан сокетів, то побачимо, що жодного напіввідкритого з’єднання не було створено.

Стан сокетів після включення SYN-cookie

У цій статті ми познайомилися з протоколом TCP, дізналися про атаку SYN-flood, навчилися її проводити, а також захищатись від неї. У цій статті розглядалася лише одна атака на протокол TCP, хоча насправді їх набагато більше.

Ось короткі описи кожної з них:

  • TCP reset. Атака, коли зловмисник відправляє TCP-сегмент з прапором RST одному з учасників з’єднання, що трактується модулем TCP, як аварійне закриття з’єднання.

  • TCP hijalking. Атака, при якій зловмисник вклинюється в з’єднання, маскуючи свої пакети під пакети законного користувача, тим самим поставляючи жертві власні дані.

  • Повторення сегментів TCP. Атака при якій зловмисник перехоплює весь трафік, що виходить із одного джерела, а потім, ініціюючи з’єднання, повторює їх знову.

Інші статті по темі
КібервійнаСоціальна інженерія
Читати далі
Атака на «водоймі», що це таке та як від неї захиститися?
У цій статті ви знайдете докладну інформацію про природу атаки на "водойму", методи її виконання та практичні поради з безпеки, які допоможуть вам убезпечити свій комп'ютер та дані від потенційних загроз.
958
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.