tcpdump: відсіювання HTTP GET

  • 2012-02-06
  • (автор: dor)

Уявимо себе адміністратором сервера, що перебуває під атакою--відплатою за EX.ua (одразу зауважу, що я не є таким адміністратором, у мене просто гарна уява).

У першу чергу, нам було би цікаво, що саме летить на нас, що саме «валить» наш сайт «із ніг».

Щоб довідатися, є різні способи — скажімо, дивитися журнал веб-сервера, дивитися трафік на сервері утилітою tcpdump чи подібною; можна на проміжному комутаторі відгалужувати трафік і дивитися його tcpdump’ом десь на іншому комп’ютері... Але, так чи інакше, завжди цікаво знайти найбільш універсальний інструмент.

На мій погляд, найбільш універсальним інструментом є саме tcpdump.

Одразу зауважу, що ми можемо «попрохати» tcpdump писати трафік у файл, кожні N секунд закривати файл і починати новий, а на щойно закритому виконувати певну дію (запускати скрипт) — таким чином ми можемо не лише збирати, а й у режимі «майже реального» часу аналізувати інформацію і виконувати певні дії. Це все вміє сам tcpdump, ми маємо лише все продумати і написати скрипти .)

Наприклад, може бути зручним використання утиліти fail2ban; але цей скрипт працює на одному ядрі і на гарно навантаженому сервері (яким, імовірно, є кожен сервер під атакою) почувається невпевнено. Але ми можемо суттєво полегшити йому життя, якщо не змушуватимемо читати журнал веб-сервера, а «згодовуватимемо» вже добре проаналізовану інформацію. Наприклад, із зібраної tcpdump’ом інформації відбирати адреси, з яких надходить більше X [кіло]запитів за одиницю часу.

Отже, tcpdump виглядить («має вигляд» — «виглядить», а не «виглядає»!) досить зручним інструментом. Тож спробуємо з його допомогою ловити лише HTTP GET пакети.

А тепер зазирнемо у нутрощі пакетів. Для початку розберемося із прикладом, яким бачимо у man tcpdump:

To print all IPv4 HTTP packets to and from port 80, i.e. print only packets that contain data, not, for example, SYN and FIN packets and ACK-only packets...

tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

Щоб розібратися у цьому, нам, імовірно, треба буде поглядати на структуру пакета IP та структуру пакета TCP.

Отже, почнемо з початку.

ip[2:2] — два байти, 3-4-й -- довжина пакета.

ip[0] — один байт, версія + довжина заголовка у 4-байтних папугах.

(ip[0]&0xf)<<2 — ігноруємо версію, беремо довжину заголовка у 4 байтних папугах, множимо на 4 --- отримуємо довжину заголовка у байтах.

Тобто, (ip[2:2] - ((ip[0]&0xf)<<2)) — розмір пакета мінус розмір заголовка --- розмір поля даних пакета IP (тобто, розмір того, що вкладено у пакет IP, --- заголовок пакета TCP плюс, можливо, дані).

Далі колупаємося із TCP.

Тринадцятий байт заголовка TCP — tcp[12] --- у перших чотирьох бітах містить розмір заголовка TCP у 4-байтних папугах.

(tcp[12]&0xf0)>>2 — беремо байт, ігноруємо молодші 4 біти, зсуваємо --- тобто, ділимо на 4, отримуємо розмір заголовка TCP у байтах. Чому ділимо і чому саме на 4? Тому що ми взяли число із старших бітів. Тобто, фактично, треба було зсунути вправо на 4 біти (>>4 --- поділити на 16) і помножити на 4 --- бо у 4-байтних папугах --- (<<2), а це те саме, що >>2.

