
В ClickHouse существует функция, которая позволяет пользователю с соответствующими разрешениями создавать словари для взаимодействия с различными базами данных и выполнения по ним конкретных запросов. Для PostgreSQL SELECT-запросы оборачиваются в выражение COPY( {QUERY} ) TO STDOUT перед выполнением в базе данных. Добавив скобку к созданному словарю, можно выйти из выражения COPY( {QUERY} ) TO STDOUT и выполнить произвольные SQL-запросы, что, в свою очередь, может привести к выполнению произвольных команд на сервере базы данных.
Словари PostgreSQL создаются со следующей структурой:
SOURCE(POSTGRESQL(
port 5432
host 'postgresql-hostname'
user 'postgres_user'
password 'postgres_password'
db 'db_name'
table 'table_name'
replica(host 'example01-1' port 5432 priority 1)
replica(host 'example01-2' port 5432 priority 2)
where 'id=10'
invalidate_query 'SQL_QUERY'
query 'SELECT id, value_1, value_2 FROM db_name.table_name'
))
В документации по движкам PostgreSQL, используемым в словарях, упоминается следующее:
SELECT-запросы на стороне PostgreSQL выполняются как COPY (SELECT ...) TO STDOUT внутри транзакции PostgreSQL только для чтения с фиксацией после каждого SELECT-запроса.
Поскольку запросы, определённые в словаре, не проходят дополнительной проверки перед отправкой в экземпляр Postgres, из выражения «COPY(...) TO STDOUT» можно выйти, начав запрос с «)», создав транзакцию, которая не является транзакцией только для чтения. Например, следующий запрос можно использовать в ClickHouse для создания «плохого» словаря Postgres:
CREATE DICTIONARY exec_dict(id UInt64, value UInt64 DEFAULT 0) PRIMARY KEY id SOURCE(POSTGRESQL(port 5432 host '172.17.0.3' user 'postgres' password 'password' db 'postgres' query 'SELECT 1) TO PROGRAM \'id>/tmp/test\';-- ')) LAYOUT(DIRECT())
После создания словаря его можно загрузить в ClickHouse, обратившись к словарю. ClickHouse вернёт ошибку, указывающую, что функция COPY, ожидаемая ClickHouse, завершилась сбоем. Однако остальная часть запроса всё равно выполнится в базовой базе данных PostgreSQL. Злоупотребляя функцией PostgreSQL PROGRAM, можно выполнять произвольные команды.
Хотя первоначальное тестирование проводилось на версии 25.8.10.7, когда отчёт был подан 30 января 2025 года, последняя версия на тот момент была 26.3.9.8, и уязвимость всё ещё присутствовала. После рассмотрения проблема была помечена как «не применимо» 10 апреля 2026 года со следующим заявлением:
нет — это связано не с соображениями безопасности, а в основном с эффективностью. Пользователь с учётными данными postgres + удалённой табличной функцией уже может многое сделать или напрямую подключиться к базе данных PostgreSQL и выполнить эти запросы.
Поэтому это не риск: злоумышленнику здесь требуются действительные учётные данные для базы данных PostgreSQL и действительный пользователь ClickHouse + разрешение на использование табличной функции PostgreSQL.
Что касается защиты базы данных PostgreSQL, пользователи должны использовать разумные разрешения для любых учётных данных PostgreSQL, используемых пользователем ClickHouse, — а это означает ограниченные разрешения, область действия, а не напрямую стандартные учётные данные «postgres».
Таким образом, это всё ещё применимо к последним версиям ClickHouse на момент написания этого отчёта:
Похоже, что исправление вряд ли будет выпущено, а это означает, что будут затронуты все текущие и, возможно, будущие версии ClickHouse.