MITM-атака: как кто-то встаёт между тобой и сервером
Разбираю, как работает атака «человек посередине» на уровне протоколов: ARP-спуфинг, подмена DNS, SSL stripping. И что реально мешает злоумышленнику влезть в твой трафик.
Представь, что ты пишешь записку и просишь соседа по парте передать её другу на другом конце класса. Сосед может прочитать записку. Может подменить пару слов. Может вообще выкинуть твою и написать свою — а ты и не узнаешь, потому что ответ придёт обратно через того же соседа. Вот это и есть атака «человек посередине», или MITM (Man-in-the-Middle). Только вместо парты — сеть, а вместо соседа — тот, кто умеет встать на пути твоего трафика.
Звучит как что-то из шпионских фильмов, но на деле это одна из самых старых и до сих пор живых сетевых атак. Я долго относился к ней как к учебному примеру из курса по сетям — пока однажды не поймал себя на мысли, что подключаюсь к банку через вокзальный Wi-Fi без VPN. Тогда и захотелось разобраться, что именно тут может пойти не так.
Суть атаки
Нормальное соединение выглядит так: твой ноутбук говорит напрямую с сервером, и между ними никого нет.
ТЫ ──────────────────────────────► СЕРВЕР
◄──────────────────────────────
При MITM в эту линию незаметно вклинивается третий. Он принимает твои пакеты, читает их, при желании меняет — и пересылает дальше. То же самое в обратную сторону. Обе стороны уверены, что говорят напрямую друг с другом.
ТЫ ──────► ЗЛОУМЫШЛЕННИК ──────► СЕРВЕР
◄────── ◄──────
│
▼
читает и подменяет
Вся атака держится на одном: заставить твой трафик идти через чужую машину. И, что важно, злоумышленнику не нужно ломать шифрование. Он атакует доверие — те механизмы, по которым твой компьютер вообще решает, кому отправлять пакеты и кому верить. А доверия в сети, как выясняется, выдаётся авансом гораздо больше, чем стоило бы.
Удобно делить MITM на два этапа. Сначала встать на пути трафика — это про сеть. Потом уже разобраться с шифрованием — это про TLS. Дальше разберу оба.
Этап первый: встать на пути
ARP-спуфинг
Самый классический способ влезть в трафик внутри локальной сети — например, той самой публичной Wi-Fi-сети в кафе.
Внутри сети устройства находят друг друга не по IP, а по MAC-адресам — физическим адресам сетевых карт. Чтобы узнать, какой MAC соответствует нужному IP, компьютер кричит на всю сеть: «у кого IP 192.168.1.1 (это роутер), отзовитесь своим MAC?». Кто отозвался — тому и шлём. Этот механизм называется ARP.
Проблема в том, что ARP никого не проверяет. Любой ответ принимается на веру. Злоумышленник просто отвечает на чужие запросы: «IP роутера — это мой MAC». И заодно говорит роутеру обратное: «IP твоего ноутбука — тоже мой MAC». Теперь весь трафик между тобой и роутером идёт через машину атакующего.
КАК ДОЛЖНО БЫТЬ
ТЫ ──────► РОУТЕР ──────► ИНТЕРНЕТ
ПОСЛЕ ARP-СПУФИНГА
ТЫ ──────► АТАКУЮЩИЙ ──────► РОУТЕР ──────► ИНТЕРНЕТ
«я роутер» │
▼
весь трафик у него
Ничего сложного: ноутбук с нужным софтом и общая сеть с жертвой. Кафе, коворкинг, аэропорт — везде, где десятки незнакомых людей сидят в одном Wi-Fi.
Подмена DNS
DNS — это телефонная книга интернета. Ты вводишь mybank.ru, а DNS превращает имя в IP-адрес, к которому реально пойдёт соединение. Запросы эти исторически ходят открытым текстом и без подписи.
Если атакующий уже встал между тобой и роутером (см. ARP выше), он ловит твой DNS-запрос и отвечает раньше настоящего сервера: «mybank.ru — это вот такой IP» — и подсовывает адрес своей машины. Браузер честно идёт по этому адресу, открывает копию сайта банка, ты вводишь логин и пароль — и отдаёшь их прямо в руки.
Имя в адресной строке при этом правильное. Меняется то, что за ним стоит.
Поддельная точка доступа
Иногда даже спуфить ничего не надо. Достаточно поднять Wi-Fi-точку с названием вроде Free_Airport_WiFi и подождать. Телефоны вокруг сами цепляются к знакомым или к открытым сетям, и весь их трафик с самого начала идёт через тебя. Встраиваться ни во что не нужно — ты и так уже посередине.
Этап второй: что делать с HTTPS
Допустим, трафик жертвы пошёл через атакующего. Но сейчас почти всё ходит по HTTPS, и просто прочитать его не выйдет — он зашифрован. Тут и начинается интересное.
SSL stripping
Самый коварный приём, придуманный ещё в 2009 году Мокси Марлинспайком. Он бьёт не по шифрованию, а по моменту до него.
Смотри, как обычно происходит вход на сайт. Ты редко пишешь https:// руками — чаще просто mybank.ru или жмёшь старую ссылку. Браузер сначала стучится по http://, а сервер отвечает: «иди на https://». И только потом начинается защищённое соединение. Вот эта первая открытая секунда — дыра.
Атакующий перехватывает тот самый первый HTTP-запрос. С сервером он сам устанавливает честный HTTPS, а тебе отдаёт обычный HTTP. Для сервера всё выглядит нормально — он говорит с кем-то по HTTPS. А ты сидишь на HTTP и не видишь ни замочка, ни предупреждений. Просто страница без шифрования, на которую ты вводишь пароль открытым текстом.
ТЫ ──http──► АТАКУЮЩИЙ ──https──► СЕРВЕР
(открыто) (зашифровано)
Сервер думает: всё ок, HTTPS.
Ты думаешь: ну, сайт как сайт.
Пароль улетает открытым текстом.
Самое противное — тут нет ошибки сертификата, на которую можно среагировать. Замочка просто нет, а на его отсутствие почти никто не смотрит.
Поддельный сертификат
Второй путь — не понижать HTTPS, а попытаться его подделать. Атакующий подсовывает свой сертификат на mybank.ru. В норме браузер тут же поднимет тревогу: сертификат подписан не тем, кому доверяет система, — и покажет красный экран с предупреждением.
Этот барьер ломается, по сути, только в двух случаях. Либо у атакующего есть доступ к доверенному центру сертификации (редкость, но в истории такое случалось). Либо на устройство жертвы заранее подсунули «свой» корневой сертификат — так, кстати, легально работает корпоративная инспекция трафика, и так же действует часть зловредов.
Отсюда правило, в которое стоит въесться намертво: никогда не проматывай предупреждение браузера о сертификате. Это ровно тот момент, когда защита кричит, что её пытаются обойти.
Что реально защищает
Хорошая новость: за годы против MITM накопился крепкий набор контрмер. Плохая — работают они слоями, и ни один слой сам по себе не закрывает всё.
- HTTPS везде и без HTTP-версии. Пока есть хоть одна открытая страница, есть и щель для SSL stripping. Сайт должен говорить только по HTTPS.
- HSTS. Заголовок, которым сервер говорит браузеру: «ко мне ходи только по HTTPS, даже не пробуй HTTP». А если домен попал в встроенный в браузеры preload-список, то и самый первый запрос уже не уйдёт открытым. Это и есть прямое лекарство от SSL stripping.
- Проверка сертификата. Тот самый красный экран. Не игнорируй его. Для мобильных приложений идут дальше и применяют certificate pinning — приложение заранее знает, какой именно сертификат у его сервера, и любой другой отвергает, даже формально валидный.
- Защищённый DNS. DNS-over-HTTPS и DNS-over-TLS прячут и подписывают запросы, так что подменить ответ на лету уже не выйдет.
- VPN на чужом Wi-Fi. Самое простое для обычного человека. VPN заворачивает весь трафик в свой шифрованный туннель. Даже если кто-то сидит посередине в кафе, он видит лишь поток нечитаемых байтов до VPN-сервера, и ARP-спуфинг с подменой DNS об этот туннель разбиваются.
Если свести к одному совету для не-инженера: на любом публичном Wi-Fi включай VPN и никогда не кликай «всё равно продолжить» на предупреждениях о сертификате. Этого хватает, чтобы закрыть подавляющее большинство сценариев.
А разработчику — относиться к сети как к враждебной среде по умолчанию. Не «за фаерволом безопасно», а «между двумя моими сервисами вполне может кто-то сидеть». HTTPS внутри, HSTS снаружи, нормальная проверка сертификатов в каждом HTTP-клиенте. Скучно, зато работает.
Вся атака «человек посередине» держится на одном допущении — что трафик идёт туда, куда ты думаешь, и тому, кому ты думаешь. Защита, по сути, сводится к тому, чтобы это допущение перестало быть просто верой и стало проверяемым фактом.