
Docker-лаборатория, воспроизводящая CVE-2026-10795: обход аутентификации UpdraftPlus UpdraftCentral, объединённый с установкой плагина для получения RCE. Включает уязвимые/исправленные цели, PoC-эксплойт и пошаговый разбор исходного кода.
Этот репозиторий содержит локальную Docker-лабораторию для воспроизведения и проверки CVE-2026-10795, уязвимости неаутентифицированного обхода аутентификации, затрагивающей плагин WordPress UpdraftPlus через его удаленный коммуникационный слой UpdraftCentral.
Уязвимое поведение существует в потоке обработки RPC-сообщений UpdraftCentral. В уязвимых версиях поддельное RPC-сообщение с format=1 может обойти проверку подписи, запустить путь неудачного расшифрования RSA и все равно добраться до симметричного расшифрования с предсказуемым поведением нулевого ключа/нулевого IV. Это позволяет принять и выполнить сфабрикованное зашифрованное RPC-сообщение как команду UpdraftCentral.
Эта лаборатория сравнивает две версии UpdraftPlus:
| Сервис | Версия UpdraftPlus | Назначение | URL |
|---|---|---|---|
vuln | 1.26.4 | Уязвимая цель для сравнения | http://127.0.0.1:8081 |
patched | 1.26.5 | Исправленная цель для сравнения | http://127.0.0.1:8082 |
Демонстрируемая цепочка:```text Unauthenticated attacker → forged UpdraftCentral RPC request → format=1 signature verification bypass → failed RSA decrypt not rejected in vulnerable version → predictable zero-key/zero-IV decrypt path → forged JSON RPC command accepted → privileged UpdraftCentral command dispatch → plugin.upload_plugin → install and activate marker plugin → hard-coded /usr/bin/id proof endpoint
Основная уязвимость — обход аутентификации. Лабораторная работа демонстрирует, что этот обход может быть объединён в цепочку для достижения воздействия типа RCE при наличии привилегированного состояния ключа UpdraftCentral, поскольку UpdraftCentral предоставляет легитимные команды управления плагинами, которые могут устанавливать и активировать плагины WordPress.
Это не уязвимость прямого внедрения команд. Доказательство выполнения кода основано на злоупотреблении функцией установки аутентифицированных плагинов после обхода границы аутентификации RPC.
Данная лабораторная работа предназначена только для контролируемого локального исследования, понимания исходного кода и демонстрации в портфолио.
## Подтверждённые факты
| Утверждение | Доказательство | Как проверить в этой лабораторной работе |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| UpdraftPlus 1.26.4 уязвим в этой лабораторной работе. | Уязвимый сервис принимает поддельное RPC-сообщение `format=1` и отправляет `plugin.upload_plugin`. | Запустить `python3 poc/poc.py --url http://127.0.0.1:8081`. |
| UpdraftPlus 1.26.5 блокирует поддельное сообщение в этой лабораторной работе. | Исправленный сервис не возвращает тело ответа RPC и не отправляет поддельную команду. | Запустить `python3 poc/poc.py --url http://127.0.0.1:8082`. |
| Проблема заключается в обходе аутентификации в слое RPC UpdraftCentral. | Неаутентифицированный запрос RPC с подделкой может достичь отправки команды в уязвимой версии. | Сравнить поведение `--ping` между портами `8081` и `8082`. |
| Лабораторная работа не устанавливает плагин-маркер заранее. | Установка включает только WordPress, UpdraftPlus и локальное состояние ключа UpdraftCentral. | Проверить `/wp-json/cve-lab/v1/id` до запуска PoC. |
| PoC устанавливает плагин-маркер через поддельный RPC. | PoC отправляет `plugin.upload_plugin` с ZIP-нагрузкой плагина в поле данных RPC. | Запустить PoC, затем запросить `/wp-json/cve-lab/v1/id`. |
| Уязвимая цель достигает воздействия типа RCE. | Плагин-маркер предоставляет жёстко закодированную конечную точку, возвращающую вывод `/usr/bin/id`. | Уязвимая цель возвращает `uid=33(www-data) gid=33(www-data)`. |
| Исправленная цель не устанавливает плагин-маркер. | Конечная точка маркера возвращает `404 rest_no_route` на исправленном сервисе. | Запустить PoC против `http://127.0.0.1:8082`. |
| Лабораторная работа требует состояния ключа UpdraftCentral. | Отправка UpdraftCentral зависит от локальной записи ключа и связанных метаданных. | Изучить `scripts/setup-wordpress.sh`. |
## Допущения и неизвестные
В данной лабораторной работе намеренно создаётся локальное состояние ключа UpdraftCentral для воспроизведения условия сайта, где настроено удалённое управление.
Созданное состояние ключа является предварительным условием лабораторной работы, а не самой уязвимостью. Оно позволяет лабораторной работе последовательно задействовать уязвимый путь разбора и дешифрования RPC.
Лабораторная работа не утверждает, что каждая установка UpdraftPlus немедленно эксплуатируема. Продемонстрированная цепочка зависит от наличия локальной записи ключа UpdraftCentral, связанной с привилегированным пользователем WordPress.
Лабораторная работа демонстрирует контролируемое воздействие типа RCE путём установки плагина-маркера, который предоставляет жёстко закодированную доказательную конечную точку `/usr/bin/id`. Она не предоставляет универсальный веб-шелл, параметр произвольного выполнения команд, реверс-шелл, механизм сохранения, кражу учётных данных или внешний обратный вызов.
PoC ограничен только локальными целями и по умолчанию отклоняет нелокальные имена хостов.
## Краткое описание первопричины
Первопричиной является неправильная проверка RPC-сообщений UpdraftCentral в уязвимых версиях UpdraftPlus.
Уязвимый поток RPC принимает сообщение `format=1`. Путь `format=1` не требует такой же проверки подписи, как более новые форматы сообщений.
Проблема на высоком уровне:```text
format=1 message
→ signature verification is bypassed
→ RSA decrypt of the symmetric key can fail
→ failed decrypt result is not rejected
→ false is passed into the symmetric cipher as a key
→ phpseclib normalizes this into a predictable null key path
→ attacker-controlled encrypted JSON can decrypt successfully
→ command is dispatched
При уязвимом поведении расшифровка RSA может возвращать:```text false
Вместо отклонения этого неудачного результата дешифрования уязвимый поток продолжается и передает значение в уровень симметричного дешифрования.
Эффективная уязвимая схема:```php
$sym_key = $rsa->decrypt($sym_key);
$rij->setKey($sym_key);
$decrypted = $rij->decrypt($ciphertext);
Проблема в том, что $sym_key не проверяется перед использованием.
Когда $sym_key равен false, настройка шифра следует предсказуемому поведению с нулевым ключом/нулевым IV. Это позволяет создать зашифрованный RPC-полезный груз, используя известный нулевой ключ и нулевой IV.
Патч добавляет проверку перед использованием симметричного ключа:```php if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) { return false; }
Это изменяет границу доверия.
До патча:```text
failed RSA decrypt result could still reach symmetric decrypt
После патча:```text failed RSA decrypt result is rejected before command dispatch
Вот почему уязвимая служба выполняет поддельную RPC-команду, а исправленная — нет.
## Почему обход аутентификации может привести к выполнению кода