Информационная безопасность
[RU] switch to English


Хакер-спец #9 20053APA3A

Безопасность распространенных прикладных сетевых протоколов: взгляд со стороны клиента

Получив предложение написать статью о безопасности сетевых протоколов и их уязвимостях, я сначала хотел отказаться - кажется, что на эту тему написано уже все, что можно. Но не смог удержаться от соблазна взглянуть на эту проблему не с привычной точки зрения атаки на серверные системы, а рассмотреть некоторые (и ни в коем случае не все) интересные аспекты, связанные с работой клиентских приложений. Проблема безопасности клиентских приложений это то, что занимает меня последние 7 лет. А с началом 21го века именно проблему безопасности клиентских систем ведущие эксперты ставят на первое место. Конечно, мы никуда не денемся от анализа классических атак, таких как перехват соединения данных в FTP и на любителей 0days эта статья не рассчитана, но надеюсь, что взгляд на некоторые проблемы будет если и не новым, то, по крайней мере, интересным.
  1. Ошибки уровня стандарта - дырки в RFC.

    Проблемы с безопасностью клиентского приложения могут начаться еще до того, как оно написано - в момент, когда выбираются протоколы и стандарты по которым приложение будет работать.

    История протокола FTP

    Переходим к обязательной программе. Говоря о безопасности сетевых протоколов, нельзя не рассказать о протоколе FTP (File Transfer Protocol, протокол передачи файлов). Последний стандарт описывающий протокол FTP, RFC 959, относится аж к 1985 году. То есть за 3 года до червя Морриса - первого события привлекшего общее внимания к вопросам компьютерной безопасности. Червь Морриса вообще был хорошим пинком сети, поменявшим направление ее развития, его польза многократно превосходит нанесенные им же убытки. Но тогда протокол FTP был создан исключительно для удобной передачи файлов между системами, но без малейшей попытки сделать эту передачу безопасной. Меня просто поражает тот факт, что этот протокол до сих пор используется, причем практически в первозданной форме, в тех приложениях, для которых он совершенно не подходит. Протокол FTP вообще очень неудобен в реализации - этот протокол никогда не создавался для реализации в какой-либо клиентской программе. Например, FTP не определяет формат, в котором должен выдаваться список файлов. Протокол FTP создавался как расширение обычного протокола telnet, т.е. все команды FTP должны были даваться пользователем из командной строки и подразумевал наличие у пользователя shell доступа на FTP сервер. FTP-клиенты, которые предоставляли бы пользователю удобный интерфейс появились значительно позже. Давайте кратко опишем этот протокол. Протокол FTP поддерживает 2 режима - пассивный и активный и используется для передачи файлов (получения или хранения) а так же получения оглавлений каталогов. В обоих режимах FTP используется контрольное соединение, которое устанавливается клиентом на 21й (по-умолчанию) порт FTP сервера. По контрольному соединению никакие данные, ни файлы, ни оглавления каталогов, не передаются. Для передачи любого файла или оглавления устанавливается отдельное соединение.

    FTP Active Mode

    рис.1 Активный режим FTP

    В активном режиме клиент открывает со своей стороны порт, сообщает IP адрес и номер порта серверу в команде PORT, сервер устанавливает соединение на порт, выбраный клиентом (в качестве порта источника обычно используется 20).

    FTP Passive Mode

    рис.2 Пассивный режим FTP

    В пассивном режиме клиент дает команду PASV, на что сервер открывает TCP порт, сообщает ее клиенту, после чего клиент устанавливает на него соединение. После установки второго соединения (DATA connection) клиент может дать команду на получение или отправку данных, которые и будут переданы без какой-либо модификации через это дополнительное соединение, после чего оно немедленно будет разорвано. Изначально, эти два режима предназначались для того, чтобы клиент мог переписать файл с одного сервера на другой, не закачивая файл к себе.

    FTP between 2 servers

    рис.3 Перезапись файла между двумя сервами FTP

    Для этого клиент мог установить контрольное соединение на сервер A, дать ему команду PASV, установить соединение на сервер B и дать ему команду PORT с данными переданными сервером A в ответ на команду PASV. Таким образом DATA connection устанавливалось между серверами A и B, после чего клиент может дать команду на хранение файла одному серверу и передачу файла второму серверу.

    Классические атаки на FTP

    На первый взгляд, все гениально. Недостатки протокола FTP впервые были подробно описаны экспертом лаборатории NAI Дэвидом Сейсердотом (David Sacerdote) только в 1996. В чем они заключаются? Что, если после того, как сервер открыл порт по команде PASV, к нему подключится кто-то посторонний? Это значит, что когда клиент даст команду на получение или хранение файла, сервер отдаст файл постороннему, или получит файл любезно предоставленный посторонним, а клиент останется ни с чем. Такая ситуация называется перехватом соединения данных (DATA connection hijack).

    Как посторонний может узнать порт, назначенный сервером, если он не видел ответа на команду PASV в контрольном соединении? Для этого ему может быть достаточно установить свое контрольное соединение и дать команду PASV. В большинстве случаев, если он сделает это непосредственно перед соединением клиента, он получит порт на единичку ниже и может попытаться атаковать следующий порт.

    Следующая классическая атака с использованием особенностями протокола FTP связана с командой PORT.

    FTP bounce attack

    рис.4 Атака FTP Bounce

    Что если попросить FTP Сервер подключиться к интересующему нас порту постороннего компьютера? Если порт закрыт, то мы сразу получим сообщение об ошибке. А если порт открыт? То мы можем заслать туда любой файл, хранящийся на FTP сервере, дав команду на получения файла. Таким образом, мы можем использовать FTP сервер для атак на чужой компьютер, оставаясь при этом в тени. Причем, если FTP сервер стоит на пограничном компьютере, мы можем атаковать компьютер находящийся во внутренней сети. Такая техника называется FTP bounce attack (не знаю, как это принято переводить на русский, но звучит как "атака рикошетом от FTP").

    Но больше всего матных слов в адрес протокола FTP было сказано, разумеется, разработчиками различных средств защиты, которым надо было работу этого FTP обеспечить. Как, например, обеспечить работу FTP клиента, с его обратными соединениями в активном режиме, через NAT? Или работу FTP сервера в пассивном режиме, с его соединениями на случайные непривилегированные порты за брандмауэром? Открывать все порты? Единственное решение, которое и используется разработчиками - это следить за командами, передаваемыми в контрольном соединении или ответами сервера. Например, следить за ответом сервера на команду PASV и разрешать соединение на указанный им порт. Однако, если фаервол работает на сетевом уровне и анализирует данные только одного IP пакета, то его можно обмануть, "заставив" FTP сервер сгенериовать пакет с нужными данными. Например, выдав длинную заведомо неправильную команду, содержащую в конце нужные нам данные. При ответе сервера сообщением об ошибке, в котором сервер повторит команду, будет сформировано несколько IP пакетов. Можно угадать размер команды так, чтобы нужные нам данные пришлись на начало второго пакета, и таким образом заставить фаервол открыть нужный нам порт.

    Еще одна менее распространенная атака позволяет просканировать порты самого FTP сервера. Для этого просто команда PASV дается большое количество раз. Разумеется, сервером открываются только те порты, которые были свободны, это позволяет обнаружить "занятые" порты.

    Как решаются все этим проблемы? Большая часть FTP серверов пожертвовали возможностью прямой передачи файлов с сервера на сервер, и требуют, чтобы соединение на порт данных приходило с того же адреса, что и контрольное соединение. То же касается и команды PORT. Трюк со сканированием портов через PASV во многих серверах еще проходит, хотя кое-где порты открываются в случайном порядке из ограниченного диапазона. Современные фаерволы используют технику stateful inspection, когда "реконструируется" протокол прикладного уровня, а не учитываются данные отдельных пакетов, это устраняет возможность обхода фаерволов:

    Ну а что же с FTP клиентом?

    Все классические атаки FTP касаются сервера. Дэвид Сейсердот написал, что атака на перехват соединения крайне сложно реализуется для сервера и не реализуется для клиента. К сожалению, статью Дэвида, по рекомендации Aleph One я прочитал значительно позже : Но не читали ее и разработчики серверов FTP. А потому, когда лет через 5 я изобрел велосипед и заново "открыл" эту проблему все было в первозданном виде. По счастливому стечению обстоятельств и из-за природной лени, вместо статьи я написал весьма простенькую утилитку, ftpspy, которая использовала обычный connection flood успешно срабатывала с вероятностью более 50% на большинстве живших тогда FTP серверов:. А так же и FTP клиентах, только не в пассивном, а активном режиме.

    FTP data hijack (ftpspy) attack

    рис.4 Атака перехвата FTP-соединения против клиента

    Правда для атаки на FTP клиента она требовала, чтобы на той же машине присутствовал FTP сервер, чтобы иметь возможность "угадать" порт. Если порты назначаются системой подряд, то порт можно угадать и другим способом, например "прогнав" письмо через почтовый сервер. Используя техники Stealth-сканирования можно наблюдать за достаточно большим количеством портов одновременно. Ниже в этой статье, рассматривая проблемы утечки данных и пассивного сканирования мы найдем и другие способы определения клиентского порта. Подробнее об истории ftpspy (кроме исторической ценности он уже больше ничего не имеет, т.к. большая часть систем имеют если и не безопасные FTP сервера, то по крайней мере защиту от SYN-флуда) можно прочитать в [http://www.security.nnov.ru/articles/].

    Все вышеперечисленное затрагивает и проблему обхода брандмауэра через клиента FTP. Заставив клиента загрузить файл с хорошо подогнанным длинным именем с вашего FTP сервера, можно "подделать" команду PORT, и заставить брандмауэр, персональный брандмауэр или NAT с трансляцией портов, защищающий клиента пробросить TCP порт на интересующий порт клиента (например 139). IP адрес, как правило, контролируется, поэтому дальнейшая атака должна проводиться с того же сервера.

    Итак, мы теперь знаем основные недостатки FTP с точки зрения клиента - возможность перехвата данных, недостаточная стандартизованность и плохая совместимость с брандмауэрами. Это само по себе уже достаточный повод избегать использования FTP везде, где можно.

    Проблемы "монстроидальных" протоколов

    Очень часто проблемы протокола связаны с попыткой разработчика сделать протокол слишком универсальным и описать в нем как можно больше функций. Из-за этого получается "монстр", реализовать который чрезвычайно сложно, и еще сложнее соблюсти при этом безопасность. В качестве иллюстрации можно привести протоколы IMAPv4 и POPv3. POPv3 достаточно легковесный протокол с минимальным набором команд для получения почты. IMAPv4 - грузный монстра, который предназначен для реализации почты в "легком" клиенте - в нем все функции сортировки, поиска и хранения сообщений, анализа структуры сообщения, работы с вложенными файлами и т.д. перекладываются на сервер. К чему это привело? К тому, что кроме единственной программы pine, написанной самими разработчиками протокола никто не поддерживает IMAPv4 в полном объеме. Ни одна другая, включая все популярные почтовые агенты, не использует никакой функционал IMAP, которого не было бы в POP (существует распространенное мнение, что POP3 не поддерживает хранение писем на сервере, просмотр части сообщения, выборочное получение или удаление сообщений - это не так). В тоже время, IMAPv4 позволяет работать, например, с любыми файлами находящимися на сервере, за пределами почтовой папки или ящика пользователя, о чем администраторы очень часто даже не догадываются. Набор утилит [http://www.security.nnov.ru/files/imaptools.tgz] позволяет просматривать, получать и удалять любые файлы с правами почтового пользователя через сервер imap-uw.

  2. Общие проблемы различных протоколов - аутентификация пользователя

    Другая распространенная проблема, возникающая еще до того, как приложение написано - выбор протокола аутентификации пользователя.

    Аутентификация - это процесс, в результате которого сервер узнает, кем является подключающийся пользователь. В настоящее время наиболее распространенным методом аутентификации для сервисов Internet является проверка имени и пароля пользователя. Что можно сказать о наиболее распространенных протоколах? Протокол передачи почты SMTP (действующим стандартом является RFC 821, более свежий RFC 2821 не получил такого статуса и, скорее всего, никогда не получит) не предусматривает аутентификации пользователя. По идее, это означает, что SMTP сервисом может пользоваться любой желающий, что позволяет подменить адрес отправителя сообщения или разослать спам через почтовый сервис. На практике используется аутентификация и авторизация (т.е. определение какими именно функциями сервера может пользоваться клиент) по IP адресу. Как правило, почтовый сервер не дает клиентам "чужих" сетей использовать сервер в качестве релея, т.е. отправлять почту кому-либо, кроме получателей, обслуживаемых данным сервером. Имеется расширение протокола SMTP, RFC 2554, которое предусматривает возможность аутентификации и подразумевает, что основным методом аутентификации должна быть аутентификация по методу запрос-ответ. Однако на практике наиболее распространенным и совместимым методом является AUTH LOGIN, при котором логин и пароль пользователя передаются в открытом виде. Проверить какие протоколы аутентификации поддерживаются сервером можно с помощью команды EHLO:

    <<220 mailserver.domain.example Microsoft ESMTP MAIL Service 6.0.3790.1
    >>EHLO ME
    <<250- mailserver.domain.example Hello [172.22.22.227]
    <<250-TURN
    <<250-SIZE
    <<250-ETRN
    <<250-PIPELINING
    <<250-DSN
    <<250-ENHANCEDSTATUSCODES
    <<250-8bitmime
    <<250-BINARYMIME
    <<250-CHUNKING
    <<250-VRFY
    <<250-X-EXPS GSSAPI NTLM LOGIN
    <<250-X-EXPS=LOGIN
    <<250-AUTH GSSAPI NTLM LOGIN
    <<250-AUTH=LOGIN
    <<250-XEXCH50
    <<250 OK
    

    Данный сервер поддерживает аутентификацию по методу LOGIN (открытым паролем), NTLM и GSSAPI.

    Протокол HTTP (действующий стандарт RFC 2616) определяет возможность аутентификации пользователя, но не дает каких-либо конкретных механизмов. RFC 2617 определяет возможность аутентификации паролем в открытом тексте, называемую в HTTP Basic или по методу запрос/ответ (challenge/response) который в HTTP называется Digest. Однако аутентификация паролем в открытом виде на сегодня является единственным методом поддерживаемым во всех распространенных браузерах и веб-серверах. Поддерживаемые сервером методы аутентификации видны из заголовка WWW-Authenticate, который сервер дает при запросе на аутентификацию:

    Content-Length: 1037
    Content-Type: text/html
    Server: Microsoft-IIS/6.0
    WWW-Authenticate: Basic www.domain.example
    WWW-Authenticate: Negotiate
    WWW-Authenticate: NTLM
    X-Powered-By: ASP.NET
    Date: Wed, 13 Jul 2005 20:33:28 GMT
    

    Показывает, что сервер поддерживает аутентификацию Basic, Negotiate и NTLM.

    Протокол FTP поддерживает исключительно аутентификацию в открытом тексте, хотя и для него есть расширения, аналогичные AUTH в SMTP для аутентификации методом запрос-ответ.

    Протокол POP3 (RFC 1939) поддерживает 2 метода аутентификации - аутентификацию в открытом тексте и аутентификацию APOP по методу запрос-ответ. Кроме того, опять же имеются расширения аналогичные AUTH в SMTP. Отличить сервер поддерживающий APOP достаточно легко по баннеру сервера:

    +OK Microsoft Exchange Server 2003 POP3 server version 6.5.7226.0
    
    Этот сервер не поддерживает APOP.
    +OK 3APA3A/POP3-2.0-RC5.1 <[email protected]>
    

    Этот сервер поддерживает APOP, что видно по части приветствия заключенной в угловые скобки. Эта часть приветствия используется в APOP в качестве запроса (challenge).

    Несколько сложнее с поддержкой расширенной аутентификации по методам AUTH. Ее наличие и разрешенные методы иногда можно проверить с помощью команд CAPA или команды AUTH без параметров.

    Что представляет из себя каждый метод парольной аутентификации и какие его недостатки?

    Аутентификация в открытом тексте (plain text, он же USER/PASS в FTP и POP3, он же AUTH LOGIN в SMTP и IMAP, он же Basic в HTTP)

    Недостатки метода очевидны: пароль передается "по проводам" в открытом тексте, и может быть перехвачен в случае прослушиваемой разделяемой сети, с помощью ARP poisoning, DNS poisoning, при компрометации сервера или другими методами, обсуждение которых выходит за рамки статьи. В случае SMTP и HTTP логин и пароль передаются в кодировке base64.

    Аутентификации по Challenge-Response (запрос-ответ) с помощью стандартных хэш-функций

    К этим методам можно отнести APOP, AUTH CRAM-MD5 и Digest в HTTP, реже используются другие CRAM-методы, например CRAM-MD4, CRAM-SHA1. При использовании такой аутентификации пароль пользователя никогда не попадает в провода. Причем даже криптографические проблемы SHA-1 или слабые генераторы случайных чисел при генерации challenge практически не сказываются на уровне защиты пароля. Однако, следует помнить, что Challenge-Response не защищает от атак на подбор слабых паролей (bruteforce), в случае если пароль короткий или подбирается по словарю.

    Встроенная аутентификация Windows

    Это AUTH NTLM и аутентификации NTLM и Negotiate в HTTP. В Outlook Express встроенная аутентификация NTLM называется SPA (Secure Password Authentication). Недостатки такой аутентификации во-первых в ее прозрачности - сначала пробуется имя и пароль с которыми осуществлен вход в систему, во-вторых, во многих версиях Windows, невозможность подключиться к одному и тому же серверу с несколькими учетными записями. В третьих, это возможность атак релеинга аутентификации в случае NTLM. Об этом классе атак и других особенностях и недостатках NTLM подробно рассказывается в моей статье "NTLM и корпоративные сети" [http://www.security.nnov.ru/articles/ntlm]. Использовать встроенную аутентификацию Windows (и в частности SPA) с недоверенными серверами ни в коем случае нельзя.

    Аутентификация Kerberos

    Это AUTH GSSAPI и HTTP аутентификация Negotiate. Kerberos это единственная аутентификация, при которой проверяется IP адрес клиента и сервера в процессе аутентификации. Это защищает (разумеется, при полной и правильной реализации Kerberos) от атак релеинга и подмены сервера, от которых не защищают все прочие виды аутентификации. К сожалению, ввиду своей достаточно сложной топологии, в Internet Kerberos практически не применим, и используется преимущественно в корпоративных сетях, т.к. подобную аутентификацию сложно использовать через NAT или прокси.

    Во многих случаях клиентское приложение самостоятельно выбирает наиболее "мощный" протокол аутентификации, так поступают, например, практически все клиенты HTTP (браузеры). Хотя бывают и досадные недоразумения, как например в Mozilla Firefox [http://www.security.nnov.ru/Fnews19.html].

    На первый взгляд, такое поведения вполне оправдано, но у него есть огромный недостаток - атакующий, который имеет возможность контролировать трафик между клиентом и сервером (активные атаки Man-in-the-Middle, например в случае подмены сервера или релеинга соединения) может "заставить" переползти клиента на более мягкий протокол аутентификации, вплоть до открытого текста.

    Разумеется, после всего вышеперечисленного можно порекомендовать в клиентском приложении использовать Kerberos аутентификацию, либо, в случае если она недоступна, аутентификацию Challenge-Response.

    Кроме того, все современные протоколы поддерживают TLS (Transport Layer Security, протокол поглотивший SSL) версию. При условии, что работа с сертификатами реализована не корректна, TLS обеспечивает надежную защиту данных от перехвата и подмены, а так же взаимную аутентификацию клиента и сервера на основе сертификатов. Если есть такая возможность - TLS надо внедрять и использовать.

  3. Ошибки реализации сетевых протоколов в клиентских приложениях

    Хотя это и могло бы быть вкусным, мы не будем подробно разбирать уязвимости конкретных реализаций. На момент написания статьи в базе уязвимостей [http://www.security.nnov.ru/] 577 клиентских ошибок (более 10%). Назовем наиболее повторяющиеся проблемы:

    Переполнения буфера, ошибки форматной строки, целочисленные переполнения

    Ошибки связанные с плохим стилем программирования. Очень часто возникают при разборе клиента ответа на команду или даже при просто длинном приветственном сообщении сервера.

    Манипуляция данными

    Сюда можно отнести, например, проблемы межсайтового скриптинга или подмены содержимого в браузерах и почтовых программах. Подобные ошибки, как правило, связаны с плохим дизайном программы.

    Отказ в обслуживании

    Возникает, например, при разборе сложных или нестандартных данных и может приводить к зависанию приложения (вечным циклам) или краху. Чаще всего возникают из-за невозможности обработать исключительные или граничные ситуации.

    Недостаточная проверка данных

    Например, недостаточная проверка пути доверия сертификата или обратный путь в каталогах, когда серверное приложение может управлять тем, в какую папку попадет загруженный клиентом файл.

    Утечка информации

    Клиентское приложение сообщает больше чем требуется данных о себе, системе где оно работает или пользователе.

Пора сделать выводы: необходимо учитывать многие аспекты безопасности клиентских приложений - безопасность самого используемого протокола передачи данных, безопасность выбранного метода аутентификации и шифрования, качество кода клиентского приложения. Любое обращение клиентского приложения на сервер связано с некоторым обменом данных, эти данные могут быть "хорошими" или "плохими", о чем очень часто забывают разработчики.

Перепечатка данной статьи невозможна без разрешения издательства Gameland

О сайте | Условия использования
© SecurityVulns, 3APA3A, Владимир Дубровин
Нижний Новгород