Один GET-запрос — и ваши ключи от почты утекли: CVE-2026-4020 в Gravity SMTP
Один GET-запрос — и ваши ключи от почты утекли: CVE-2026-4020 в Gravity SMTP
Представьте: вы установили SMTP-плагин для WordPress, подключили SendGrid или Amazon SES, проверили что письма уходят — и забыли. Плагин работает, всё нормально. Тем временем любой желающий, даже без аккаунта на вашем сайте, отправляет один HTTP GET-запрос и получает 365 КБ JSON с вашими API-ключами, OAuth-токенами, DKIM-конфигурацией, списком всех установленных плагинов с версиями и структурой базы данных. Без логина. Без брутфорса. Без эксплойта. Просто запрос к открытому endpoint.
Именно это происходит с сайтами, на которых установлен Gravity SMTP версии 2.1.4 и ниже. Уязвимость получила идентификатор CVE-2026-4020, CVSS 7.5 (High), CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor. За этой оценкой стоит полный дамп credentials вашего почтового сервиса, готовый к использованию без какой-либо дополнительной подготовки. Wordfence уже заблокировал более 17 миллионов попыток эксплуатации.
ЧТО ТАКОЕ GRAVITY SMTP
Gravity SMTP — коммерческий WordPress-плагин от компании RocketGenius, той же команды что создала Gravity Forms. Плагин решает типичную задачу: WordPress по умолчанию отправляет почту через PHP mail(), что не работает на большинстве хостингов — письма либо не доходят вообще, либо падают в спам, потому что сервер не авторизован отправлять почту от имени домена. Gravity SMTP заменяет этот сломанный механизм на подключение к профессиональному почтовому сервису — SendGrid, Mailgun, Amazon SES, Google Workspace, Brevo, Postmark, Resend, Zoho и другим. Плагин установлен примерно на 100 000 сайтов.
Именно это и делает его привлекательной целью. SMTP-плагин по своей природе — это хранилище ключей. Он знает всё что нужно для отправки почты от имени вашего домена: API-ключи, OAuth-токены, SMTP-логины и пароли, DKIM-конфигурацию. Без этих данных плагин не может работать, поэтому они хранятся прямо в WordPress — в базе данных и в конфигурации плагина. Это нормальная архитектура, так работают все SMTP-плагины.
КАК РАБОТАЕТ УЯЗВИМОСТЬ
Когда WordPress-плагин регистрирует REST API endpoint, он должен указать permission_callback — функцию-охранника, которая решает: этот запрос пропустить или отклонить. Вернула true — проходи. Вернула false — получи 401. Вся система контроля доступа держится на этой одной функции.
В Gravity SMTP кто-то написал охранника, который пропускает всех. Без исключений. Endpoint /wp-json/gravitysmtp/v1/tests/mock-data зарегистрирован с permission_callback, который возвращает true безусловно — без проверки сессии, роли, nonce или чего угодно ещё. Добавь к запросу параметр ?page=gravitysmtp-settings, и плагин послушно вызовет внутренний метод register_connector_data(), который соберёт полный System Report и отдаст его в ответе. Всё что плагин знает о системе — на блюдечке.
Эксплуатация выглядит так: одна команда curl, никаких специальных инструментов, никакого предварительного знания о цели:
curl "https://example.com/wp-json/gravitysmtp/v1/tests/mock-data?page=gravitysmtp-settings"
В ответ приходит JSON объёмом ~365 КБ, содержащий API-ключи и OAuth-токены для всех настроенных почтовых интеграций, SMTP-логины и пароли, DKIM-токены, версию PHP, версию веб-сервера, полный список установленных плагинов с версиями, активную тему, имена таблиц базы данных и версию MariaDB/MySQL.
Затронуты все версии Gravity SMTP от 2.1.4 и ниже. Исправление вышло в версии 2.1.5 — 17 марта 2026 года, до публичного раскрытия уязвимости. Патч добавил корректную проверку прав доступа в permission_callback.
ХРОНОЛОГИЯ
RocketGenius исправила уязвимость в марте 2026 года — тихо, одной строкой в коде, без упоминания в changelog и без единого письма пользователям. Логика понятна: не привлекать внимание до того, как большинство обновится. Но у платных плагинов автообновления часто отключены — люди боятся что обновление сломает продакшн. В итоге тысячи сайтов так и остались на 2.1.4, даже не подозревая что патч уже существует.
В начале мая администраторы в r/WordPress начали жаловаться на странное: SendGrid-аккаунты заблокированы за спам, Mailgun-счета выросли втрое за ночь, у некоторых провайдеры сами ротировали ключи с пометкой «подозрительная активность». CrowdSec зафиксировал первую реальную эксплуатацию 27 мая, а к 1 июня классифицировал трафик как «фоновый шум» — то есть уязвимость уже вошла в автоматизированные сканеры, которые методично перебирают WordPress-сайты без участия человека.
19 июня 2026 года вышел официальный advisory. К тому дню счётчик перевалил за 17 миллионов заблокированных попыток. Пик — 7 июня, больше 4 миллионов запросов за одни сутки. Три месяца между патчем и публичным раскрытием оказались не защитой, а временным преимуществом для тех, кто нашёл баг раньше Wordfence.
ПОЧЕМУ ЭТО ВАЖНО
Два сайта потеряли SendGrid-аккаунты. Оба работали на Gravity SMTP, оба подключили платные SendGrid-планы для транзакционной почты. Через 36 часов после того как их endpoint отдал credentials сканеру, SendGrid заблокировал аккаунты за рассылку спама. Восстановление заняло восемь дней и потребовало письменного инцидент-репорта. Восемь дней без транзакционной почты — без подтверждений заказов, без писем о смене пароля, без уведомлений. Для интернет-магазина это не «инцидент безопасности», это операционный коллапс.
CVSS 7.5 — это High, и оценка заслуженная: атака не требует ничего, ноль условий для входа, ноль привилегий, один запрос. Но то, что атакующий получает в ответ — это не просто «утечка информации» в абстрактном смысле, а готовый инструментарий для нескольких независимых векторов атаки одновременно.
Скомпрометированный API-ключ SendGrid или Mailgun даёт атакующему возможность отправлять письма от вашего домена. Не подделанные — настоящие, через ваш аккаунт, с вашими credentials. Такие письма проходят SPF-проверку, потому что отправлены через авторизованный сервис. Они проходят DKIM-проверку, потому что подписаны вашим ключом. С точки зрения любого почтового фильтра и получателя — это легитимная почта от вашего домена. Именно такую инфраструктуру арендуют фишинговые группы за большие деньги. Здесь она достаётся бесплатно одним curl-запросом.
Параллельно с этим атакующий получает полную карту вашего сайта. Список установленных плагинов с точными версиями — это база для выбора следующего вектора атаки. Есть устаревший плагин с известным CVE? Атакующий видит его сразу. Версия PHP, версия MariaDB, имена таблиц в базе данных — всё это снижает порог для последующей эксплуатации любой другой уязвимости, которую атакующий найдёт или уже имеет в арсенале.
Отдельно стоит поговорить о DKIM. Большинство администраторов после инцидента сбрасывают API-ключи — и считают что всё чисто. Но если в дампе были DKIM-токены, просто смена API-ключей не закрывает проблему полностью. DKIM-ключ привязан к DNS-записи вашего домена, а не к аккаунту в почтовом сервисе. Если атакующий успел скопировать приватный DKIM-ключ, он технически может продолжать подписывать письма вашей доменной подписью — даже после того, как вы отозвали все API-ключи. Решение — ротация DKIM-selector: создать новую DNS-запись с новым ключом, а старый selector деактивировать у провайдера.
ЧТО ДЕЛАТЬ
Первый шаг — проверить установлен ли плагин и какая версия используется. В консоли WordPress это видно в разделе Plugins → Installed Plugins. Через WP-CLI проверка занимает секунду:
wp plugin get gravity-smtp --field=version
Если версия 2.1.4 или ниже — обновить немедленно:
wp plugin update gravity-smtp
После обновления убедитесь что патч работает. Запрос к endpoint должен теперь возвращать 401 или 403, а не JSON с данными:
curl -o /dev/null -s -w "%{http_code}" \
"https://example.com/wp-json/gravitysmtp/v1/tests/mock-data?page=gravitysmtp-settings"
Если сайт работал на уязвимой версии — считайте все credentials скомпрометированными и ротируйте их независимо от того, нашли вы следы атаки в логах или нет. Атакующие не оставляют следов в WordPress — они просто делают GET-запрос к открытому endpoint и получают данные. Следы есть только в access-логах веб-сервера. Проверьте их на наличие запросов к уязвимому endpoint за последние недели — активное сканирование началось в мае:
grep "gravitysmtp/v1/tests/mock-data" /var/log/nginx/access.log
# или для Apache:
grep "gravitysmtp/v1/tests/mock-data" /var/log/apache2/access.log
Если записи есть — сайт почти наверняка был запрошен сканером. Дата первого попадания в логах покажет с какого момента считать credentials скомпрометированными. Ротируйте все API-ключи почтовых интеграций в настройках соответствующих сервисов: SendGrid, Mailgun, Amazon SES, Google OAuth, Brevo — всё что было подключено в Gravity SMTP. Если использовался DKIM — создайте новый selector в настройках провайдера, обновите TXT-запись в DNS, старый selector деактивируйте. Это важно: смена API-ключа без смены DKIM-selector оставляет атакующему возможность подписывать почту вашим доменом.
И пока вы не закрыли эту дыру — включите автообновления. WordPress умеет автоматически обновлять плагины, но для платных плагинов это часто отключено: администраторы боятся что обновление сломает кастомизации. Страх понятный, но цена — именно такие ситуации, когда патч лежит три месяца, а сайт остаётся уязвимым. Включить автообновления через WP-CLI:
wp plugin auto-updates enable gravity-smtp
Или для всех плагинов сразу — чтобы не выбирать вручную какой важный, а какой нет:
wp plugin auto-updates enable --all
Если обновление невозможно прямо сейчас — например, сайт управляется третьей стороной и требует согласования — заблокируйте endpoint на уровне nginx как временную меру:
location ~* /wp-json/gravitysmtp/ {
deny all;
return 403;
}
ВЫВОДЫ
CVE-2026-4020 — хрестоматийный пример CWE-200: одна строка кода в permission_callback превращает SMTP-плагин в публичный дамп credentials. CVSS 7.5 (High), активная эксплуатация, 17 миллионов заблокированных попыток — и всё это за уязвимость, которую не нужно эксплуатировать в буквальном смысле. Доступ к SMTP-аккаунту с хорошей репутацией домена стоит на чёрном рынке дороже, чем многие RCE-эксплойты.
Если Gravity SMTP установлен — обновите до 2.1.5, проверьте логи, ротируйте credentials и DKIM. Если не установлен — убедитесь что ваш SMTP-плагин вообще не регистрирует публичные endpoint с данными. Это касается любого плагина, который хранит API-ключи: от SMTP до интеграций с payment-провайдерами и CRM-системами. REST API в WordPress — удобный инструмент, но каждый незащищённый endpoint это потенциальная точка утечки.
Патч вышел в марте. Сайты ломают в июне. Три месяца разрыва — это не вина разработчика, который баг закрыл. Это цена тихого патча без уведомлений и отключённых автообновлений. Следующий раз это будет другой плагин, другой endpoint, те же последствия. Единственное что меняет уравнение — автообновления включены, или вы сами следите за security-релизами плагинов которые хранят ваши ключи.