Отже, ((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) — це розмір пакета мінус розмір заголовка IP мінус розмір заголовка TCP. Результат має бути не нульовий, бо нас цікавлять пакети, що містять дані.

Із цим прикладом все зрозуміло.

Але нас цікавлять HTTP GET пакети.

Щойно ми з’ясували, що (tcp[12]&0xf0)>>2 — розмір заголовка TCP у байтах. Це поле також називається Data Offset --- це, зрозуміло, одночасно зміщення («адреса») першого байту поля даних.

Отже tcp[ ( (tcp[12]&0xf0)>>2 ) ] — перший байт поля даних, а tcp[ ( (tcp[12]&0xf0)>>2 ) : 4 ] --- перші 4 байти поля даних (пробіли вставив для читабельності; проте, вони не заважають і при виконанні команди).

Отже, для відловлювання HTTP GET ми будемо використовувати, скажімо, таку команду: > >

tcpdump -ttttqnc 200  -Ai IFACE -s 1500  'dst host HOST and tcp port 80 and (tcp[((tcp[12]&0xf0)>>2):4] == 0x47455420)'

Тут 0x47455420 — якраз і є HTTP GET; точніше, це рядок «GET ». Ми взяли чотири байти (:4); можемо брати 1, 2 чи 4.

Така команда дає нам на екран 200 пакетів (так, у реальній ситуації нас би цікавив вивід у файл і ротація файлів, а також обробляння файлів різними скриптами; але ми вже, здається, досягли мети цієї публікації); нижче кілька таких пакетів. Як я й казав, «організатори» подібних атак — великі свині: вони не попереджують користувача, що «вирахувати» його буде простіше простого (нижче я «замаскував» IP адреси «хакерів» та назву сайту --- адміністратором якого я не є,).

2012-02-06 11:31:25.566267 IP X1.60881 > Y.80: tcp 750
E...	v..|.}.......J....P..9.....P...'...GET /?id=1328520686735&msg=ex.ua HTTP/1.1
Host: SITE
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://pastehtml.com/view/bmp0uzp8a.html
Cookie: __utma=246119045.1297742463.1328024224.1328220961.1328347611.4; __utmz=246119045.1328347611.4.4.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=%D1%82%D1%83%D1%82%20%D0%B1%D1%83%D0%BB%D0%B0%20%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0%20%D1%81%D0%B0%D0%B9%D1%82%D1%83%2C%20%D0%B0%D0%BB%D0%B5%20dor%20%D1%97%D1%97%20%D0%B7%D0%B0%D1%84%D0%B5%D0%B9%D0%BA%D0%B0%D0%B2

2012-02-06 11:31:25.726106 IP X3.1177 > Y.80: tcp 671
E.....@.x....XH...J....P....vD.$...]3......
..aZ.f.uGET /?id=1328520684410&msg=%D0%9F%D0%9D%D0%A5 HTTP/1.1
Host: SITE
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://pastehtml.com/view/bmp0uzp8a.html
Cookie: __utma=246119045.536187851.1328266246.1328266246.1328298238.2; __utmz=246119045.1328266246.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=%D1%82%D1%83%D1%82%20%D0%B1%D1%83%D0%BB%D0%B0%20%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0%20%D1%81%D0%B0%D0%B9%D1%82%D1%83%2C%20%D0%B0%D0%BB%D0%B5%20dor%20%D1%97%D1%97%20%D0%B7%D0%B0%D1%84%D0%B5%D0%B9%D0%BA%D0%B0%D0%B2

2012-02-06 11:31:26.179446 IP X4.32613 > Y.80: tcp 361
E...BB@.|...^JU...J..e.P...;WI..P.?\U...GET /?id=1328520719743&msg=ex.ua HTTP/1.1
Host: SITE
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://pastehtml.com/view/bmp0uzp8a.html

2012-02-06 11:31:26.545684 IP X5.60881 > Y.80: tcp 750
E.......|.n.......J....P..;.....P...%"..GET /?id=1328520687714&msg=ex.ua HTTP/1.1
Host: SITE
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://pastehtml.com/view/bmp0uzp8a.html
Cookie: __utma=246119045.1297742463.1328024224.1328220961.1328347611.4; __utmz=246119045.1328347611.4.4.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=%D1%82%D1%83%D1%82%20%D0%B1%D1%83%D0%BB%D0%B0%20%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0%20%D1%81%D0%B0%D0%B9%D1%82%D1%83%2C%20%D0%B0%D0%BB%D0%B5%20dor%20%D1%97%D1%97%20%D0%B7%D0%B0%D1%84%D0%B5%D0%B9%D0%BA%D0%B0%D0%B2

Наостанок зауважу, що не всі «хакери» стріляли із JS LOIC, але зазвичай у таких випадках інші нечисельні напади також можна «вирахувати» чи завдяки певним шаблонам, чи по перевищенню кількості запитів на секунду певної межі. Саме у таких випадках. Випадки серйозніші й болісніші розглянемо якось у наступній серії.