Liferay в gov секторе — как тяга к халяве, ой, то есть к OpenSource доводит до CWE-319


Сегодня как раз читал статью про потрясающее детище советского инженерного искусства - Ми-173-2 - вертолёт радиолокационной разведки использовавшийся для перехвата радиотелефонной связи.
Да, в те суровые годы для того, что бы узнать секретные данные приходилось трудиться, стараться и напрягаться. В отличие от современных реалий.
Сейчас же, благодаря тяге "специалистов" к использованию дешёвых, а зачастую и бесплатных решений на базе Open Source вероятному противнику получить секретные данные стало очень-очень просто, достаточно выпустить программу которую захотят использовать например в госсекторе, при обслуживании почтовых рассылок с чувствительной информацией. И оставить в этой программе даже не бэкдор, а просто функцию по умолчанию, которая при нежелании "специалиста" прочитать инструкцию и настроить всё как следует - приведёт к компрометации паролей и утечке данных тысяч пользователей государственных сервисов.
Иностранщина в царстве Гостайны
Есть в ИТ-мире особая категория - закрытые государственные информационные системы (ГИС). Мир тотальной секретности. Здесь безопасность возведена в ранг абсолютной религии. Это место, где что бы просто заменить тонер в принтере, нужно иметь допуск к государственной тайне. Как меня не взяли эникейщиком, когда первый отдел запорол из-за цвета паспорта я уже рассказывал ранее.
Естественно, пользователь, заходящий на такой портал, ожидает увидеть интерфейс, вычищенный до блеска, тотально импортозамещенный и суровый.
И каково же изумление, когда под капотом монструозного портала обнаруживается сердце продукта от американской компании Liferay Inc. со штаб-квартирой в солнечной Калифорнии. Естественно, покупать коммерческие Enterprise-лицензии и платить американцам за DXP-версию в госсекторе никто не будет — санкции, комплаенс и здравый смысл против этого. Поэтому за основу берётся Liferay Community Edition — полностью бесплатная Open Source версия на Java.
Логика безопасников была идеальной: исходный код «коробки» можно легально скачать с GitHub, проверить по строчкам на отсутствие скрытых закладок, одобрить на совете ведомства и развернуть в закрытом защищенном периметре.
Сама архитектура получившейся системы выглядит монументально: авторизация делегирована внешним доверенным государственным шлюзам, обмен данными идет по защищенному протоколу OAuth 2.0, а фронтенд прикрыт валидными CSRF-токенами.
Вы проходите весь этот сложнейший квест верификации, открываете красивое модальное окно «Смена данных аутентификации», которое строго требует: «Придумайте новый сложный пароль». Вы вводите заветный секрет, нажимаете кнопку «Сохранить», сервер рапортует об успехе. А через секунду на ваш личный e-mail прилетает автоматическое транзакционное письмо, которое ставит шах и мат всей многомиллионной безопасности ведомства.
Потому, что кроме аудита софта на скрытые закладки надо ещё и идиотентест проводить среди сотрудников хоть изредка.
Анализ уязвимости: Смотрим глазами в Message Source
Побудем в роли душнилы и откроем исходный код прилетевшего письма (message-source) прямо в почтовом клиенте. Картинка ниже (все идентифицирующие домены и персональные данные, разумеется, надежно закрашены черным маркером ради принципов ответственного разглашения):

