Корпоративные данные часто представляют собой коммерческую тайну. Их утечка может привести к удару по репутации, финансовым потерям или даже банкротству. Поэтому требования безопасности к B2B-продукту должны быть очень высокими. Создавая новый продукт — Корпоративную Почту Mail.ru — мы уделяли вопросу ее безопасности особое внимание.

Корпоративная Почта Mail.ru — on-premises версия знакомой всем B2C-почты Mail.ru. По сравнению с ней она содержит ряд модификаций для работы в новых условиях — контуре клиента.

Чтобы наши клиенты были уверены в безопасности, мы решили пройти аудит в сторонней компании и исправить все найденные недостатки до того, как предлагать продукт рынку. Для этого обратились к одной из самых авторитетных компаний в сфере информационной безопасности — Digital Security.

Результаты аудита — под катом.

Удаленное выполнение кода в uWSGI


Существуют разные фреймворки для создания веб-приложений на Python. Обычно для связки между веб-приложением и веб-сервером используют интерфейс Python Web Server Gateway Interface (WSGI). Кроме того, использование WSGI позволяет реализовать middleware-компоненты.

Чтобы стандартизировать взаимодействие между веб-приложением на Python и веб-сервером, например Apache или Nginx, был разработан стандарт PEP 0333, а затем PEP 3333, — в этих стандартах описывается WSGI-интерфейс. Не будем останавливаться на том, как работает WSGI, а расскажем о популярном сервере, который поддерживает WSGI-интерфейс — uWSGI.



uWSGI-сервер может работать как в режиме обычного веб-сервера, так и в «WSGI-режиме», обмениваясь данными с другим веб-сервером, например Nginx. При этом Nginx использует одноименный бинарный протокол uwsgi, который интересен злоумышленникам благодаря богатой функциональности. При анализе «внутренностей» решения обнаружился uWSGI-сервер, доступ к которому был у всех внутренних компонентов продукта.

Проблема была в том, что в uwsgi-протоколе можно использовать так называемые магические переменные, которые позволяют динамически конфигурировать uWSGI-сервер. Среди этих переменных есть UWSGI_FILE, которая позволяет загрузить новое динамическое приложение, если в переменной указать путь до файла. Как оказалось, uWSGI-сервер может обрабатывать различные схемы в этом пути, например: section, fd, call,или самое интересное — exec. Таким образом, можно передать в качестве значения переменную exec://<cоmmand>, что позволит выполнить произвольную bash-команду. Для анализа этой проблемы был написан эксплоит, доступный на github.


Пример запроса, выполняющего команду.

