Безопасность как искусство
92,45
рейтинг
4 марта 2013 в 15:51

Разработка → SSRF DoS Relaying recovery mode

За 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 типа потенциальнаяжертваdos:портсервиса/. Но, поскольку протокол HTTP подразумевает, что клиент первым отправляет запрос, то соединение между хостом-релеем и хостом-жертвой быстро завершится. Выбор других типов URI невелик: кроме HTTP, только FTP поддерживается практически всеми широко распространенными технологиями, в которых возможен SSRF. На первый взгляд, передача URI типа потенциальнаяжертва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сервер/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 "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-атаки передать напрямую адресжертвы/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 Александр Большев, к сожалению, пока не имеющий аккаунта на Хабре.
UPD: благодаря Genome_X аккаунт появился — встречайте пользователя dark_k3y!
Автор: @oprisko
Digital Security
рейтинг 92,45
Безопасность как искусство

Комментарии (12)

  • 0
    Интересная статья, спасибо.
  • +3
    Никто не против, если расшифрую SSRF — Server-Side Request Forgery. Плохо гуглится)
  • 0
    Только жесткая фильтрация исходящих соединений, только хардкор. Удивительная статья :)
  • 0
    «но это та ситуация, когда лекарство может быть опаснее болезни».

    А что в этом такого уж страшного? Многие хостинги (по крайней мере раньше) на самых простых видах услуги это запрещали по дефолту и открывали по запросу на избранные адреса или порты (например для исходящей почты). Да, это может что-то нарушить, но настроить все под нужды конкретного ресурса не квадратура круга. И защиту это даст не только от данного вида атаки.
    • +1
      Тут дело вот в чем:
      — во многих случаях FTP (порт управляющего соединения) так или иначе нужен (например, для обновлений) и закрывать его неудобно.
      — ну и 80-й порт наружу вы вряд ли закроете :)
      Что уже приведет к потенциальной возможности атаки на любые Web-сервера.

      Даже есть 21-й порт закрыт, то можно провести атаку через URI фейковыйфтпсервер:80/file.txt, а фейковый сервер (слушающий на порту 80) вам вернет адресжертвы,80. Кроме того, недостаточно жесткая фильтрация позволяет провести атаки не только на внешние хосты, но и на хосты в DMZ и (в худшем случае) внутренние хосты в сети.

      И даже если вы закроете и 80-й порт на выход, то остается еще менее эффективный «лобовой» метод атаки посредством URI адресжертвы: портсервиса, где адресжертвы — это 127.0.0.1 или адрес за DMZ/во внутренней сети.

      И вот фильтрация вышеперечисленных атак может доставить немало неудобств в обычном функционировании сети :)

      Хотя я с вами согласен, формулировка выглядит излишне пафосно, погорячился :)
      • 0
        Спасибо за комментарий. В целом все так. Просто вспомнился некий опыт относительно давний. И резануло слух. Закрыите 80 порта для исходящих соединений тоже практиковалось и для тьмущей тьмы сайтов-визиток или хомячковых форумов это проблемы не представляло в середие нулевых, а их чаще всего и ломали для подобных целей (незабвенная радость всех скрипткидди — пхпбб). А для кого представляло, те не сидели на виртуальном хостинге. Хотя сейчас да, понаворачивали всякого и наверное так не делают :)

        Типичный пример подобного условия в те годы support.demos.ru/archive/hosting/faq.php?SECTION_ID=121

        «Скрипт получает ответы от других web-серверов. Возвращается ошибка '400 Bad request'.
        В целях безопасности, на стандартном хостинге запрещены исходящие соединения и открываются только по запросу клиента, с указанием адреса ресурса к которому нужен доступ. Другим решением, в данной ситуации, может послужить использование услуги Виртуальный сервер VPS, где подобных ограничений нет.»
        • 0
          Ну тут речь идет не о сайтах-визитках на VPS, в них вероятность обнаружить SSRF очень мала. :) А вот любой мало-мальски средний/крупный проект стоит хотя бы на выделенном сервере, и там вероятность закрытия 80-го порта будет поменьше. По факту, как я уже писал в статье, лучшим способом предотвращения такого типа атак будет полный отказ от команды PASV (и замена её на корректную реализацию EPSV) в библиотеках соответствующих Web-фреймворков и языков.
          • 0
            Я ведь не утверждаю, что закрывали 80 порт из-за SSRF. Всякие там дырявые пхпбб или мамбы, которые владельцы никогда не обновляли и не будут можно использовать (и использовали) гораздо тривиальней, заливали туда скрипты и флудили и спамили ими без всяких извратов. Поэтому мера была очень жизненная, а не надуманная.
          • 0
            И кстать, «полный отказ от команды PASV » можно реализовать опять же не затрагивая библиотеки и прочий софт. На том же линуксе можно совершенно буюджетно зафильтровать иптаблесом символьную последовательность команды. Это может и кривовато выглядит, но действенно. Как и 80 порт можно блокировать не вообще, а для соотв. uid/gid что бы немного погибче было и тот же админ мог при необходимости в консоли юзать wget или менеджер пакетов что-то обновлять из сети.
      • 0
        Могу еще заметить и про ДМЗ. Я занимаюсь некоей корпоративной сеткой, в которой сама сетевая инфраструктура в моих руках, а вот серверная лишь отчасти и подчиняется всяким политикам вышестоящих корп. структур и рукам чужих серверных админов. Так я даже для внутренних, не публичных серверных сегментов ЛВС фильтрую исходящие коннекты в пользовательские или, где возможно и в другие серверные сегменты. Это не так гемморно и страшно, как кажется. Зато в нашей ветвистой организации мы из тех немногих, кто не личился от кидо в начале 2009, хотя с АВЗ было все не очень хорошо. Другие же заражались пошаговым принципом на ура (кого пугали трудности сетевой фильтрации). Сетевая фильтрация конечно не панацея, но не последний кирпичик в общем здании безопасности. Иногда (увы) — один из немногих вообще возможных.
        • 0
          Просто не все такие хорошие и педантичные администраторы, как вы :) Это раз.

          Во вторых, в условиях бизнес-приложений, очень трудно не оставить открытым хотя бы один порт. Обновления, бизнес-взаимодействия, различные API, сервисы и RPC… А уже хотя бы один открытый порт оставляет возможность для атаки (через него можно подключиться на фейковый FTP-сервер). А атаковать можно и внутренние сервисы внутри сети. И здесь к сетевой фильтрации подключается фильтрация уже на уровне контекста протокола, и настройка всего это в большой корпорации может быть действительно опасно для самой инфраструктуры. Хотя, вы правы, если все делать педантично и аккуратно, то защититься от релеинга атак (кроме как на самого себя) — вполне возможно. Но идеальных сетей к сожалению очень мало в этом мире :(.
  • 0
    Думаю правильным способом должно бы запретить на уровне приложения соединения по сторонним адресам из вьюшек страниц. На уровне контролеров контроль протокола и разрешонных для связи хостов.

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

Самое читаемое Разработка