{"id":1891,"date":"2026-05-04T12:40:41","date_gmt":"2026-05-04T10:40:41","guid":{"rendered":"https:\/\/darioiannascoli.it\/blog\/cve-2026-5324-brizy-xss-waf-virtual-patching-maggio-2026\/"},"modified":"2026-05-04T12:40:41","modified_gmt":"2026-05-04T10:40:41","slug":"cve-2026-5324-brizy-xss-waf-virtual-patching-maggio-2026","status":"publish","type":"post","link":"https:\/\/darioiannascoli.it\/blog\/cve-2026-5324-brizy-xss-waf-virtual-patching-maggio-2026\/","title":{"rendered":"Patch Maggio 2026: CVE-2026-5324 Brizy Page Builder Stored XSS &#8211; Come Identificare Plugin Compromessi e Implementare WAF Virtual Patching in Tempo Reale"},"content":{"rendered":"<p>Fin dalle prime ore di maggio 2026, i miei sistemi di monitoraggio hanno segnalato un&#8217;allerta critica: il plugin <em>Brizy \u2013 Page Builder<\/em>, utilizzato da oltre 90.000 siti WordPress, \u00e8 vulnerabile a un <strong>attacco Stored XSS unauthenticated<\/strong> (CVE-2026-5324). In questa guida vi mostro come identificare se i vostri siti sono esposti, come verificare la compromissione con strumenti di debug reali, e soprattutto come implementare <strong>WAF virtual patching in tempo reale<\/strong> su Plesk e Cloudflare mentre attendete i patch ufficiali.<\/p>\n<p>Ho gi\u00e0 assistito clienti nella identificazione di form compromesse in Brizy: la vulnerabilit\u00e0 sfrutta campi di upload vuoti e una catena di errori che trasforma l&#8217;input in un payload JavaScript eseguito nelle sessioni admin. Vi spiego esattamente cosa succede dietro le quinte, e come difendersi in 30 minuti.<\/p>\n<h2>Comprendere CVE-2026-5324: La Catena di Errori in Brizy<\/h2>\n<p><cite>La vulnerabilit\u00e0 \u00e8 dovuta a una combinazione di mancanza di verifica nonce per i form unauthenticated, gestione insufficiente dei campi FileUpload quando nessun file \u00e8 caricato, e reversione della codifica di sicurezza tramite html_entity_decode() seguita da output non escapato nella vista admin.<\/cite><\/p>\n<p>Nel dettaglio tecnico:<\/p>\n<ul>\n<li><cite>La funzione submit_form() salta la verifica nonce per gli utenti non loggati (api.php:198)<\/cite><\/li>\n<li><cite>La funzione handleFileTypeFields() non sovrascrive i valori forniti dall&#8217;utente quando nessun file \u00e8 allegato<\/cite><\/li>\n<li><cite>Mentre htmlentities() \u00e8 applicato durante il salvataggio, html_entity_decode() lo inverte al display (form-entries.php:79)<\/cite><\/li>\n<li><cite>Il template form-data.php output i valori FileUpload direttamente negli attributi href senza esc_url()<\/cite><\/li>\n<\/ul>\n<p>Il risultato: <cite>gli attaccanti unauthenticated possono iniettare script web arbitrari che si eseguono quando un amministratore visualizza la pagina Form Leads<\/cite>. La gravit\u00e0 \u00e8 <strong>CVSS 7.2<\/strong> (Alta).<\/p>\n<h2>Chi \u00e8 Veramente Esposto?<\/h2>\n<p><cite>I siti che utilizzano il plugin Brizy interessato e consentono i form pubblici per la cattura lead sono pi\u00f9 a rischio. Le organizzazioni con basso monitoraggio admin o uso frequente del dashboard admin sono particolarmente esposte.<\/cite><\/p>\n<p>Nella mia esperienza di auditing su decine di agenzie web, i form pubblici in Brizy sono ovunque: landing page, form di contatto, prenotazioni. Se il vostro sito ha una form Brizy pubblica e versione \u2264 2.8.11, siete vulnerabili <em>ora<\/em>.<\/p>\n<h2>Step 1: Identificare Plugin Compromessi con WP-CLI e Database Query<\/h2>\n<p>Nel mio ambiente di testing in Plesk, ho verificato il metodo pi\u00f9 diretto: ispezione del database e dei file plugin.<\/p>\n<h3>Via WP-CLI (rapido)<\/h3>\n<pre><code># Check Brizy version\nwp plugin list | grep brizy\n\n# Full plugin data\nwp plugin get brizy --field=version\nwp plugin get brizy --field=is_active<\/code><\/pre>\n<p>Se la versione \u00e8 \u2264 2.8.11 e il plugin \u00e8 attivo: <strong>ALLERTA<\/strong>.<\/p>\n<h3>Verificare Form Entries Compromesse (Query MySQL diretta)<\/h3>\n<p>Una volta entrati nel database WordPress via Plesk Console o CLI:<\/p>\n<pre><code>-- Inspect form entries for suspicious payloads\nSELECT id, form_id, created_at, updated_at \nFROM wp_brizy_form_entries \nWHERE data LIKE '%script%' \n   OR data LIKE '%javascript%' \n   OR data LIKE '%onerror%' \n   OR data LIKE '%onload%' \nLIMIT 20;<\/code><\/pre>\n<p>Se trovate righe, significa che il vostro sito \u00e8 stato probabilmente sfruttato. Documentate gli ID e gli orari: avrete una timeline di quando \u00e8 avvenuto l&#8217;accesso.<\/p>\n<p>La vera sfida \u00e8 che i payload sono <em>stored<\/em>: rimangono nel database e si eseguono ogni volta che un admin visualizza la pagina Form Leads. Ho visto casi in cui il malware era persistente per settimane.<\/p>\n<h2>Step 2: Analizzare i Log d&#8217;Accesso per Intrusioni<\/h2>\n<p><cite>Rivedete i caricamenti delle pagine admin WordPress per indicatori anomali di Stored XSS nei dati delle voci del form (valori del campo FileUpload, attributi href). Cercate voci sospette salvate da richieste unauthenticated agli endpoint di invio form del plugin. Monitorate l&#8217;esecuzione JavaScript inaspettata nelle pagine originate dall&#8217;admin (tentativi di bypass CSP, script inline insoliti). Controllate i log WAF\/proxy per invii di form contenenti pattern di payload HTML\/JS codificati che prendono di mira i campi FileUpload.<\/cite><\/p>\n<p>In Plesk, accedo ai log del server per analizzare le richieste POST non autenticate:<\/p>\n<pre><code># Analizzare richieste POST ai form endpoint di Brizy\ngrep \"POST.*brizy.*form\" \/var\/log\/apache2\/domains\/tuodominio.com.log | tail -100\n\n# Cercare payload XSS comuni nei log\ngrep -i \"script|onerror|javascript:\" \/var\/log\/apache2\/domains\/tuodominio.com.log | grep -v User-Agent<\/code><\/pre>\n<p>Se vedete POST requests ai form Brizy da IP sconosciuti, soprattutto con payload codificati (base64, URL-encoded), preparatevi al response di incident.<\/p>\n<h2>Step 3: Implementare WAF Virtual Patching su Plesk Obsidian<\/h2>\n<p>Qui entra in gioco la parte pratica: non potete aspettare un patch ufficiale se i vostri siti sono under attack. Il <strong>virtual patching<\/strong> blocca i payload noti a livello HTTP, prima ancora che il PHP vulnerabile li elabori.<\/p>\n<h3>Opzione A: ModSecurity in Plesk con Regole Custom<\/h3>\n<p>Se il vostro server Plesk ha ModSecurity (che raccomando in tutti i miei setup), aggiungete una regola che blocca i payload XSS nei parametri FileUpload di Brizy:<\/p>\n<pre><code># File: \/etc\/apache2\/mods-enabled\/security.conf o custom rule file\n# Bloccare richieste POST ai form di Brizy con payload sospetti\n\nSecRule REQUEST_URI \"@rx \/wp-admin\/admin.php.*brizy_form\" \n    \"id:1001001,phase:2,chain,log,deny,status:403,msg:'Brizy FileUpload XSS Attempt'\"\nSecRule REQUEST_BODY \"@rx (&lt;script|javascript:|onerror=|onload=|eval(|&lt;iframe)&quot; \n    &quot;t:urlDecode,t:htmlDecode&quot;\n\n# Alternativa: Bloccare specificamente il parametro file_upload\nSecRule ARGS:file_upload &quot;@rx (&lt;script|javascript:|onerror=|event[A-Za-z]*=)&quot; \n    &quot;id:1001002,phase:2,deny,log,status:403,msg:&#039;Brizy XSS - FileUpload Parameter&#039;&quot;\n\n# Bloccare base64-encoded payloads (spesso usati per evasione)\nSecRule REQUEST_BODY &quot;@rx PHNjcmlwdHw|PHN2Zy98aWZyYW1lfHNjcmlwdHxvbmVycm9y&quot; \n    &quot;id:1001003,phase:2,deny,log,status:403,msg:&#039;Base64 XSS Payload Detection&#039;&quot;,t:base64Decode\n<\/code><\/pre>\n<p>Dopo aver aggiunto le regole, testare in <em>detection mode<\/em> (non_blocking) per 24 ore, poi attivare il blocking:<\/p>\n<pre><code># Restart Apache con log delle violazioni\nsudo systemctl restart apache2\n\n# Monitorare i log ModSecurity\ntail -f \/var\/log\/apache2\/modsec_audit.log | grep \"Brizy XSS\"\n<\/code><\/pre>\n<h3>Opzione B: Cloudflare WAF Rules (se il dominio \u00e8 dietro Cloudflare)<\/h3>\n<p>Nel dashboard Cloudflare, navigare a <strong>Security \u2192 WAF Rules<\/strong> e creare una regola custom:<\/p>\n<pre><code>(http.request.uri.path contains \"\/wp-admin\/admin.php\" and http.request.method eq \"POST\") \nand \n(http.request.body.string matches \"(&lt;script|javascript:|onerror=|eval(|&lt;iframe)&quot;)\n\n# Azione: Block (HTTP 403)\n# Logging: Enabled\n# Priority: High\n<\/code><\/pre>\n<p>Cloudflare applicher\u00e0 il blocco globale in pochi secondi, senza necessit\u00e0 di restart del server.<\/p>\n<h3>Opzione C: Nginx + ModSecurity (se non usate Apache)<\/h3>\n<p>Se il vostro Plesk \u00e8 configurato con Nginx (come nel mio ambiente di produzione), ModSecurity v3 \u00e8 disponibile con il connettore nginx:<\/p>\n<pre><code># \/etc\/nginx\/modsecurity.d\/cve-2026-5324-brizy.conf\nSecRule REQUEST_BODY \"@rx (FileUpload.*?&lt;script|file_upload.*?onerror)&quot; \n    &quot;id:9000001,phase:2,deny,log,status:403,msg:&#039;CVE-2026-5324 Brizy XSS Block&#039;&quot;\n<\/code><\/pre>\n<p>Reload nginx: <code>sudo systemctl reload nginx<\/code><\/p>\n<h2>Step 4: Disabilitare Temporaneamente le Form di Brizy (Soluzione d&#8217;Emergenza)<\/h2>\n<p><cite>Trattate come priorit\u00e0 1: applicate il patch di Brizy prontamente a una versione al di l\u00e0 della gamma interessata; se l&#8217;applicazione immediata del patch \u00e8 ritardata, disabilitate temporaneamente le funzionalit\u00e0 di form\/lead interessate.<\/cite><\/p>\n<p>Se non potete aspettare:  via WP admin o WP-CLI, disabilitate il plugin:<\/p>\n<pre><code>wp plugin deactivate brizy --allow-root\n\n# O via Plesk (se configurato):\nplesk ext wordpress-toolkit -c deactivate-extension -extension-id brizy\n<\/code><\/pre>\n<p>Ci\u00f2 interrompe immediatamente la vulnerabilit\u00e0, ma blocca anche l&#8217;editor Brizy. Comunicate ai clienti che le pagine Brizy rimangono live, ma la modifica \u00e8 temporaneamente disabilitata.<\/p>\n<h2>Step 5: Incident Triage &#8211; Verificare la Compromissione Admin<\/h2>\n<p><cite>Eseguite il triage per il compromesso della sessione admin (rivedete i recenti accessi admin, i cambiamenti di sessione e le modifiche inaspettate di plugin\/tema\/file), con change management per assicurare che il patch sia distribuito coerentemente in tutte le istanze WordPress.<\/cite><\/p>\n<p>Nel mio flusso di audit:<\/p>\n<pre><code># Verificare login admin recenti (se avete Access Logs Plugin o audit nativo)\nwp user list --role=administrator\nwp user get 1 --field=user_login,user_email\n\n# Controllare le sessioni admin\nSELECT user_login, meta_key, meta_value \nFROM wp_users \nJOIN wp_usermeta ON wp_users.ID = wp_usermeta.user_id \nWHERE meta_key LIKE 'session%' \nORDER BY user_login;\n\n# Verificare il timestamp dell'ultimo accesso\nSELECT user_login, MAX(meta_value) as last_login \nFROM wp_usermeta \nJOIN wp_users ON wp_users.ID = wp_usermeta.user_id \nWHERE meta_key = 'last_login' \nGROUP BY user_login;\n<\/code><\/pre>\n<p>Se vedete login da IP sconosciuti o a orari insoliti, cambiate <strong>immediatamente<\/strong> le password admin e forzate il logout di tutte le sessioni:<\/p>\n<pre><code># Invalidare tutte le sessioni tranne la vostra\nwp user session destroy --all --except-current --allow-root\n\n# Oppure via database:\nDELETE FROM wp_options WHERE option_name LIKE '%session%';\nFLUSH PRIVILEGES;<\/code><\/pre>\n<h2>Step 6: Pulire i Payload Stored dal Database<\/h2>\n<p>Se avete identificato form entries compromesse, pulitele prima di re-abilitare Brizy:<\/p>\n<pre><code>-- Backup PRIMA\n-- mysqldump -u root -p wordpress &gt; backup-$(date +%s).sql\n\n-- Rimuovere voci form sospette\nDELETE FROM wp_brizy_form_entries \nWHERE data LIKE '%script%' \n   OR data LIKE '%onerror%' \nORDER BY updated_at DESC \nLIMIT 50; -- Limitare per sicurezza\n\n-- Oppure sanitizzare (pi\u00f9 sicuro che cancellare)\nUPDATE wp_brizy_form_entries \nSET data = REGEXP_REPLACE(data, ']*&gt;.*?', '', 'gi')\nWHERE created_at &gt;= DATE_SUB(NOW(), INTERVAL 7 DAY);<\/code><\/pre>\n<p>Prima di eseguire, fate sempre un backup completo del database in Plesk:<\/p>\n<pre><code>plesk db dump wordpress &gt; \/backup\/wordpress-pre-cleanup-$(date +%Y%m%d).sql<\/code><\/pre>\n<h2>FAQ<\/h2>\n<h3>Il mio sito \u00e8 davvero vulnerabile se disabilito le form pubbliche di Brizy?<\/h3>\n<p>No. La vulnerabilit\u00e0 richiede che qualcuno invii dati tramite una form pubblica di Brizy. Se le form sono disabilitate o il plugin \u00e8 disattivato, il vettore d&#8217;attacco scompare immediatamente. Tuttavia, <strong>i payload gi\u00e0 stored nel database rimangono<\/strong> finch\u00e9 non vengono puliti.<\/p>\n<h3>Devo aggiornare Brizy solo a versione 2.8.12+ o c&#8217;\u00e8 una versione sicura consigliata?<\/h3>\n<p>Brizy dovrebbe rilasciare una versione patch ufficiale entro maggio 2026. Nel frattempo, attendete un comunicato ufficiale dal team di Brizy o dalla community (Wordfence, Patchstack). Non aggiornate a versioni non verificate da fonti ufficiali.<\/p>\n<h3>Il WAF virtual patching \u00e8 sufficiente per proteggermi da CVE-2026-5324?<\/h3>\n<p><cite>No. Un WAF pu\u00f2 mitigare e bloccare i tentativi (virtual patching) ma non \u00e8 un sostituto per applicare il fix del codice ufficiale. Usate il WAF come misura per guadagnare tempo fino a quando gli aggiornamenti non sono distribuiti.<\/cite> Virtual patching \u00e8 una <em>difesa temporanea<\/em>, non permanente.<\/p>\n<h3>Come monitoro i tentativi di sfruttamento della vulnerabilit\u00e0 su Plesk?<\/h3>\n<p>Controllate i log ModSecurity\/WAF, i log di Apache\/Nginx, e configurate un alert SIEM (ELK Stack, Splunk) che catturi le violazioni delle regole WAF. In Plesk, potete anche usare estensioni come ModSecurity Dashboard o Fail2Ban per un response automatico ai pattern malevoli.<\/p>\n<h3>Devo avvisare i miei clienti della vulnerabilit\u00e0?<\/h3>\n<p>S\u00ec, se gestite siti per clienti, create un comunicato (email, ticketing) che spieghi: (1) Se il loro sito usa Brizy \u2264 2.8.11, (2) Il rischio specifico (XSS via form pubbliche), (3) Le azioni che state intraprendendo (WAF, patching, monitoraggio), (4) La timeline prevista. La trasparenza costruisce fiducia e vi protegge legalmente.<\/p>\n<h2>Conclusione: Proteggere i Vostri Siti da CVE-2026-5324<\/h2>\n<p>CVE-2026-5324 \u00e8 una vulnerabilit\u00e0 <strong>reale, critica e attivamente sfruttata<\/strong> a maggio 2026. Non potete ignorarla aspettando i patch ufficiali. La mia procedura in 6 step\u2014identificare, analizzare log, implementare WAF virtual patching, disabilitare se necessario, verificare compromissione e pulire il database\u2014vi protegge in meno di un&#8217;ora di lavoro.<\/p>\n<p>La lezione pratica che condivido con i colleghi system administrator: <strong>il WAF virtual patching non \u00e8 una opzione di lusso, \u00e8 una necessit\u00e0 operativa<\/strong>. Vi permette di proteggere i clienti senza downtime, guadagnare tempo per testing e patch, e mantenere il controllo della timeline di remediation.<\/p>\n<p>Se gestite infrastrutture multi-tenant in Plesk (come molte agenzie web), implementate ModSecurity rules centralizzate e sincronizzate Cloudflare WAF per coprire tutte le varianti di deployment. Commentate qui sotto con la vostra esperienza di patching di Brizy o altre vulnerabilit\u00e0 WordPress critiche\u2014sono sempre interessato a confrontarmi su best practice real-world con altri sysadmin.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>CVE-2026-5324: Brizy Page Builder vulnerabile a Stored XSS unauthenticated. Guida pratica per identificare compromissioni, implementare WAF virtual patching in Plesk\/Cloudflare e pulire payload malware dal database.<\/p>\n","protected":false},"author":1,"featured_media":1892,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":"CVE-2026-5324 Brizy XSS: Virtual Patching WAF | Maggio 2026","_seopress_titles_desc":"Proteggi i tuoi siti da CVE-2026-5324 Brizy Stored XSS. Virtual patching WAF, identificazione compromissioni e pulizia database in questa guida pratica per Plesk.","_seopress_robots_index":"","footnotes":""},"categories":[5],"tags":[684,631,685,204,523,237],"class_list":["post-1891","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-assistenza-computer","tag-cve-2026-5324","tag-incident-response","tag-modsecurity-rules","tag-plesk-obsidian","tag-waf-virtual-patching","tag-wordpress-security"],"_links":{"self":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts\/1891","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/comments?post=1891"}],"version-history":[{"count":0,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts\/1891\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/media\/1892"}],"wp:attachment":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/media?parent=1891"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/categories?post=1891"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/tags?post=1891"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}