Эта уязвимость могла быть проэксплуатирована, только если злоумышленник:

  • Уже находится во внутренней сети продукта, например, скомпрометировал один из компонентов. Это может позволить ему захватить новый компонент, получить доступ к новым данным и продолжить атаку.
  • Имеет SSRF с возможностью отправки произвольных данных по TCP (например, с использованием gopher://). В этом случае злоумышленник может получить доступ внутрь продукта.

Стоит отметить, что реализации CGI-интерфейсов для других языков программирования или фреймворков тоже могут быть уязвимы, пример — эксплоит из того же репозитория для FastCGI. Нельзя сказать, что это уязвимость в привычном понимании, скорее особенность CGI-серверов, поэтому нужно максимально ограничивать доступ к таким серверам.

Обход CSRF-защиты


Благодаря внедрению различных механизмов безопасности в браузерах, client-side атаки в современном вебе постепенно начинают исчезать. Это относится и к CSRF: браузеры уже внедрили поддержку SameSite cookie, хотя при неправильной их конфигурации всё равно могут оставаться лазейки. Кроме того, многие популярные фреймворки позволяют разработчикам легко настроить CSRF-защиту, но несколько ошибок или некритичных уязвимостей могут обернуться возможностью CSRF-атаки. Такие ошибки были обнаружены в приложении календаря, входящего в наш продукт.

В приложении есть API, которое позволяет выполнять действия над событиями и календарями пользователя, например: редактировать, просматривать или удалять их. Для обращения к объекту в URL-пути передается параметр UID, который отвечает за ID календаря или события. Выглядит это примерно так:

example.com/api/calendar/{UID}/action?
example.com/api/event/{UID}/action?



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

Первое — импорт файлов в формате ICS (специальный формат для календарей и событий), в них есть специальное поле UID, которое пользователь контролирует при импорте. При этом после импорта событий их UID останутся такими же, какие были переданы в файле. Кроме того, у этого параметра нет фильтрации. Таким образом, пользователь мог создавать событие с произвольным UID.

Второе — возможность изменения UID-календаря при его редактировании. Это можно было сделать, перехватив запрос с редактированием календаря и просто изменив поле UID. Фильтрация отсутствовала и тут.

Другая важная особенность: в этом API реализована CSRF-защита, для этого в GET-параметрах передается специальный параметр, играющий роль как ключа для API, так и CSRF-токена. Он добавляется с помощью JavaScript ко всем запросам к API. Передавать CSRF-токены в GET-параметрах — плохая практика, в этом случае возможна утечка токенов через referer, логи приложения или историю браузера.

Соберем всё вместе. Злоумышленник может в приложении контролировать UID объектов и делиться с другими пользователями доступом как к событиям, так и к календарям. При этом пользователи будут видеть тот же UID, а когда станут работать с таким объектом, запросы будут выполняться с UID, который контролируется злоумышленником. Используя это, злоумышленник может сделать объект с UID вида:

../../../AnyPathTo?anyparam=value&

Теперь, когда пользователь будет выполнять действие над объектом, сгенерируется запрос:

example.com/api/event/../../../AnyPathTo?anyparam=value&/action

Потом к нему также добавится токен, играющий роль CSRF-токена:

example.com/api/event/../../../AnyPathTo?anyparam=value&/action&token=abcdef

И наконец, выполняя запрос, браузер нормализует последовательность «../», в итоге запрос отправится к

example.com/AnyPathTo?anyparam=value&/action&token=abcdef

Теперь злоумышленник может заставить пользователя отправить запрос к приложению по произвольному пути с произвольными параметрами и с корректным CSRF-токеном. Осталось понять, какие методы запросов мы можем выполнять.

Это оказалось просто: при редактировании отправляется PUT, при удалении — DELETE, при просмотре — GET (POST применяется для создания, и мы не можем вынудить жертву его использовать). С помощью DELETE злоумышленник сможет заставить браузер пользователя выполнить запрос на удаление какого-либо объекта у пользователя. Отдельный бонус для злоумышленника — когда пользователь редактирует объект, отправляется PUT-запрос с телом запроса. При редактировании календаря в теле запроса будет JSON, в котором указаны все параметры текущего календаря. То есть злоумышленник, создавший «зловредный» календарь, контролирует эти параметры. Если злоумышленнику удастся перенаправить запрос на редактирование со «зловредного» календаря на приватный календарь пользователя, то все свойства «зловредного» календаря применятся к свойствам календаря пользователя-жертвы. Так можно перезаписать доступ к календарю, поскольку он является одним из свойств календаря, указанных в JSON.



Возможность MITM-атаки


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

Одна из главных возможностей продукта — интеграция с Active Directory. Она реализована для аутентификации через LDAP и сбора писем с сервера Exchange, в этом примере речь пойдет об ActiveSync. Для злоумышленника это очень интересная цель, поскольку во время соединения между продуктом и Active Directory передаются учетные записи и пароли пользователей. Получив доступ к соединениям, злоумышленник сможет перехватывать учетные записи и будет на один шаг ближе к компрометации домена.

Во внутренних решениях и на серверах компаний часто встречается проблема с некорректным использованием TLS или вообще его отсутствием, притом что внедрить TLS для сервиса несложно. Обычно это следствие того, что внутренняя сеть компании считается более безопасной, и администраторы компании не тратят время на создание корректной PKI-инфраструктуры и выпуск сертификатов для всех серверов.

Самая частая атака внутри корпоративных сетей — MITM. Атаки этого типа чаще всего позволяют получить доступ внутри Active Directory компании. При этом далеко не всегда злоумышленник может атаковать взаимодействие server-to-server внутри сети компании, чаще всего он или его модель при пентестах попадает в пользовательский сегмент сети, в котором нет сервера Exchange или контроллера домена. Кроме того, в нашем случае продукт не использует широковещательные протоколы разрешения имен, такие как NBNS, LLMNR, mDNS, поэтому спуфинг этих протоколов не позволит реализовать MITM. Таким образом, для успешной MITM между решением и другими серверами необходимо, чтобы злоумышленник имел доступ в сеть, в которой установлен один из этих компонентов. Достигнуть этой цели иногда возможно — бывают уязвимые маршрутизаторы или серверы, которые в итоге позволяют получить доступ к той или иной сети.

В нашем случае в ходе анализа выяснилось, что интеграция с Active Directory уязвима к MITM-атакам.

Когда пользователь вводит логин и пароль, система отправляет два LDAP-запроса на контроллер домена. Первый запрос возвращает список почтовых адресов, и если логин пользователя присутствует в этом списке, то отправляется второй запрос, представляющий собой Simple LDAP Authentication. Данные передаются в открытом виде без использования SSL/TLS, вернее, не используется LDAPS (LDAP over SSL). Это позволяет злоумышленнику даже в случае пассивной MITM-атаки получать учетные записи пользователей, которые в данный момент авторизуются в продукте.



Вторая проблема: при соединении с Exchange-сервером по протоколу ActiveSync для сбора входящих писем система не проверяла подлинность TLS-сертификата сервера. В этом случае злоумышленник мог бы реализовать активную MITM-атаку, при получении соединения — отдавать самоподписанный сертификат, устанавливать соединение и проксировать данные на сервер Exchange; тогда MITM будет незаметна, а злоумышленник сможет получить учетные данные пользователя, которые передаются в протоколе ActiveSync.



Используя эти уязвимости, злоумышленник теоретически может получать учетные записи пользователей, после чего использовать их в атаке на домен Active Directory. Отдельно стоит отметить, что правильное использование TLS — это необходимая задача для компании, которая внедряет решение.

Результат


Мы постоянно сталкиваемся с хакерскими атаками и накопили солидный опыт в том, как их нужно отбивать. Считаем, что продукты, которые ставим в периметр заказчика, должны быть максимально безопасными, в том числе по результатам независимых проверок. Корпоративная Почта Mail.ru — именно такой продукт.

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

Мы попросили аудиторов уделить наибольшее внимание измененной авторизации (в Корпоративной Почте используется AD заказчика) и основному почтовому API — был подробно проанализирован исходный код этих компонентов. В итоге найденные недостатки в основном были связаны с измененной топологией сети и специфичными для решения on-premises модификациями.

Для остальных компонентов (календарь, интерфейс администрирования Mail.ru для бизнеса) использовалась модель gray-box: аудиторы взаимодействовали с сервисом с привилегиями обычных пользователей, но могли подключиться к контейнеру с запущенным приложением, частично обладали исходными текстами API и могли уточнять детали у разработчиков.

Аудит оказался для нас очень полезным. Мы нашли ряд недостатков в некоторых компонентах, которые оперативно исправили, чтобы выпустить на рынок безопасный продукт. Заодно убедились в высоком уровне защищенности большинства других компонентов. Планируем проводить такие аудиты регулярно — хотим, чтобы наш продукт всегда был в топе самых безопасных отечественных решений не только по нашему мнению, но и по мнению независимых аудиторов.

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