In questo articolo vengono descritti i problemi di sicurezza associati all'uso di LINQ to XML e vengono fornite indicazioni per ridurre l'esposizione ai rischi in termini di sicurezza.
Panoramica sulla sicurezza in LINQ to XML
LINQ to XML è progettato più per semplificare la programmazione che per applicazioni lato server con requisiti rigorosi di sicurezza. La maggior parte degli scenari XML sono costituiti dall'elaborazione di documenti XML attendibili, anziché dall'elaborazione di documenti XML non attendibili caricati in un server. LINQ to XML è ottimizzato per questi scenari.
Se è necessario elaborare dati non attendibili provenienti da origini sconosciute, si consiglia di usare un'istanza della classe XmlReader configurata per filtrare gli attacchi di tipo Denial of Service XML noti.
Se è stata configurata una classe XmlReader per limitare gli attacchi Denial of Service, è possibile usare tale classe per popolare l'albero LINQ to XML e sfruttare comunque i miglioramenti di LINQ to XML per la produttività nella programmazione. Diverse tecniche implicano la creazione di lettori configurati per limitare i problemi di sicurezza e quindi la creazione di istanze di un albero XML tramite il lettore configurato.
XML è intrinsecamente vulnerabile agli attacchi di tipo Denial of Service, perché i documenti non presentano vincoli in termine di dimensioni, complessità, dimensioni dei nomi degli elementi e così via. Indipendentemente dal componente usato per l'elaborazione XML, è necessario essere sempre pronti a riciclare il dominio dell'applicazione se usa una quantità eccessiva di risorse.
Se si opera in ambienti meno protetti, è necessario tenere conto di diversi problemi di sicurezza associati a XML e all'uso delle classi in System.Xml, System.Xml.Schema, System.Xml.XPath e System.Xml.Xsl. Di seguito sono elencati solo alcuni di questi problemi:
XSD, XPath e XSLT sono linguaggi basati su stringa in cui è possibile specificare operazioni che richiedono quantità elevate di tempo o memoria. È responsabilità dei programmatori di applicazioni che usano stringhe XSD, XPath o XSLT da origini non attendibili verificare che tali stringhe non siano dannose o monitorare e mitigare la possibilità che la valutazione di tali stringhe comporti un consumo eccessivo delle risorse di sistema.
Gli schemi XSD (inclusi quelli inline) sono intrinsecamente vulnerabili ad attacchi Denial of Service. È consigliabile non accettare schemi provenienti da origini non attendibili.
XSD e XSLT possono includere riferimenti ad altri file, ad esempio riferimenti che generano attacchi tra zone e tra domini diversi.
Le entità esterne nelle dichiarazioni DTD possono generare attacchi tra zone e tra domini diversi.
Le dichiarazioni DTD sono vulnerabili ad attacchi di tipo Denial of Service
I documenti XML particolarmente complessi possono presentare problemi di Denial of Service. È preferibile limitare la complessità dei documenti XML.
Leggere i dati in blocchi per limitare gli attacchi a documenti di grandi dimensioni.
I blocchi di script nei fogli di stile XSLT possono esporre numerosi attacchi.
Effettuare convalide accurate prima di costruire espressioni XPath dinamiche.
Problemi di sicurezza in LINQ to XML
I problemi di sicurezza illustrati in questo articolo non vengono presentati in un ordine specifico. Tutti i problemi sono importanti e devono essere affrontati nel modo appropriato.
Un attacco riuscito di tipo elevazione dei privilegi offre a un assembly dannoso un maggior controllo sull'ambiente. Può inoltre provocare la diffusione di dati, problemi di Denial of Service e così via.
Le applicazioni non devono divulgare dati agli utenti che non sono autorizzati a visualizzarli.
Gli attacchi di tipo Denial of Service causano il consumo di quantità eccessive di memoria o tempo CPU da parte di LINQ to XML. Sono considerati meno gravi degli attacchi di tipo elevazione dei privilegi o di quelli che comportano la diffusione di dati. Sono, tuttavia, estremamente importanti negli scenari in cui un server deve elaborare documenti XML provenienti da origini non attendibili.
Non esporre messaggi di errore a chiamanti non attendibili
La descrizione di un errore può rivelare dati, ad esempio i dati che vengono trasformati, nomi file o dettagli sull'implementazione. I messaggi di errore non devono essere esposti a chiamanti non attendibili. È necessario intercettare tutti gli errori e segnalarli con messaggi di errore personalizzati.
Non chiamare CodeAccessPermissions.Assert in un gestore eventi
A un assembly possono essere associate autorizzazioni minori o maggiori. Gli assembly con autorizzazioni maggiori hanno un maggior controllo sul computer e sugli ambienti.
Se il codice di un assembly con autorizzazioni maggiori chiama CodeAccessPermission.Assert in un gestore eventi e quindi l'albero XML viene passato a un assembly dannoso con autorizzazioni limitate, l'assembly dannoso può causare la generazione di un evento. L'evento esegue codice incluso nell'assembly con autorizzazioni di livello superiore, di conseguenza l'assembly dannoso opererebbe in questo caso con privilegi elevati.
Non accettare DTD provenienti da origini non attendibili
Le entità nelle dichiarazioni DTD sono intrinsecamente non protette. È possibile che un documento XML dannoso contenente una dichiarazione DTD induca il parser a usare tutta la memoria e tutto il tempo CPU disponibili, generando un attacco Denial of Service. Pertanto, in LINQ to XML l'elaborazione DTD è disattivata per impostazione predefinita. Non accettare DTD provenienti da origini non attendibili.
È ad esempio possibile che vengano accettate DTD da origini non attendibili nel caso di un'applicazione Web che consente agli utenti Web di caricare un file XML che fa riferimento a una DTD e a un file DTD. Dopo la convalida del file, una DTD dannosa potrebbe eseguire un attacco Denial of Service sul server. Un altro esempio di DTD accettate da origini non attendibili è il riferimento a una DTD su una condivisione di rete che consente anche l'accesso FTP anonimo.
Evitare l'allocazione eccessiva del buffer
Gli sviluppatori di applicazioni devono essere consapevoli che origini dati di dimensioni estremamente grandi possono portare all'esaurimento delle risorse e ad attacchi Denial of Service.
Se un utente malintenzionato invia o carica un documento XML di grandi dimensioni, può causare un consumo eccessivo di risorse di sistema da parte di LINQ to XML. Ciò costituisce un attacco di tipo Denial of Service. Per evitare questo problema, è possibile impostare la proprietà XmlReaderSettings.MaxCharactersInDocument e creare un lettore che può caricare documenti di dimensioni soggette a limitazioni. Usare quindi il lettore per creare l'albero XML.
Se ad esempio è noto che le dimensioni massime previste dei documenti XML provenienti da un'origine non attendibile saranno minori di 50.000 byte, impostare XmlReaderSettings.MaxCharactersInDocument su 100.000. In questo modo l'elaborazione dei documenti XML non viene ostacolata e allo stesso tempo è possibile limitare le minacce di Denial of Service che si presenterebbero se fosse possibile caricare documenti che consumano grandi quantità di memoria.
Evitare un'eccessiva espansione delle entità
Un tipo noto di attacco Denial of Service associato all'utilizzo di una dichiarazione DTD si verifica quando un documento provoca un'eccessiva espansione delle entità. Per evitare questo problema, è possibile impostare la proprietà XmlReaderSettings.MaxCharactersFromEntities e creare un lettore che presenta limitazioni in termini di numero di caratteri risultanti dall'espansione di entità. Usare quindi il lettore per creare l'albero XML.
Limitare la profondità della gerarchia XML
Un possibile attacco di tipo Denial of Service si verifica quando viene inviato un documento con una profondità della gerarchia eccessiva. Per evitare questo problema, è possibile eseguire il wrapping di una classe XmlReader nella classe personalizzata che conteggia la profondità degli elementi. Se la profondità supera un predeterminato livello ragionevole, è possibile terminare l'elaborazione del documento dannoso.
Proteggersi da implementazioni XmlReader o XmlWriter non attendibili
Gli amministratori devono verificare che tutte le implementazioni XmlReader o XmlWriter fornite esternamente abbiano nomi sicuri e siano state registrate nella configurazione del computer. In questo modo è possibile evitare il caricamento di malware camuffato da lettore o writer.
Liberare periodicamente gli oggetti che fanno riferimento a XName
Per proteggersi da determinati tipi di attacco, i programmatori di applicazioni devono liberare periodicamente tutti gli oggetti che fanno riferimento a un oggetto XName nel dominio dell'applicazione.
Proteggersi da nomi XML casuali
Le applicazioni che accettano dati da origini non attendibili dovrebbero eseguire il wrapping di una classe XmlReader nel codice personalizzato per verificare la possibile presenza di nomi e spazi dei nomi XML casuali. Se vengono individuati nomi e spazi dei nomi XML casuali, l'applicazione può terminare l'elaborazione del documento dannoso.
È possibile limitare il numero di nomi in un determinato spazio dei nomi (inclusi i nomi non inseriti in uno spazio dei nomi) a un livello ragionevole.
Serializzare oggetti LINQ to XML in testo XML prima di passare i dati a un componente non attendibile
È possibile usare LINQ to XML per creare pipeline di elaborazione in cui componenti diversi dell'applicazione caricano, convalidano, eseguono query, trasformano, aggiornano e salvano i dati XML passati tra componenti come alberi XML. In questo modo è possibile ottimizzare le prestazioni, perché l'overhead associato al caricamento e alla serializzazione di oggetti in testo XML viene eseguito solo fino alle estremità della pipeline. Gli sviluppatori devono tenere presente, tuttavia, che tutte le annotazioni e i gestori eventi creati da un componente sono accessibili ad altri componenti. Ciò può creare numerose vulnerabilità se i componenti presentano livelli di attendibilità diverse. Per compilare pipeline protette tra componenti meno attendibili, è necessario serializzare gli oggetti LINQ to XML in testo XML prima di passare i dati a un componente non attendibile.
CLR (Common Language Runtime) rende disponibile un certo grado di sicurezza. Ad esempio, un componente che non include una classe privata non può accedere alle annotazioni immesse da tale classe. Tuttavia, le annotazioni possono essere eliminate da componenti che non riescono a leggerle. Questa situazione può essere sfruttata in un attacco di tipo manomissione.
L'origine di questo contenuto è disponibile in GitHub, in cui è anche possibile creare ed esaminare i problemi e le richieste pull. Per ulteriori informazioni, vedere la guida per i collaboratori.
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback:
Informazioni su come usare le annotazioni in LINQ to XML per associare qualsiasi oggetto arbitrario di qualsiasi tipo arbitrario a qualsiasi componente XML di un albero XML.
Per scrivere una query in XML inclusa in uno spazio dei nomi, usare oggetti XName con lo spazio dei nomi corretto. Informazioni su come eseguire questa operazione in C# e Visual Basic e su come creare query.
È possibile analizzare una stringa con XElement.Parse per creare un albero XML in C# e Visual Basic e creare un albero XML con valori letterali XML in Visual Basic.