Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Scripting tra siti (XSS) è una vulnerabilità di sicurezza che consente a un cyberattacker di inserire script lato client (in genere JavaScript) in pagine Web. Quando altri utenti caricano le pagine interessate, vengono eseguiti gli script di cyberattacker. Il cyberattacker può quindi rubare cookie e token di sessione, modificare il contenuto della pagina Web tramite la manipolazione DOM o reindirizzare il browser a un'altra pagina. Le vulnerabilità XSS si verificano generalmente quando un'applicazione riceve un input dell'utente e lo visualizza in una pagina senza prima convalidarlo, codificarlo o sottoporlo a escape.
Questo articolo si applica principalmente a ASP.NET Core MVC con visualizzazioni, Razor Pages e altre app che restituiscono CODICE HTML che possono essere vulnerabili a XSS. Le API Web che restituiscono dati sotto forma di HTML, XML o JSON possono attivare attacchi XSS nelle app client se non sanificano correttamente l'input dell'utente. Questo comportamento dipende dalla quantità di attendibilità che l'app client inserisce nell'API. Se un'API accetta contenuto generato dall'utente e lo restituisce in una risposta HTML, i dati sono aperti all'attacco. Un attaccante informatico può iniettare script dannosi nel contenuto che vengono eseguiti quando la risposta viene visualizzata nel browser dell'utente.
Per evitare attacchi XSS, le API Web devono implementare la convalida dell'input e la codifica di output. La convalida dell'input garantisce che l'input dell'utente soddisfi i criteri previsti e non includa codice dannoso. La codifica dell'output garantisce che tutti i dati restituiti dall'API siano correttamente sanificati in modo che non possano essere eseguiti come codice dal browser dell'utente. Per altre informazioni, vedere GitHub dotnet/aspnetcore.docs issue #28789.
Proteggere l'applicazione da XSS
A livello di base, XSS funziona ingannando l'applicazione nell'inserimento di un <script> tag nella pagina sottoposta a rendering o inserendo un On* evento in un elemento.
Per evitare di introdurre XSS nell'applicazione, gli sviluppatori devono implementare le tecniche di prevenzione seguenti:
Non inserire mai dati non attendibili nell'input HTML, a meno che non si seguano le altre tecniche elencate in questa sezione.
I dati non attendibili sono dati controllabili da un cyberattacker. Gli esempi includono input di moduli HTML, stringhe di query, intestazioni HTTP o persino dati originati da un database. Un cyberattacker potrebbe essere in grado di violare il database anche se non possono violare l'applicazione.
Prima di inserire dati non attendibili in un elemento HTML, assicurarsi che i dati siano codificati in HTML.
La codifica HTML accetta caratteri come la parentesi angolare sinistra o minore di (
<) e le modifica in una forma sicura come (<).Prima di inserire dati non attendibili in un attributo HTML, verificare che i dati siano codificati con attributi HTML.
Questa forma specializzata di codifica HTML gestisce virgolette doppie (
"), virgolette singole ('), e commerciale (&) e meno di (<). Quando si gestisce l'input non attendibile, utilizzare la codifica HTML per il contenuto HTML generale e la codifica degli attributi HTML per gli attributi HTML.Prima di inserire dati non attendibili in JavaScript, inserire i dati in un elemento HTML il cui contenuto viene recuperato in fase di esecuzione.
Se non è possibile seguire questa tecnica, assicurarsi che i dati siano codificati in JavaScript. La codifica JavaScript converte caratteri pericolosi per JavaScript in un valore equivalente esadecimale. Ad esempio, la codifica JavaScript modifica il carattere "minore di" (
<) con il valore esadecimale\u003C.Prima di inserire dati non attendibili in una stringa di query URL, assicurarsi che i dati siano codificati in URL.
Esplorare la codifica HTML con Razor
Il Razor motore usato in MVC codifica automaticamente tutti gli output generati dalle variabili, a meno che non si lavori per impedire questo comportamento. Usa regole di codifica degli attributi HTML ogni volta che si usa la direttiva at symbol @ . Poiché la codifica degli attributi HTML è un superset di codifica HTML, non è necessario considerare se usare la codifica HTML o la codifica degli attributi HTML. È necessario assicurarsi di usare solo il simbolo @ at in un contesto HTML e non quando si tenta di inserire l'input non attendibile direttamente in JavaScript.
Razor Gli helper tag codificano anche l'input usato nei parametri dei tag.
Si consideri la visualizzazione seguente Razor :
@{
var untrustedInput = "<\"123\">";
}
@untrustedInput
Questa vista restituisce il contenuto della untrustedInput variabile. La variabile include alcuni caratteri usati negli attacchi XSS: minore di (<), virgolette doppie (") e parentesi angolare destra o maggiore di (>). Esaminando il codice sorgente, l'output renderizzato viene codificato come segue:
<"123">
Avviso
ASP.NET Core MVC fornisce una classe HtmlString che non viene codificata automaticamente all'output. Questa classe non deve mai essere usata in combinazione con l'input non attendibile perché espone una vulnerabilità XSS.
Esplorare la codifica JavaScript con Razor
In alcuni casi, è possibile inserire un valore in JavaScript da elaborare nella visualizzazione. Esistono due modi per eseguire questa attività. Il modo più sicuro per inserire i valori consiste nell'inserire il valore in un attributo di dati di un tag e recuperarlo in JavaScript. Ad esempio:
@{
var untrustedInput = "<script>alert(1)</script>";
}
<div id="injectedData"
data-untrustedinput="@untrustedInput" />
<div id="scriptedWrite" />
<div id="scriptedWrite-html5" />
<script>
var injectedData = document.getElementById("injectedData");
// All clients
var clientSideUntrustedInputOldStyle =
injectedData.getAttribute("data-untrustedinput");
// HTML 5 clients only
var clientSideUntrustedInputHtml5 =
injectedData.dataset.untrustedinput;
// Put the injected, untrusted data into the scriptedWrite div tag.
// Do NOT use document.write() on dynamically generated data as it can lead to XSS.
document.getElementById("scriptedWrite").innerText += clientSideUntrustedInputOldStyle;
// Or, you can use createElement() to dynamically create document elements.
// This instance uses textContent to ensure the data is properly encoded.
var x = document.createElement("div");
x.textContent = clientSideUntrustedInputHtml5;
document.body.appendChild(x);
// You can also use createTextNode on an element to ensure data is properly encoded.
var y = document.createElement("div");
y.appendChild(document.createTextNode(clientSideUntrustedInputHtml5));
document.body.appendChild(y);
</script>
Il markup precedente genera il codice HTML seguente:
<div id="injectedData"
data-untrustedinput="<script>alert(1)</script>" />
<div id="scriptedWrite" />
<div id="scriptedWrite-html5" />
<script>
var injectedData = document.getElementById("injectedData");
// All clients
var clientSideUntrustedInputOldStyle =
injectedData.getAttribute("data-untrustedinput");
// HTML 5 clients only
var clientSideUntrustedInputHtml5 =
injectedData.dataset.untrustedinput;
// Put the injected, untrusted data into the scriptedWrite div tag.
// Do NOT use document.write() on dynamically generated data as it can lead to XSS.
document.getElementById("scriptedWrite").innerText += clientSideUntrustedInputOldStyle;
// Or, you can use createElement() to dynamically create document elements.
// This instance uses textContent to ensure the data is properly encoded.
var x = document.createElement("div");
x.textContent = clientSideUntrustedInputHtml5;
document.body.appendChild(x);
// You can also use createTextNode on an element to ensure data is properly encoded.
var y = document.createElement("div");
y.appendChild(document.createTextNode(clientSideUntrustedInputHtml5));
document.body.appendChild(y);
</script>
Il codice precedente genera l'output seguente:
<script>alert(1)</script>
<script>alert(1)</script>
<script>alert(1)</script>
Avviso
Non concatenare input non attendibili in JavaScript per creare elementi DOM e non usare document.write() con contenuti generati dinamicamente.
Usare invece uno degli approcci seguenti per impedire che il codice venga esposto a XSS basato su DOM:
- Chiamare
createElement()e assegnare valori di proprietà con metodi o proprietà appropriati, ad esempionode.textContent=onode.InnerText=. - Chiamare il
document.CreateTextNode()metodo e aggiungerlo nella posizione DOM appropriata. - Chiamare il metodo
element.SetAttribute(). - Usa l'assegnazione
element[attribute]=.
Codificatori di accesso nel codice
È possibile usare codificatori HTML, JavaScript e URL nel codice in due modi:
- Iniettarli tramite iniezione delle dipendenze.
- Utilizzare i codificatori predefiniti contenuti nel namespace
System.Text.Encodings.Web.
Quando si usano i codificatori predefiniti, le personalizzazioni applicate agli intervalli di caratteri (in modo che vengano considerate sicure) non abbiano effetto. I codificatori predefiniti usano le regole di codifica più sicure possibili.
Per usare i codificatori configurabili tramite l'iniezione delle dipendenze, i costruttori dovrebbero accettare un parametro HtmlEncoder, JavaScriptEncoder e UrlEncoder, a seconda dei casi.
Ad esempio:
public class HomeController : Controller
{
HtmlEncoder _htmlEncoder;
JavaScriptEncoder _javaScriptEncoder;
UrlEncoder _urlEncoder;
public HomeController(HtmlEncoder htmlEncoder,
JavaScriptEncoder javascriptEncoder,
UrlEncoder urlEncoder)
{
_htmlEncoder = htmlEncoder;
_javaScriptEncoder = javascriptEncoder;
_urlEncoder = urlEncoder;
}
}
Codifica i parametri URL
Se si vuole compilare una stringa di query URL con input non attendibile come valore, usare il UrlEncoder parametro per codificare il valore:
var example = "\"Quoted Value with spaces and &\"";
var encodedValue = _urlEncoder.Encode(example);
Dopo la codifica, la encodedValue variabile contiene la stringa %22Quoted%20Value%20with%20spaces%20and%20%26%22. Gli spazi, le virgolette, la punteggiatura e altri caratteri non sicuri vengono codificati in percentuale nel valore esadecimale. Ad esempio, un carattere spazio viene convertito in %20.
Avviso
Non usare l'input non attendibile come parte di un percorso URL. Passa sempre l'input non attendibile come valore della stringa di query.
Personalizzare i codificatori
Per impostazione predefinita, i codificatori usano un elenco sicuro limitato all'intervallo Unicode latino di base. Tutti i caratteri all'esterno dell'intervallo indicato vengono codificati come equivalenti al codice carattere. Questo comportamento influisce anche sul rendering da parte degli Razor helper tag e degli helper HTML perché usano i codificatori per restituire le stringhe.
Lo scopo di questo comportamento è proteggere da bug sconosciuti o futuri del browser. I bug delle versioni precedenti del browser hanno ostacolato il parsing basato sull'elaborazione di caratteri non inglesi. Se il sito Web usa pesantemente caratteri non latini, ad esempio cinese, cirillico o altri, questo comportamento probabilmente non è adatto per la configurazione.
È possibile personalizzare gli elenchi sicuri del codificatore in modo da includere intervalli Unicode appropriati per l'app durante l'avvio. Apportare le personalizzazioni nel file Program.cs .
Ad esempio, è possibile usare la configurazione predefinita con un Razor helper HTML simile al codice HTML seguente:
<p>This link text is in Chinese: @Html.ActionLink("汉语/漢語", "Index")</p>
Il markup precedente viene visualizzato con testo cinese codificato:
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
Per ampliare l'intervallo di caratteri trattati come sicuri dal codificatore, inserire la riga seguente nel file Program.cs :
builder.Services.AddSingleton<HtmlEncoder>(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs }));
È possibile personalizzare gli elenchi sicuri del codificatore in modo da includere intervalli Unicode appropriati per l'applicazione durante l'avvio, in ConfigureServices().
Ad esempio, usando la configurazione predefinita, è possibile usare un Razor HtmlHelper come in questo caso;
<p>This link text is in Chinese: @Html.ActionLink("汉语/漢語", "Index")</p>
Quando si visualizza l'origine della pagina Web, si noterà che è stato eseguito il rendering come indicato di seguito, con il testo cinese codificato;
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
Per ampliare i caratteri trattati come sicuri dal codificatore, inserire la riga seguente nel ConfigureServices() metodo in startup.cs;
services.AddSingleton<HtmlEncoder>(
HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.BasicLatin,
UnicodeRanges.CjkUnifiedIdeographs }));
In questo esempio viene ampliato l'elenco sicuro in modo da includere gli Ideogrammi unificati Unicode Range CJK. Il seguente output mostra la vista renderizzata per la gamma più ampia di caratteri sicuri:
<p>This link text is in Chinese: <a href="/">汉语/漢語</a></p>
Gli intervalli di elenchi sicuri vengono specificati come grafici di codice Unicode, non come linguaggi. Lo standard Unicode include un elenco di grafici di codice che è possibile usare per trovare il grafico che contiene i caratteri. Ogni codificatore (HTML, JavaScript, URL) deve essere configurato separatamente.
Nota
La personalizzazione dell'elenco sicuro influisce solo sui codificatori originati tramite inserimento delle dipendenze.
Se si accede direttamente a un codificatore tramite System.Text.Encodings.Web.*Encoder.Default, viene usato solo l'elenco sicuro predefinito, l'alfabeto latino di base.
Determinare quando e dove codificare
In generale, la procedura accettata è che la codifica avviene nel punto di output e i valori codificati non devono mai essere archiviati in un database.
La codifica nel punto di output consente di modificare l'uso dei dati. Ad esempio, passare da HTML a un valore di stringa di query. Questo approccio consente di eseguire facilmente ricerche nei dati senza dover codificare i valori prima della ricerca. Consente inoltre di sfruttare eventuali modifiche o correzioni di bug apportate ai codificatori.
Usare la convalida come tecnica di prevenzione XSS
La convalida può essere uno strumento utile per limitare gli attacchi XSS. Ad esempio, una stringa numerica contenente solo i caratteri 0-9 non attiva un attacco XSS.
La convalida è più complessa quando html viene accettato nell'input dell'utente. L'analisi dell'input HTML può essere difficile e talvolta impossibile. Markdown, insieme a un parser che rimuove l'HTML incorporato, è un'opzione più sicura per accettare contenuti avanzati.
Non fare mai affidamento solo sulla convalida. Codifica sempre l'input non attendibile prima dell'output, indipendentemente dalla convalida o dalla purificazione.