За 2012 год SSRF-атаки превратились из чего-то экзотического во вполне реальную угрозу. Работы Александра Полякова, Владимира Воронцова и других исследователей в этой области составили практически полную картину различных механизмов проведения таких атак и возможных последствий. Тем не менее, поскольку разработка этой тематики началась сравнительно недавно, поле для исследований еще остается.
В этой статье будет рассмотрена небольшая особенность протокола FTP, благодаря которой уязвимость, позволяющей провести SSRF-атаку, можно использовать не только для получения информации или развития вектора атаки, но и для релеинга атак типа DoS как на внешние, так и на внутренние системы (в том числе и на систему с уязвимостью, позволяющей DoS-атаку).
Немного теории из прошлого века (можно пропустить)
Один из старейших способов DoS-атаки – это SYN-flood. Атакующий засыпает атакуемый сервис SYN-пакетами, игнорируя SYN/ACK-ответы. Таким образом, на хосте жертвы появляется множество полуоткрытых соединений, и в конце концов жертва становится просто не состоянии ответить даже на вполне нормальный и легитимный запрос на соединение с сервисом. Такой способ атаки стар, как сам Интернет, а первая официальная классификация, за авторством исследователей из CERT, появилась аж в 1996 году. На настоящий момент существует множество способов борьбы с SYN-flood, такие как SYN-куки, SYN-кэширование, фильтрация и адаптивная обработка на шлюзах. Использование в SYN-flood полуоткрытого, а не полностью открытого соединения выгодно не только тем, что атакуемая сторона не обрабатывает ответы, но и тем, что в отправляемые SYN-запросы можно подставить любой IP-адрес, таким образом скрыв атакующего. Несмотря на то, что атака открытыми соединениями может быть более эффективной с точки зрения противостояния средствам защиты, правильная ее реализация гораздо сложнее (если, конечно, это не DDoS-атака). Посредством SSRF можно эмулировать DoS-атаку открытыми соединениями, при этом IP-адрес атакующего будет точно так же скрыт от жертвы.
Суть уязвимости
Допустим, у нас есть хост, имеющий уязвимость, позволяющую произвести SSRF-атаку. Это может быть XXE-инъекция, некорректный серверный редирект, CRLF-расщепление запроса или простейший file_get_contents() с пользовательским параметром в PHP. Передав хосту некий URI, мы может заставить его выполнить запрос с использованием соответствующего протокола. Первое, что приходит в голову в отношении релеинга DoS – передать HTTP-URI типа http://потенциальнаяжертваdos:портсервиса/
. Но, поскольку протокол HTTP подразумевает, что клиент первым отправляет запрос, то соединение между хостом-релеем и хостом-жертвой быстро завершится. Выбор других типов URI невелик: кроме HTTP, только FTP поддерживается практически всеми широко распространенными технологиями, в которых возможен SSRF. На первый взгляд, передача URI типа ftp://потенциальнаяжертваdos:портсервиса/
выглядит многообещающе, так как FTP-клиент перед отправкой команд ждет приветствия от сервера («220 FTP server ready»). Но, к сожалению, большинство FTP-клиентов имеют небольшой таймаут соединения и, не получив ответа от сервера в течение 5–10 секунд, попросту отключатся. Большинство серверных технологий с «поддержкой» SSRF разорвут соединение с потенциальной жертвой, если будет разорвано соединение, внутри которого происходила SSRF-атака. Еще одно препятствие – клиент моментально отключится от сервера, если получит сообщение, отличное от стандартного приветствия. Но не все потеряно – FTP через SSRF все еще можно использовать в качестве DoS-релея. Для этого необходимо просто вспомнить о некоторых свойствах протокола.
При работе с FTP-сервером клиент использует два соединения – управляющее и передачи данных. Первое используется для обмена командами и результатами их выполнения между клиентом и сервером, второе – для непосредственной передачи данных (листингов каталогов, текстовых и двоичных файлов и т.п.). FTP может работать в двух режимах – активном или пассивном, от режима зависит способ установки соединения передачи данных.
В активном режиме FTP-клиент создает управляющее соединение с сервером и отправляет ему свой IP-адрес и новый номер порта (отличный от номера клиентского порта управляющего соединения), после чего ждет, пока сервер не запустит соединение с этим адресом и номером порта.
В современных сетях чаще всего используется пассивный режим, поскольку клиент может находится за NAT или брандмауэром. Клиент передает серверу команду пассивного режима и, получив от сервера его IP-адрес и номер порта, открывает соединение передачи данных с произвольного клиентского порта к полученному адресу и порту. Самая интересная особенность пассивного режима состоит в том, что, подключившись к каналу передачи данных сервера, клиент будет ждать, пока сервер начнет передачу данных. При этом таймауты на это соединение в большинстве FTP-клиентов сравнимы с таймаутами TCP-соединений. В прошлом активный режим на FTP-сервере широко использовался для проведения сканирований типа «FTP BOUNCE» и DoS-атак открытыми соединениями. SSRF позволяет использовать для проведения DoS-атак открытыми соединениями FTP-клиент в пассивном режиме.
Поскольку в режиме соединения передачи данных клиент всегда ждет данные от сервера, можно осуществить следующую схему атаки (см. рисунок 1). Атакующий поднимает где-то фейковый FTP-сервер (0), который в качестве адреса соединения передачи данных будет передавать адрес жертвы. В свою очередь, в SSRF-атаке в качестве URI можно передать ftp://фейковыйftpсервер/file.txt
(1). Тогда хост, подверженный SSRF (хост-релей), подключится к фейковому FTP-серверу и при попытке скачать файл (2) получит от него в качестве адреса и порта пассивного соединения адрес и порт жертвы (3). Установившееся соединение (4) между хостом-релеем и жертвой будет активно не менее 60 секунд (если сервис на хосте-жертве ждет каких-то данных от клиента, так ведут себя, например, HTTP и LDAP). Приятное дополнение: после установки соединения передачи данных управляющее соединение между фейковым FTP-сервером и хостом-релеем можно разорвать. Соединение передачи данных при этом не будет затронуто до конца передачи данных или таймаута. Таким образом, при многократном проведении SSRF-атаки путем передачи адреса фейкового FTP-сервера на хост-жертву обрушится поток подключений, целиком зависящий от мощности и настроек web-сервера хоста-релея. При этом нагрузка на фейковый сервер не такая уж и большая. Если наш фейковый сервер способен обрабатывать 100 запросов в секунду, то к концу первой минуты атаки с хостом-жертвой будет установлено уже 6000 соединений. Кроме того, хост-жертва никогда не узнает IP-адрес атакующего.
Осталось решить последнюю задачу – как же передать клиенту (хосту-релею) адрес жертвы?
Схема атаки
В современной реализации FTP за установление пассивного режима отвечают две команды PASV и EPSV. Основное их отличие – в ответе.
Синтаксис ответа PASV:
227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
(где a1-a4 — октеты IP-адреса в десятичном счислении, а порт представляется в виде 256*p1 + p2)
Синтаксис команды EPSV немного иной:
229 Entering Extended Passive Mode (|||p|)
(где p – порт)
Таким образом, более новая команда EPSV (описанная в RFC 2428) запрещает указывать другой IP-адрес для установления соединения передачи данных, и FTP-клиент по умолчанию считает этот адрес равным адресу сервера в управляющем соединении. Казалось бы, стройная идея атаки рушится. Но в реальности, если сервер ответит на команду EPSV «500 Command not implemented», то подавляющее большинство реализаций FTP-клиентов предложат серверу команду PASV. А уже в ней можно передать адрес и порт сервиса жертвы. При этом в большинстве случаев сразу после получения от FTP-клиента команды RETR (получение файла) можно разорвать соединение с клиентом.
Пример: допустим, у нас есть уязвимый к XXE JSP-сервлет, работающий под управлением Java 1.6.x. Отправив ему в качестве внешней ENTITY, например, "<!ENTITY J SYSTEM "ftp://fakeftp.adress/file">
", можно инициировать его подключение на фейковый FTP. Тот, в свою очередь, для осуществления атаки должен произвести следующую серию ответов на команды:
220 i58 FTP server ready.
USER anonymous
331 Guest login ok, send your email address as password.PASS Java1.6.0_01@
230 Guest login ok, access restrictions apply.TYPE I
200 Type set to I.EPSV ALL (2)
500 Command not implemented, superfluous at this site. (2)PASV (2)
227 Entering Passive Mode (vic,tim,server,ip,0,80). (3)RETR file
150 Opening BINARY mode data connection for 'file' (5000000 bytes).
[здесь фейковый FTP-сервер может спокойно разорвать соединение]
Как это выглядит в WireShark (192.168.200.138 – фейковый FTP, 192.168.200.128 – релей, 46.4.x.x – жертва)
Определенная тонкость заключается в том, что фейковому FTP необходимо отвечать ошибкой на любые команды активного режима (e.g. EPRT) и команды пассивного режима новой формации (EPSV, EPSV ALL), чтобы у FTP-клиента не было выбора, кроме как использовать старую команду PASV. Кроме того, в ответе на команду RETR должен быть указан достаточный размер файла, чтобы FTP-клиент продолжал поддерживать соединение, даже если атакуемый сервис отправит ему какие-то данные.
Различные web-технологии, подверженные SSRF-атакам, имеют разные реализации FTP-клиентов. Эти реализации обладают своими свойствами, которые накладывают ограничение на применение DoS-релеинга посредством URI-схемы ftp://
. Сводные характеристики клиентов представлены в таблице:
PHP | +* |
cURL | + |
Java 1.6 | +* |
Java 1.7 | Соединения передачи данных только с 127.0.0.1 и адресом FTP-сервера* |
LWP | +* |
ASP.Net | -** |
Python | + |
* В некоторых случаях необходимости в фейковом FTP-сервере нет, так как управляющее FTP-соединение в данной технологии имеет тайм-аут в 60 секунд, и если атакуемый сервис не возвращает (некорректных) данных, то можно в качестве URI в SSRF-атаки передать напрямую ftp://адресжертвы/file.txt
. Если вам повезло, то FTP-соединение не будет разорвано, даже если будет закрыто соединение, внутри которого происходила SSRF-атака.
** В ASP.Net при XXE-инъекции управляющее FTP-соединение с удаленным хостом устанавливается с таймером в 60 секунд. Кроме того, при разрыве соединения, внутри которого происходила SSRF-атака, соединение с жертвой остается. Так что, несмотря на отсутствие поддержки PASV, возможна прямая атака с релеингом.
Забавно, но в Java 1.7 запрещено устанавливать соединение передачи данных с адресом, отличным от адреса контрольного соединения, даже если используется команда PASV. Но, внося эту правку, разработчики забыли про локальную петлю, то есть можно применить данную технику для DoS'а внутренних сервисов хоста, даже закрытых брандмауэром. В качестве реального примера можно привести одну из старых версий SAP Portal, в которой была возможна SSRF-атака через XXE. Портал лег при =<50 запросов с SSRF и релеингом атаки на локальный SAP'овский web-сервер при помощи URI с протоколом FTP.
Защита
Как можно защититься от атаки такого рода? Понятно, что если нет уязвимостей, приводящих к SSRF, то и данная техника работать не будет. Если опустить рассуждения на тему того, что в современном мире уже не осталось FTP-серверов без поддержки RFC 2428 и что всем разработчикам библиотек FTP-клиентов стоит мандатно запретить использование команды PASV, то… Можно сделать так, как сделали разработчики Oracle в последней версии Java – запретить устанавливать соединения передачи данных с хостами, отличными от локальной петли и самого FTP-сервера. Но, как видно, такая «правка» не дает полной защиты от релеинга DoS. Некоторую гарантию от такого рода атак дает лишь жесткая фильтрация исходящих соединений, причем в данном случае это может сделать сам администратор сервера или инженер по ИБ, но это та ситуация, когда лекарство может быть опаснее болезни. А от релеинга DoS через локальную петлю это все равно не спасает.
Выше не описано ничего абсолютно нового или ранее не открытого, но вдвойне забавно видеть, как открытие новых типов атак на системы позволяет оживать давно уже забытым техникам.
Автор статьи — аналитик Digital Security Александр Большев, к сожалению, пока не имеющий аккаунта на Хабре.
Автор: oprisko