Статья

wp2shell: захват сайта одним запросом. Что делать прямо сейчас

В ядре WordPress нашли цепочку из двух уязвимостей: один анонимный запрос — и сервер чужой. Плагины ни при чём. Как проверить свой сайт и что делать, если уже взломали.

7 минут чтенияЦТБ Центр, Разработка и консалтинг

17 июля 2026 года WordPress выпустил внеочередное обновление. Через несколько часов после его публикации начались массовые атаки: исследователи сравнили старый и новый код, поняли, что именно чинили, и выложили рабочий эксплойт. Сейчас идёт сплошное сканирование интернета.

Уязвимость назвали wp2shell. Если у вас сайт на WordPress и вы не обновлялись после 17 июля — читайте дальше, это про вас.

Что именно случилось

Это не дыра в плагине и не проблема кривой темы. Это две ошибки в самом ядре WordPress, которые работают в связке:

НомерЧто это
CVE-2026-63030Путаница в обработке групповых запросов к REST API по адресу /wp-json/batch/v1. Позволяет обойти проверку прав. Появилась в версии 6.9.
CVE-2026-60137SQL-инъекция в параметре author__not_in. Присутствует начиная с версии 6.8.

По отдельности каждая неприятна. Вместе они дают то, что на языке безопасности называется худшим из возможного: выполнение произвольного кода без авторизации. Атакующему не нужна учётная запись, не нужен пароль, не нужно ничего знать о вашем сайте. Достаточно одного анонимного запроса.

И ещё одна деталь, которая ломает привычную логику защиты: атака работает на чистой установке. Без плагинов, без сторонней темы, без единой сомнительной строчки чужого кода. Совет «ставьте поменьше плагинов» здесь не помогает вообще.

Ваша версия под ударом?

ВерсияСтатус
7.0.0 — 7.0.1Уязвима, полная цепочка
6.9.0 — 6.9.4Уязвима, полная цепочка
6.8.x до 6.8.6Уязвима SQL-инъекция, полная цепочка не работает
7.0.2, 6.9.5, 6.8.6Исправлено

Версию видно в админке на странице «Консоль». Через консоль сервера:

wp core version

Первое действие: обновиться

Не «на неделе», не «после согласования». Эксплойт публичный, сканирование идёт прямо сейчас, взлом занимает секунды.

wp core update
wp core update-db

Если обновление ломает сайт — это неприятно, но это меньшая из двух проблем. Сломанный сайт вы почините. Взломанный сервер придётся считать чужим целиком.

Если обновиться прямо сейчас нельзя

Бывает: старая тема, привязанные интеграции, согласование через три отдела. Тогда закройте доступ к уязвимому адресу на уровне сетевого экрана или CDN.

Но есть ловушка, на которой уже погорели. Групповой запрос можно передать не только в адресе, но и в теле POST-запроса. Правило, которое проверяет только адрес, обходится тривиально. Блокировать нужно всё сразу:

  • /wp-json/batch/v1 в пути
  • ?rest_route=/batch/v1 в параметрах
  • rest_route=/batch/v1 в теле POST-запроса
  • варианты вида /index.php?rest_route=/batch/v1

Это временная мера. Она даёт время до обновления, а не заменяет его.

Как понять, что вас уже взломали

Обновление закрывает дверь, но не выгоняет того, кто вошёл раньше. Проверять нужно обязательно — даже если сейчас всё выглядит нормально.

Следы в логах

Ищем обращения к групповому адресу:

grep -Ei "batch/v1|rest_route=/?batch" /var/log/nginx/access.log*

Если такие строки есть — смотрим, была ли среди них попытка инъекции:

grep -Ei "batch/v1|rest_route=/?batch" /var/log/nginx/access.log* \
  | grep -Ei "author.?exclude|UNION|SLEEP\(|SUBSTRING"

И попытки добраться до пользователей и плагинов:

grep -Ei "wp/v2/(users|plugins)" /var/log/nginx/access.log* \
  | grep -Ei "administrator|roles"

Известные признаки

