
Анализ и сквозная реализация исправленной wordpress RCE уязвимости - CVE-2026-60137 и CVE-2026-63030

Все PoC используют одни и те же две уязвимости — путаницу в пакетном маршруте REST (CVE-2026-63030) и
SQL-инъекцию author__not_in (CVE-2026-60137) — с одинаковой двойной вложенной формой пакета.
Разница между ними заключается в выбранном пути RCE, предусловиях окружения
и безопасных настройках по умолчанию. В этом документе конкретно указано, где в этом ландшафте
находится реализация из данного репозитория.
check не отправляет SQL-полезную нагрузку, если не указано;
весь трафик может содержать тег атрибуции; всё, что команда shell записывает
на цель, автоматически удаляется после завершения. См. §3.[1] Только временная/слепая как канал чтения; примитив поддельного поста через UNION существует внутри
моста, но не предоставляется как оракул извлечения.
[2] Наивный зонд доступности (0) UNION SELECT …») молча отбрасывается при гидратации кеша объектов, available()возвращает false, и весь мост без аутентификации прерывается — см. §1. [3] В собственном README проекта указано «нет постоянного кеша объектов (Redis/Memcached)» в разделе «Предусловия». [4] Публичный вариант, отзеркаленный на Sploitus (ссылка ниже): слепое чтение плюс дропперINTO OUTFILEв качестве шага RCE, с использованиемper_page=-1в полях категорий. [5] Путь RCE через OUTFILE не зависит от рендеринга поддельных постов, поэтому кеши объектов не блокируют его — блокируют привилегия MySQLFILEи общая доступная для записи директория. Управляемый хостинг почти никогда не даётFILEпользователю БД WordPress, иsecure_file_priv` обычно установлен.
Примитив поддельного поста через UNION зависит от того, как WP_Query возвращает строки:
wp_posts; внедрённая строка через UNION
сразу становится WP_Post. Подделка отображается.На хостах с постоянным кешем объектов заполненный базовый набор результатов переводит WP_Query в
режим разделения. Стандартный зонд, используемый публичными PoC —
0) UNION SELECT <поддельная строка> -- -
— оставляет базовый набор заполненным (post_author NOT IN (0) соответствует каждой строке), поэтому за
кешем объектов поддельная строка исчезает: зонд доступности даёт ложноотрицательный результат, available()
возвращает false, и весь мост без аутентификации сообщается как «мёртвый» на хосте, который на самом деле
полностью эксплуатируем. Публичный унификатор документирует ту же границу, указывая «нет постоянного кеша объектов»
как жёсткое предусловие.
Этот репозиторий вместо этого опустошает базовый набор:
1) AND 1=0 UNION ALL SELECT <поддельная строка> -- -
При нулевом количестве базовых строк поддельная строка является единственной строкой; запрос остаётся в режиме
полных строк; гидратация никогда не выполняется. Одно внедрённое ключевое слово (AND 1=0) — вот вся разница
между «канал UNION мёртв» и «полный RCE без аутентификации» на хостах с кешем объектов — а это
большинство управляемых продакшн-окружений WordPress. Диагностика, матрица зондов
(per_page × форма инъекции).
Примечание по области действия: канал слепого/временного чтения не чувствителен к кешу объектов (подсчёт строк в SQL не включает гидратацию поддельных постов), поэтому слепое чтение каждого PoC работает везде. Что кеш объектов убивает в других PoC, так это именно зависимую от UNION часть: инлайн-извлечение и мост SQLi → админ.
Второй, связанный урок, задокументированный в тематическом исследовании: когда оба канала работают, считайте инлайн-чтение через UNION авторитетным — оракул временных запросов на продакшне давал битовые перевороты под джиттером для значения, которое инлайн-чтение установило однозначно.
Три пути RCE без аутентификации существуют среди публичных PoC:
Этот репозиторий реализует мост: ему не нужны привилегии базы данных, выходящие за рамки того, что уже есть у WordPress,
он работает, когда уровни БД и веба ничего не разделяют, и не оставляет файлов для
зависимости от привилегии FILE. Оборотная сторона — сложность — мост представляет собой отравленный граф из семи постов,
и именно здесь скрывался ложноотрицательный результат §1 по кешу объектов.
Разработано для запуска против продакшн-систем с авторизацией, а не только в лабораториях:
check по умолчанию не наносит вреда — пассивный отпечаток плюс безвредный пакет-маркер;
SQL-полезная нагрузка не отправляется, если не указан --confirm-sqli. После применения патча
исчезающий триплет маркеров работает как валидация исправления.--user-agent для каждой команды, чтобы весь трафик эксплойта
был идентифицируем в логах (практическое правило для работы, которое публичные инструменты не устанавливают по умолчанию).author_exclude → author__not_in, примитив поддельного WP_Post через UNION и
концепция моста-кастомайзера — всё это публичные техники (наследственность признаётся ниже).INTO OUTFILE), отзеркален на Sploitus —
https://sploitus.com/exploit?id=7CD079AD-E27B-5C54-A696-60635BFDB241| Возможность | Этот репозиторий | Icex0/wp2shell-poc | sergiointel/wp2shell-poc | 0xsha/wp2shell | Вариант OUTFILE [4] |
|---|
| Чтение через слепую/временную SQLi без аутентификации | да | да | да (временная) | да | да |
| Инлайн-чтение через UNION (1 запрос/значение) | да | да | - [1] | - [1] | - |
| Чтение на основе ошибок (EXTRACTVALUE) | да | да | - | - | - |
| Канал UNION сохраняется при постоянном кеше объектов | да (пустая база) | нет — зонд даёт ложноотрицательные [2] | нет документации | нет — документированное предусловие [3] | н/п [5] |
| RCE без аутентификации без взлома | да (мост SQLi → админ) | да (тот же мост) | да (оригинал моста) | да (тот же мост) | да, через INTO OUTFILE [5] |
| Дополнительные предусловия для RCE | нет (кроме стандартной установки) | нет (на хостах без кеша объектов) | нет (то же) | нет (то же) | привилегия MySQL FILE + общий путь, доступный для записи mysqld и веб-серверу |
| Ненарушающая проверка/валидация патча | да (триплет маркеров; по умолчанию без нагрузки) | да | нет | да (block_cannot_read) | да (пакет-маркер) |
| Тегирование атрибуции/User-Agent | да, для всех команд | нет | нет | флаг транспорта | нет |
| Автоматическая очистка (веб-шелл + созданный админ) | да | да | нет документации | только веб-шелл с токеном-шлюзом | дроппер удалён [5] |
| Руководство по обнаружению для синих команд | да, по результатам реального запуска | нет | нет | лабораторная матрица | заметки по смягчению |
| Зависимости | только stdlib | только stdlib | один файл | только stdlib, один файл | пакет Python ≥3.10 |
| Путь | Используется | Дополнительные предусловия |
|---|
Мост SQLi → админ (подделка строк oEmbed/changeset/nav → POST /wp/v2/users → вход → загрузка плагина) | этот репозиторий, sergiointel (оригинал), Icex0, 0xsha | ничего, кроме стандартной установки |
Дроппер INTO OUTFILE (запись PHP-файла через SQLi, получение шелла) | Вариант OUTFILE [4] | привилегия MySQL FILE, разрешающий secure_file_priv, и директория, доступная для записи mysqld и обслуживаемая веб-сервером |
Восстановление хеша → взлом → вход (дамп user_pass, взлом офлайн, затем загрузка плагина) | все (как запасной вариант) | хеш bcrypt должен быть реально взломан ($wp$2y$, hashcat -m 35500) — медленно, часто безуспешно |