Чем уязвимость устаревшего метода аутентификации OpenID в Flask-AppBuilder опасна для Apache AirFlow и как это исправить? Обзор уязвимости CVE-2024-25128.
Уязвимости OpenID для FAB в Apache AirFlow
В конце февраля 2024 выяснилось, что в прошлом релизе Apache AirFlow 2.8, вышедшем 14 декабря прошлого года, обнаружилась критическая уязвимость, набравшая более 9 баллов по 10-баьлной шкале CVSS (Common Vulnerability Scoring System). Впрочем, эта неприятность вряд ли затронет слишком много пользователей, поскольку она связана с устаревшим методом аутентификации OpenID в Flask AppBuilder (FAB). Уязвимость CVE-2024-25128 позволяла злоумышленнику завладеть личностью любого пользователя пользовательского интерфейса Airflow, создав специально созданный запрос и внедрив собственную службу OpenID. OpenID – это открытый стандарт децентрализованной системы аутентификации, позволяющий создать единую учётную запись для аутентификации на множестве не связанных друг с другом интернет-ресурсов через внешних провайдеров. OpenID не стоит путать с OpenID Connect (OIDC) – популярным современным протоколом.
Проблема касается только тех пользователей Apache AirFlow, которые установили значение AUTH_OID для параметра AUTH_TYPE в конфигурационном файле веб-сервера webserver_config.py. Среда разработки приложений Flask-AppBuilder на основе Flask является Python-пакетом и предоставляет фреймворк для создания веб-приложений. Именно на этом основано веб-приложение веб-сервера Apache AirFlow. Уязвимость в Flask-AppBuilder позволяет злоумышленнику подделывать HTTP-запрос, обманывая бэкенд, заставляя его использовать любую запрошенную службу OpenID. Это может потенциально предоставить злоумышленнику возможность получить несанкционированный привилегированный доступ, если развернута пользовательская служба OpenID, доступная бэкенду.
Избежать этой проблемы можно, перестав использовать устаревший метод аутентификации или обновиться Apache Airflow до 2.8.2. Уязвимость исправлена в Flask-AppBuilder 4.3.11, а Apache Airflow 2.8.2 использует эту версию FAB. Менеджер аутентификации FAB изначально поставляется с Airflow, определяя аутентификацию и авторизацию пользователей по умолчанию. Бэкэнд для хранения всех сущностей, используемых менеджером аутентификации FAB, — это база данных метаданных Airflow. По умолчанию это SQLLite, но в промышленном развертывании она чаще всего заменяется на PostgreSQL, о чем мы писали здесь.
Вообще FAB поддерживает целых 5 методов аутентификации:
- AUTH_DB – самый простой тип аутентификации, когда приложение аутентифицирует пользователя по его имени и хэшированному паролю, хранящегося в базе данных;
- AUTH_LDAP – аутентификация на сервере LDAP, например MS Active Directory;
- AUTH_OAUTH – аутентификация с использованием OAUTH v1 или v2;
- AUTH_OID – задав ключ OPENID_PROVIDERS, можно добавить значения внешних провайдеров, которые будут обеспечивать аутентификацию пользователя через сторонний сервис;
- AUTH_REMOTE_USER – используется переменная среды веб-сервера REMOTE_USER, которая проверяет, авторизован ли удаленный пользователь с помощью таблицы пользователей фреймворка. Ответственность за аутентификацию пользователя лежит на веб-сервере. Это полезно для сайтов внутренней сети с использованием Kerberos, когда пользователю не нужно входить в систему с именем пользователя и паролем Flask-AppBuilder.
Если обновление или изменение метода аутентификации невозможно, следует добавить в конфигурационный файл веб-сервера webserver_config.py следующее:
import os from flask import flash, redirect from flask_appbuilder.security.forms import LoginForm_oid from flask_appbuilder.security.views import AuthOIDView from flask_appbuilder.views import expose from airflow.www.security import AirflowSecurityManager basedir = os.path.abspath(os.path.dirname(__file__)) class FixedOIDView(AuthOIDView): @expose("/login/", methods=["GET", "POST"]) def login(self, flag=True): form = LoginForm_oid() if form.validate_on_submit(): identity_url = None for provider in self.appbuilder.sm.openid_providers: if provider.get("url") == form.openid.data: identity_url = form.openid.data if identity_url is None: flash(self.invalid_login_message, "warning") return redirect(self.appbuilder.get_url_for_login) return super().login(flag=flag) class FixedAirflowSecurityManager(AirflowSecurityManager): authoidview = FixedOIDView SECURITY_MANAGER_CLASS = FixedAirflowSecurityManager
Этот код улучшает процесс аутентификации в веб-приложении самого популярного ETL-оркестратора, проверяя, что введенный пользователем OpenID URL соответствует одному из провайдеров, и заменяет стандартное поведение аутентификации на кастомное.
Освойте администрирование и эксплуатацию Apache AirFlow для оркестрации пакетных процессов в задачах реальной дата-инженерии на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
- Data Pipeline на Apache AirFlow и Apache Hadoop
- AIRFLOW с использованием Yandex Managed Service for Apache Airflow™
Источники