Исследователи опубликовали приметы конкретных инструментов, которыми пользуются атакующие:

  • Идентификаторы браузера wp2shell-check/1.0 и wp2shell-poc/1.0 в логах
  • Маркеры WP2SHELL_OUT_START и WP2SHELL_OUT_END в ответах сервера
  • Адреса, замеченные в полной цепочке: 129.121.77.134, 91.202.233.61, 125.164.233.50

Отсутствие этих примет ничего не доказывает: инструменты меняются, адреса ротируются. Их наличие доказывает многое.

Следы в файлах

Свежие PHP-файлы там, где их быть не должно:

find /var/www/html -name "*.php" -mtime -7 -print

Признаки веб-оболочки в загрузках и плагинах:

grep -RilE "eval\(|base64_decode\(|system\(|shell_exec\(" \
  /var/www/html/wp-content/uploads \
  /var/www/html/wp-content/plugins

Отдельно проверьте каталог wp-content/mu-plugins. Плагины оттуда подключаются автоматически и не отображаются в списке плагинов в админке — любимое место для закрепления:

ls -la /var/www/html/wp-content/mu-plugins/

Целостность ядра и список администраторов

wp core verify-checksums
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

Смотрите на дату регистрации. Администратор, появившийся после 17 июля и не заведённый вами, — это ответ.

Если следы нашлись

Здесь придётся сказать неприятное. При выполнении произвольного кода скомпрометированным считается весь сервер, а не только сайт. Атакующий мог прочитать конфигурацию, забрать пароль базы, поставить закладку вне каталога сайта.

Порядок действий:

  1. Снять сайт с публикации. Заглушка лучше, чем сайт, раздающий вредонос вашим клиентам.
  2. Сменить все секреты: пароль базы, соль в wp-config.php, ключи внешних сервисов, пароли администраторов. Все, а не только те, что кажутся затронутыми.
  3. Восстановиться из резервной копии, сделанной до взлома. Не «почистить» — восстановиться. Найти все закладки в чужом коде вручную невозможно, а пропустить одну достаточно, чтобы всё повторилось.
  4. Обновить WordPress на восстановленной копии, до того как открывать её наружу.
  5. Проверить, что копия чистая, теми же командами выше.
  6. Открыть сайт и наблюдать за логами ближайшие дни.

Если резервной копии до взлома нет — это отдельный разговор, и он тяжелее. Проверьте, нет ли снимка диска у хостинга: там копии часто хранятся дольше, чем в панели управления сайтом.

Что с этим делать по-хорошему

Дальше — мысль, которая нам кажется важнее самой инструкции.

Соблазн сделать из этой истории вывод «WordPress дырявый, переходите на заказную разработку» большой. Мы этот вывод делать не будем, потому что он неверный.

Дыры находят везде. В Laravel, в Next.js, в Django, в чём угодно — мы регулярно обновляем зависимости на своих проектах именно поэтому. WordPress просто заметнее: на нём работает такая доля интернета, что любая ошибка в ядре сразу становится массовым событием.

Разница не в платформе. Разница в том, есть ли человек, который в течение суток узнает о критическом обновлении и применит его.

Сайт на заказной разработке с необновлённым фреймворком уязвим ровно так же. А сайт на WordPress, за которым следят, обновился 17 июля вечером и ничего не заметил.

Вопрос, который стоит себе задать после этой истории, звучит не «на чём у нас сайт», а:

  • Кто узнает о критическом обновлении и за сколько часов?
  • Есть ли резервные копии, и восстанавливались ли вы из них хоть раз? Копия, которую ни разу не разворачивали, — это надежда, а не копия.
  • Сколько сайт может лежать без последствий для бизнеса, и знаете ли вы это число?

Если ответов нет — история с wp2shell закончилась удачно. В следующий раз может не повезти.

Коротко

  • Обновитесь до 7.0.2, 6.9.5 или 6.8.6. Сегодня.
  • Проверьте логи и файлы — обновление не выгоняет того, кто вошёл раньше.
  • Нашли следы — считайте скомпрометированным весь сервер, меняйте все секреты и восстанавливайтесь из копии.
  • Не можете обновиться сейчас — закройте batch/v1, включая передачу в теле POST-запроса.

Нужна помощь с проверкой или восстановлением — напишите нам. Разберёмся, что произошло, и приведём в порядок.

БезопасностьWordPressЗаказчику

Следующий шаг

Нужна такая же работа?