Situazione attuale: PHP2Shell. Due vulnerabilità critiche di PHP (CVSS 9,2) consentono codice dannoso senza autenticazione. Patch dal 21/10/2026.Che cosa fare ora →

Prevenire XSS in PHP: difendersi con sicurezza dal cross-site scripting

Come gli sviluppatori prevengono il cross-site scripting nelle applicazioni PHP: codifica adatta al contesto, auto-escaping nei template, pulizia dell'HTML e una Content Security Policy.

Stato 6 min di letturaGuide

In breve: XSS in PHP si previene codificando ogni output in modo adatto al suo contesto: htmlspecialchars() per HTML, json_encode() con opzioni di protezione per JavaScript, URL verificati per i link. I template con escaping automatico ne tolgono gran parte dal Suo lavoro. Una Content Security Policy e i cookie HttpOnly limitano il danno se comunque resta una vulnerabilità.

Perché ora il cross-site scripting va controllato insieme al resto

A ottobre 2026 l'attenzione è su PHP2Shell, due vulnerabilità critiche nell'interprete PHP, per le quali esistono patch dal 21/10/2026. Molte aziende, in questo contesto, fanno controllare le proprie applicazioni web. È una buona occasione per esaminare anche le debolezze nel codice proprio che nessun aggiornamento di PHP risolve.

Il cross-site scripting, in breve XSS, è una di queste. La OWASP Top 10 colloca XSS nella categoria Injection. A differenza di una vulnerabilità nel server, qui l'attacco è rivolto ai visitatori e agli utenti del Suo sito, ad esempio ai clienti nello shop o ai collaboratori nel backend.

Le conseguenze possono essere considerevoli: sessioni di amministratori prese in carico, moduli manipolati che inviano dati a terzi, o contenuti falsificati sul Suo sito. Se un account amministratore viene preso in carico, si può arrivare al controllo completo dell'applicazione.

Come nasce XSS nelle applicazioni PHP?

XSS nasce quando un'applicazione restituisce in una pagina, senza verifica, dati provenienti da una fonte non affidabile. Il browser non riesce più a distinguere tra i Suoi contenuti e il codice introdotto di nascosto e li esegue entrambi.

Si distinguono tre forme. Nel XSS riflesso il contenuto proviene direttamente dalla richiesta corrente, ad esempio da un termine di ricerca nell'URL. Nel XSS memorizzato si trova nel database, per esempio in un commento o in un campo del profilo, e colpisce chiunque apra la pagina. Il XSS basato su DOM nasce nel JavaScript del browser, quando gli script scrivono nella pagina valori presi dall'URL.

Non sono affidabili tutti i dati che non sono fissati nel codice: campi dei moduli, parametri URL, cookie, nomi di file, risposte di interfacce esterne e contenuti del proprio database che a un certo punto sono arrivati dall'esterno.

Codificare correttamente l'output in base al contesto

La regola più importante è: codificare all'output, e in modo adatto al luogo in cui finisce il valore. Per il contenuto HTML e gli attributi tra virgolette, htmlspecialchars() è lo strumento da scegliere. Una piccola funzione di supporto evita che le opzioni vengano dimenticate:

<?php
function e(?string $wert): string
{
    return htmlspecialchars($wert ?? '', ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
}
?>
<h2><?= e($produkt['name']) ?></h2>
<input type="text" name="suche" value="<?= e($_GET['q'] ?? '') ?>">

Altri contesti richiedono altri strumenti:

Contesto Metodo sicuro
Contenuto HTML, attributo tra virgolette htmlspecialchars() con ENT_QUOTES e UTF-8
Dati per JavaScript json_encode() con JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_HEX_QUOT
Parametro in un URL rawurlencode() per il singolo valore
URL completo da input dell'utente verificare lo schema, consentire solo https e http, poi htmlspecialchars()
Attributi senza virgolette, event handler, CSS evitare, non inserire lì dei valori

Per i dati di cui uno script ha bisogno, un attributo data o un blocco JSON è di solito la via più pulita:

<?php
$daten = json_encode($konfiguration, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
?>
<div id="app" data-konfig="<?= e($daten) ?>"></div>

In JavaScript legge poi il valore tramite l'attributo data e imposta i contenuti con textContent invece che con innerHTML.

Template, pulizia dell'HTML e framework

I motori di template come Twig e Blade codificano per impostazione predefinita gli output in modo automatico. Questo esclude gran parte degli errori tipici. Il pericolo sorge dove questo comportamento viene disattivato di proposito, ad esempio con il filtro raw in Twig o la sintassi {!! !!} in Blade. Tali punti dovrebbero essere rari nel codice e controllati in modo mirato a ogni review.

Se la Sua applicazione deve consentire di proposito HTML da parte degli utenti, ad esempio formattazioni nei commenti o in un sistema editoriale, codificare non basta, perché l'HTML deve essere visualizzato. Serve allora una libreria di pulizia collaudata come HTML Purifier, che lascia passare solo un elenco fisso di elementi e attributi consentiti. I filtri propri con espressioni regolari sono, per esperienza, lacunosi.

Importante

Controlli in particolare le aree di backend. XSS nelle viste che vedono solo gli amministratori è spesso sottovalutato, ma colpisce proprio gli account con più diritti.

Trovare XSS nel codice PHP esistente

Nelle applicazioni cresciute negli anni la prima domanda di solito non è come codificare correttamente, ma dove finora ci si è dimenticati di farlo. Un inizio pragmatico è la ricerca dei punti in cui le variabili vengono emesse direttamente:

# Output diretti di dati della richiesta
grep -rnE "(echo|print|<\?=)\s*\\\$_(GET|POST|REQUEST|COOKIE|SERVER)" src/ templates/ --include="*.php"
# Auto-escaping disattivato in Twig e Blade
grep -rnE "\|raw|\{!!" templates/ resources/views/

I riscontri sono incarichi di verifica, non risultati definitivi. Il XSS memorizzato una ricerca di questo tipo lo trova solo in parte, perché lì i valori vengono dal database. Controlli quindi in aggiunta tutte le viste che mostrano contenuti degli utenti: commenti, profili, note d'ordine, ticket di supporto. Nei CMS e negli shop vanno inclusi espressamente plugin e temi di terze parti, perché lì si trova gran parte della logica di output.

Anche con un codice accurato un punto può essere trascurato. Due misure limitano allora il danno. Una Content Security Policy consente al browser solo script provenienti da fonti stabilite e vieta gli script incorporati, a meno che non siano autorizzati espressamente:

Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"

Introduca una simile policy gradualmente, dapprima in sola modalità di segnalazione tramite Content-Security-Policy-Report-Only, perché le integrazioni esistenti di servizi di analisi o di pagamento vanno di solito aggiunte. Altri header sono descritti nella guida Header di sicurezza per i siti web.

Inoltre i cookie di sessione dovrebbero avere l'attributo HttpOnly, in modo che gli script non possano leggerli. Come mettere in sicurezza le sessioni nel complesso è spiegato nella guida Mettere in sicurezza le sessioni in PHP. Una debolezza affine sul lato database è trattata in Prevenire la SQL injection in PHP.

Come aiuta concretamente PHP SOS?

  • Verifichiamo template e output della Sua applicazione alla ricerca di codifiche mancanti o errate.
  • Valutiamo i ritrovamenti in base a raggiungibilità e account coinvolti e mostriamo correzioni concrete.
  • Introduciamo una Content Security Policy gradualmente, senza disturbare le funzioni dello shop o dei pagamenti.
  • Dopo la correzione testiamo di nuovo e documentiamo il risultato.

Una verifica indipendente è descritta nel servizio Audit di sicurezza e penetration test.

Domande frequenti

htmlspecialchars basta contro XSS?

Per il testo normale nel contenuto HTML e negli attributi tra virgolette sì, se indica ENT_QUOTES e il set di caratteri UTF-8. In JavaScript, negli URL o in CSS valgono altre regole e serve una codifica propria e adatta.

Dovrei filtrare gli input al salvataggio o all'output?

Codifichi all'output, in modo adatto alla destinazione. Gli input vanno controllati alla ricezione per plausibilità, ad esempio lunghezza e formato. Chi filtra solo al salvataggio trascura i dati provenienti da altre fonti e complica l'uso successivo in altri contesti.

Che cosa serve una Content Security Policy?

Una Content Security Policy stabilisce da quali fonti il browser può caricare ed eseguire script. Può limitare in modo significativo gli effetti di una vulnerabilità XSS trascurata, ma non sostituisce una codifica corretta.

Come consento formattazioni come grassetto o link nei commenti?

Usi una libreria collaudata di pulizia dell'HTML con una whitelist di elementi e attributi consentiti. Le espressioni regolari proprie per rimuovere gli script sono soggette a errori e non andrebbero usate.

Fonti

Contatto immediato

Ogni ora conta. Ci scriva adesso.

Descriva brevemente sistema, versione di PHP e quanto osservato. Ci faremo sentire, chiariremo la situazione e lavoreremo da remoto fino alla chiusura e alla documentazione dell'incidente.

Aiuto immediato