Давайте разберем технические улики, которые лежат на поверхности:
Улика №1: Забытая американская прописка
Смотрим на строку заголовка:Message-ID: <user.28615153.24b4fa5a-0f0f-05db-5d46-e748023d77d@events.liferay.com>
Хвост заголовка выдает дефолтную заглушку MailEngine в Liferay (@events.liferay.com), так как администраторы не переопределили свойство mail.string.id.
Почтовый сервер ведомства легально прошел все проверки SPF, но хвост заголовка выдает систему с потрохами.
Улика №2: Привет из песочницы разработчиков (localhost:8080)
В теме письма мы видим прекрасное:
Subject: http://localhost:8080: Your New Password.
Глобальная переменная платформы [$PORTAL_URL$], которая должна вести на официальный защищенный домен ведомства, на боевом сервере так и осталась настроенной на локальный компьютер разработчика, который собирал этот проект на коленке. Тестовые конфиги улетели в продакшен.
Улика №3: Главный грех (Plaintext в конверте)
И, наконец, тело письма:
Your new password for http://localhost:8080 is HabraHabr1.
Вместо того чтобы превратить введенный пользователем пароль в односторонний криптографический хэш (через bcrypt или Argon2) и навсегда забыть его текстовое представление, бэкенд взял этот пароль в виде обычной строки (String), подставил его в макропеременную [$PASSWORD$] внутри почтового шаблонизатора и отправил в открытом виде через цепочку почтовых посредников. Пароль лег в ваш почтовый ящик бессрочно — в незапечатанном конверте, который виден любому, кто получит доступ к почте.
Где была допущена ошибка?
Разработчики из американской компании Liferay быть может и не закладывали эту логику как уязвимость. Из коробки макрос [$PASSWORD$] в платформе предназначен только для сценария, когда администратор сам сбрасывает пароль пользователю из панели управления. Система генерирует случайный временный пароль, отправляет его на почту, а при первом входе заставляет человека его поменять.
Но инженеры сурового ведомства решили написать кастомный модуль (портлет) восстановления доступа. Они дали пользователю возможность самому ввести свой постоянный пароль в браузере, но по ошибке повесили на это действие стандартный дефолтный триггер уведомлений о создании нового аккаунта. В итоге получился опасный гибрид: пароль пользователь задал постоянный и секретный, а система обработала его как временный и выслала в рассылке.
Как исправить, если у вас может быть такая же ситуация
Если вы разворачиваете у себя тяжелые Enterprise-платформы (Liferay, Camunda, Alfresco и т.д.), помните: безопасность — это не про сложные шлюзы, это про мелочи. Закрывается эта критическая уязвимость класса CWE-319 за 10 минут силами администрирования, без написания кода.
Шаг 1. Вычищаем макросы из GUI
Заходим в панель управления Liferay под учетной записью Omniadministrator. Идем по пути: Control Panel -> System Settings -> Users -> Password Changed Notification (или New Password Notification).
Полностью удаляем макрос [$PASSWORD$] из темы и тела шаблона письма. Письмо должно содержать исключительно сухой технический факт: «Здравствуйте. Данные аутентификации для вашего Личного кабинета были успешно изменены. Если вы не совершали данного действия, немедленно свяжитесь с технической поддержкой».
Шаг 2. Корректируем системные переменные в файлах
Открываем конфигурационный файл ядра portal-ext.properties на сервере приложений и принудительно выставляем боевые параметры окружения вместо девелоперского localhost:
properties
# Задаем боевой хост для макроса [$PORTAL_URL$]
web.server.host=portal.your-goverment-domain.gov
web.server.https.port=443
web.server.protocol=https
# Переопределяем дефолтный американский домен в Message-ID почты
mail.string.id=portal.your-goverment-domain.gov
Выполняем перезапуск сервера приложений (Tomcat/WildFly). Уязвимость полностью устранена.
Вместо заключения
В XXI веке методы перехвата информации изменились. Больше не нужно ловить радиоволны над границами. Достаточно дождаться, пока enterprise-система сама пришлет пароль в открытом виде на сторонний почтовый сервис. Помните о Hardening'е, проверяйте дефолтные настройки «коробочного» софта и не оставляйте localhost там, где дежурит Первый отдел.
Дисклеймер: Данный материал подготовлен исключительно в образовательных целях и в рамках концепции Responsible Disclosure. Технический багрепорт со всеми деталями был заблаговременно направлен куда следует.
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.