Главная / wordpress / Уязвимость в WordPress 6.9.0 и выше (до 7.0.2)

Уязвимость в WordPress 6.9.0 и выше (до 7.0.2)

Автор: | 07.08.2026

Массовые взломы сайтов на WordPress в последнее время стали обыденностью, благодаря изменениям в движке, которые предположительно, должны были облегчить взаимодействие через rest api для разработчиков.

Недавно секурные ресурсы затрубили о тревоге, вордпресс экстренно выпустил обновление 7.0.2 призванный закрыть «дыру» и следом за ним сразу 7.0.3. На момент написания статьи 7.0.3 не имела подробной информации о закрытых проблемах, поэтому пройдёмся по 7.0.2, которое было призвание решить основную проблему. Речь про sql-инъекцию + пакетную обработку запросов rest api, которые могли обходить безопасность. В паре эти две уязвимости давали злоумвшленникам возможность полного захвата контроля над сайтом с вытекающими последствиями: создание новых администраторов и изменение+создание новых исполняемых файлов .php, которые обеспечивало персистенс резиденс вредоносных скриптов, маскирующихся под файлы wp.

На одном из сайтов у меня развёлся целый зоопарк скриптов, которые судя по комментариям в коде были написаны AI и частично зашифрованы, через EVAL и Base64. Скрипты даже пытались дотянуться до других сайтов, расположенных на том же хосте в обход openbase dir. Кроме того они и в бд делали записи. Пришлось делать откат файлов и бд. Если у вас нет нескомпрометированного бэкапа, то будет очень грустно.

Далее комментарий от аи.

Если посмотреть именно на исходный код, а не только на описание CVE, становится понятно, почему ошибка оказалась настолько серьезной.

Первая уязвимость — author__not_in

Параметр author__not_in предназначен для исключения авторов из выборки.

Нормальное использование:

new WP_Query([
    'author__not_in' => [3, 8, 15]
]);

В итоге WordPress строит SQL примерно такого вида:

... AND post_author NOT IN (3,8,15)

Где была ошибка

Разработчики предполагали, что значение всегда будет массивом.

В коде было что-то концептуально похожее на:

if ( is_array( $author__not_in ) ) {
    $author__not_in = array_map( 'absint', $author__not_in );
}

Если же значение приходило не массивом, а строкой, то преобразование absint() вообще не выполнялось. Затем это значение попадало в построитель SQL практически без необходимой очистки.


Почему обычный WordPress не всегда был уязвим

Сам WordPress редко передает пользовательский ввод напрямую в WP_Query.

Однако многие плагины делают примерно так:

$query = new WP_Query([
    'author__not_in' => $_GET['authors']
]);

или

$_POST['authors']

Если разработчик не проверял тип данных, возникала возможность SQL-инъекции. Поэтому уязвимость называют facilitated SQL injection — ядро создавало опасную ситуацию, но обычно требовалось, чтобы плагин или тема передали недоверенные данные.


Вторая уязвимость — REST Batch API

Именно она сделала возможной атаку без участия уязвимого плагина.

В WordPress 6.9 появился механизм пакетных REST-запросов.

Вместо

POST /wp-json/...
POST /wp-json/...
POST /wp-json/...

можно было отправить

{
  "requests": [
      {...},
      {...},
      {...}
  ]
}

и сервер выполнял всё за один запрос.

Ошибка заключалась в том, что во время обработки пакета происходила путаница между маршрутом (route) и обработчиком (handler).

Из-за этого для внутренних запросов могли применяться не те проверки безопасности, которые должны были срабатывать. Исследователи называют это route/handler confusion.


Как выглядела цепочка атаки

Самая опасная особенность заключалась именно в объединении двух ошибок:

  1. REST Batch API позволял передать данные, обходя ожидаемую валидацию.
  2. Эти данные попадали в WP_Query.
  3. author__not_in не очищался должным образом.
  4. Выполнялась SQL-инъекция.
  5. Затем злоумышленник получал возможность изменить данные сайта и, используя вторую часть цепочки, добиться выполнения произвольного PHP-кода. Patchstack независимо подтвердила возможность полного захвата сайта и сообщила об активной эксплуатации вскоре после выхода исправлений.

Почему оценка CVSS сначала была невысокой

Интересно, что первоначально WPScan оценил SQL-инъекцию примерно в 5.9 (Medium), потому что рассматривал её отдельно. Позже CISA повысила оценку до 9.1 (Critical), поскольку стало ясно, что в сочетании с REST Batch API она приводит к полному захвату сайта и уже активно эксплуатируется.


Что изменили разработчики

Исправление оказалось небольшим, но принципиальным:

  • значение author__not_in теперь приводится к безопасному виду независимо от того, пришёл массив или нет;
  • в REST Batch API устранена логическая ошибка обработки маршрутов, из-за которой можно было обходить проверки безопасности.

Вывод

Срочно обновляйтесь, если у вас версия WordPress выше 6.9.0 и ниже 7.0.2. Если вы уже словили вирус то лучше откатится на чистый бэкап. Если такой возможности нет то придется долго и нудно вычищать вирус (не только из вордпресса, если он работает под пользователем с широкими правами)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *