Prevenzione XSS in applicazioni web JSP / Servlet

Come posso evitare gli attacchi XSS in un’applicazione web JSP / Servlet?

XSS può essere prevenuto in JSP usando la funzione JSTL o fn:escapeXml() EL quando si visualizza (ri) l’input controllato dall’utente . Ciò include parametri di richiesta, intestazioni, cookie, URL, corpo, ecc. Tutto ciò che si estrae dall’object richiesta. Anche l’input controllato dall’utente da richieste precedenti che è memorizzato in un database deve essere salvato durante la visualizzazione di nuovo.

Per esempio:

 

Questo sfuggirà ai caratteri che potrebbero deformare l’HTML reso come < , > , " , ' e & in quadro HTML / XML come < > " ' e &

Si noti che non è necessario sfuggire a loro nel codice Java (Servlet), poiché sono innocui laggiù. Alcuni potrebbero scegliere di evitarli durante l'elaborazione della richiesta (come avviene in Servlet o Filter) anziché nell'elaborazione della risposta (come avviene in JSP), ma in questo modo si rischia che i dati vengano evitati a doppio escape (ad esempio & diventa &amp; invece di & e alla fine l'utente finale vedrebbe & viene presentato), o che i dati memorizzati dal DB diventano non portabili (es. quando si esportano dati in JSON, CSV, XLS, PDF, ecc. che non richiedono l'escape dell'HTML affatto). Perderai anche il controllo sociale perché non sai più ciò che l'utente ha effettivamente compilato. Come amministratore di un sito, ti piacerebbe sapere quali utenti / IP stanno cercando di eseguire XSS, in modo da poter facilmente rintracciare loro e agire di conseguenza. L'escaping durante l'elaborazione delle richieste dovrebbe essere utilizzato solo come ultima risorsa quando si ha realmente bisogno di riparare un disastro ferroviario di un'applicazione web legacy mal sviluppata nel più breve tempo ansible. Tuttavia, dovresti riscrivere i tuoi file JSP per diventare XSS-safe.

Se desideri visualizzare nuovamente l'input controllato dall'utente come HTML in cui desideri consentire solo un sottoinsieme specifico di tag HTML come , , , ecc, allora devi disinfettare l'input da un lista bianca. Puoi usare un parser HTML come Jsoup per questo. Ma, molto meglio è introdurre un linguaggio di markup amichevole come Markdown (usato anche qui su Stack Overflow). Quindi puoi usare un parser Markdown come CommonMark per questo. Ha anche incorporato funzionalità di sanitizzazione HTML. Vedi anche Sto cercando un codificatore Java HTML .

L'unica preoccupazione sul lato server per quanto riguarda i database è la prevenzione dell'iniezione SQL . È necessario assicurarsi che non si concatenano mai stringhe di input concatenate dall'utente nella query SQL o JPQL e che si stanno utilizzando query parametrizzate fino in fondo. In termini JDBC, ciò significa che è necessario utilizzare PreparedStatement anziché Statement . In termini JPA, utilizza Query .


Un'alternativa sarebbe quella di migrare da JSP / Servlet a Java MVE framework JSF di EE. Ha integrato la prevenzione XSS (e CSRF!) Ovunque. Vedi anche CSRF, XSS e SQL Injection attack prevention in JSF .

Il how-to-prevent-xss è stato chiesto più volte. Troverai molte informazioni in StackOverflow. Inoltre, il sito Web OWASP ha un foglio di trucchi di prevenzione XSS che dovresti esaminare.

Sulle librerie da utilizzare, la libreria ESAPI di OWASP ha un sapore java. Dovresti provarlo. Oltre a ciò, ogni framework che usi ha una certa protezione contro XSS. Anche in questo caso, il sito Web OWASP contiene informazioni sui framework più popolari, quindi consiglierei di visitare il loro sito.

Ho avuto grande fortuna con OWASP Anti-Samy e un consulente AspectJ su tutti i miei Spring Controller che blocca l’ingresso di XSS.

 public class UserInputSanitizer { private static Policy policy; private static AntiSamy antiSamy; private static AntiSamy getAntiSamy() throws PolicyException { if (antiSamy == null) { policy = getPolicy("evocatus-default"); antiSamy = new AntiSamy(); } return antiSamy; } public static String sanitize(String input) { CleanResults cr; try { cr = getAntiSamy().scan(input, policy); } catch (Exception e) { throw new RuntimeException(e); } return cr.getCleanHTML(); } private static Policy getPolicy(String name) throws PolicyException { Policy policy = Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml")); return policy; } } 

È ansible ottenere l’advisor AspectJ da questo post StackOverflow

Penso che questo sia un approccio migliore allora c: out in particolare se fai un sacco di javascript.

La gestione di XSS richiede più convalide, dati dal lato client.

  1. Validazioni di input (convalida del modulo) sul lato server. Ci sono molti modi per farlo. È ansible provare la convalida del bean JSR 303 ( hibernate validator ) o il framework di convalida dell’input di ESAPI . Anche se non l’ho ancora provato (ancora), c’è un’annotazione che controlla la sicurezza in html (@SafeHtml) . In effetti, potresti utilizzare il validatore di Hibernate con Spring MVC per le convalide dei bean -> Rif
  2. Richiesta di escape dell’URL – Per tutte le richieste HTTP, utilizzare una sorta di filtro XSS. Ho utilizzato quanto segue per la nostra app Web e si occupa della pulizia della richiesta dell’URL HTTP: http://www.servletsuite.com/servlets/xssflt.htm
  3. Escaping data / html restituito al client (vedi sopra alla spiegazione @BalusC).

Suggerisco di testare regolarmente le vulnerabilità utilizzando uno strumento automatico e di correggere qualsiasi cosa trovi. È molto più semplice suggerire una libreria per aiutare con una vulnerabilità specifica, quindi per tutti gli attacchi XSS in generale.

Skipfish è uno strumento open source di Google che ho indagato: trova un sacco di cose e sembra valere la pena di usarlo.

Non esiste una soluzione semplice e immediata contro XSS. L’API ESAPI OWASP ha un certo supporto per l’escaping che è molto utile e hanno librerie di tag.

Il mio approccio era sostanzialmente quello di estendere i tag 2 di stuts nei seguenti modi.

  1. Modifica s: tag di proprietà in modo che possa assumere attributi aggiuntivi che indicano quale tipo di escape è richiesto (escapeHtmlAttribute = “true” ecc.). Ciò comporta la creazione di nuove classi Property e PropertyTag. La class Property utilizza OPS ESAPI OWASP per l’escape.
  2. Cambia i modelli di freemarker per utilizzare la nuova versione di s: property e imposta l’escape.

Se non si desidera modificare le classi nel passaggio 1, un altro approccio consiste nell’importare i tag ESAPI nei modelli di freemarker ed eseguire l’escape in base alle esigenze. Quindi, se è necessario utilizzare come: tag di proprietà nel JSP, avvolgerlo con e tag ESAPI.

Ho scritto una spiegazione più dettagliata qui.

http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/

Sono d’accordo che sfuggire agli input non è l’ideale.

La mia opinione personale è che dovresti evitare di usare le pagine JSP / ASP / PHP / etc. Esegui invece l’output su un’API simile a SAX (progettato solo per le chiamate piuttosto che per la gestione). In questo modo c’è un singolo strato che deve creare un output ben formato.

Se vuoi sfuggire automaticamente a tutte le variabili JSP senza dover avvolgere esplicitamente ogni variabile, puoi utilizzare un resolver EL come descritto qui con full source e un esempio (JSP 2.0 o più recente) , e discusso più dettagliatamente qui :

Ad esempio, usando il risolutore EL sopra menzionato, il tuo codice JSP rimarrà tale, ma ciascuna variabile verrà automaticamente scappata dal resolver

 ...  

${item.name}

${item.price}

${item.description}

...

Se vuoi forzare l’escape di default in spring, puoi prendere in considerazione anche questo, ma non sfugge alle espressioni EL, basta taggare l’output, penso:

http://forum.springsource.org/showthread.php?61418-Spring-cross-site-scripting&p=205646#post205646

Nota: un altro approccio all’eliminazione di EL che utilizza le trasformazioni XSL per il preprocesso dei file JSP può essere trovato qui:

http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/