Prevención de XSS en la aplicación web JSP / Servlet

¿Cómo puedo prevenir ataques XSS en una aplicación web JSP / Servlet?

XSS puede prevenirse en JSP utilizando la etiqueta JSTL o la función EL fn:escapeXml() al (re) mostrar la entrada controlada por el usuario . Esto incluye parámetros de solicitud, encabezados, cookies, URL, cuerpo, etc. Cualquier cosa que extraiga del objeto de solicitud. Además, la entrada controlada por el usuario de solicitudes anteriores que se almacena en una base de datos debe escaparse durante la nueva visualización.

Por ejemplo:

 

Esto escapará a los caracteres que pueden deformar el HTML renderizado, como < , > , " , ' y & en entidades HTML / XML como < > " , ' y &

Tenga en cuenta que no necesita escapar de ellos en el código de Java (Servlet), ya que son inofensivos allí. Algunos pueden optar por escapar de ellos durante el procesamiento de solicitud (como lo hace en Servlet o Filtro) en lugar de procesar la respuesta (como lo hace en JSP), pero de esta manera puede arriesgarse a que los datos escapen innecesariamente (por ejemplo, & convierte en &amp; lugar de & y, en última instancia, el usuario final vería & se presentaría), o que los datos almacenados en base de datos se vuelven inservibles (por ejemplo, al exportar datos a JSON, CSV, XLS, PDF, etc. que no requieren escapado de HTML) en absoluto). También perderás el control social porque ya no sabrás qué ha rellenado el usuario. Sería muy útil para el administrador del sitio saber qué usuarios / IP intentan realizar XSS, para que puedas rastrear fácilmente ellos y tomar acciones en consecuencia. El escapado durante el proceso de solicitud solo debe usarse como último recurso cuando realmente necesite arreglar un accidente de tren de una aplicación web heredada mal desarrollada en el menor tiempo posible. Aún así, en última instancia, debe volver a escribir sus archivos JSP para que sean seguros para XSS.

Si desea volver a mostrar la entrada controlada por el usuario como HTML en la que le gustaría permitir solo un subconjunto específico de tags HTML como , , , etc., debe desinfectar la entrada mediante un lista blanca Puede usar un analizador HTML como Jsoup para esto. Pero, mucho mejor es introducir un lenguaje de marcado amigable para los humanos como Markdown (también usado aquí en Stack Overflow). Entonces puede usar un analizador de Markdown como CommonMark para esto. También tiene capacidades integradas de desinfección HTML. Ver también estoy buscando un codificador Java HTML .

La única preocupación en el lado del servidor con respecto a las bases de datos es la prevención de inyección SQL . Debe asegurarse de que nunca concatete cadenas de entrada controlada por el usuario directamente en la consulta SQL o JPQL y que está utilizando consultas parametrizadas todo el camino. En términos de JDBC, esto significa que debe usar PreparedStatement lugar de Statement . En términos de JPA, use Query .


Una alternativa sería migrar de JSP / Servlet a Java EE MVC framework JSF . Tiene incluida la prevención XSS (y CSRF!) En todos los lugares. Consulte también prevención de ataques de inyección CSRF, XSS y SQL en JSF .

El cómo-prevenir-xss ha sido preguntado varias veces. Encontrará mucha información en StackOverflow. Además, el sitio web de OWASP tiene una hoja de trucos de prevención de XSS que debe pasar.

En las bibliotecas para usar, la biblioteca ESAPI de OWASP tiene un sabor java. Deberías probarlo. Además de eso, cada marco que uses tiene cierta protección contra XSS. De nuevo, el sitio web de OWASP tiene información sobre los marcos más populares, por lo que recomendaría visitar su sitio.

Tuve mucha suerte con OWASP Anti-Samy y un asesor de AspectJ en todos mis controladores de spring que bloquea el ingreso de 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; } } 

Puedes obtener el asesor de AspectJ desde la publicación stackoverflow

Creo que este es un mejor enfoque que c: especialmente si haces un montón de javascript.

La administración de XSS requiere múltiples validaciones, datos del lado del cliente.

  1. Validaciones de entrada (validación de formulario) en el lado del servidor. Hay múltiples formas de hacerlo. Puede probar la validación de beans JSR 303 ( validador de hibernación ) o el marco de Validación de entradas ESAPI . Aunque todavía no lo he probado (todavía), hay una anotación que comprueba html seguro (@SafeHtml) . De hecho, podría utilizar el validador Hibernate con Spring MVC para validaciones de frijoles -> Ref.
  2. Escapar solicitudes de URL : para todas sus solicitudes HTTP, use algún tipo de filtro XSS. He utilizado lo siguiente para nuestra aplicación web y se encarga de limpiar la solicitud HTTP URL – http://www.servletsuite.com/servlets/xssflt.htm
  3. Escaping data / html devuelto al cliente (mire arriba en la explicación de @BalusC).

Sugeriría regularmente probar vulnerabilidades usando una herramienta automatizada, y arreglar lo que encuentre. Es mucho más fácil sugerir una biblioteca para ayudar con una vulnerabilidad específica que luego para todos los ataques XSS en general.

Skipfish es una herramienta de código abierto de Google que he estado investigando: encuentra muchas cosas y parece que vale la pena usarlas.

No hay una solución sencilla y lista para usar contra XSS. La API OWASP ESAPI tiene algo de apoyo para el escape que es muy útil, y tienen bibliotecas de tags.

Mi enfoque fue básicamente extender las tags de los stuts 2 de las siguientes maneras.

  1. Modifique s: etiqueta de propiedad para que pueda tomar atributos adicionales que indiquen qué tipo de escape se requiere (escapeHtmlAttribute = “true”, etc.). Esto implica la creación de nuevas clases Property y PropertyTag. La clase de propiedad usa la api de OWASP ESAPI para el escape.
  2. Cambie las plantillas de freemarker para usar la nueva versión de la propiedad s: y configure el escape.

Si no desea modificar las clases en el paso 1, otro enfoque sería importar las tags ESAPI en las plantillas de freemarker y escaparse según sea necesario. Luego, si necesita usar como: etiqueta de propiedad en su JSP, envuélvala con una etiqueta ESAPI.

He escrito una explicación más detallada aquí.

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

Estoy de acuerdo en que escapar de las entradas no es lo ideal.

Mi opinión personal es que debe evitar el uso de páginas JSP / ASP / PHP / etc. En su lugar, se envía a una API similar a SAX (solo diseñada para llamadas en lugar de para el manejo). De esta forma, hay una sola capa que debe crear una salida bien formada.

Si desea escaparse automáticamente de todas las variables JSP sin tener que envolver explícitamente cada variable, puede usar una resolución EL como se detalla aquí con fuente completa y un ejemplo (JSP 2.0 o más reciente) , y se discute con más detalle aquí :

Por ejemplo, al usar la resolución EL anteriormente mencionada, su código JSP seguirá siendo así, pero el solucionador escapará automáticamente cada variable

 ...  

${item.name}

${item.price}

${item.description}

...

Si desea forzar el escape por defecto en spring, podría considerar esto también, pero no escapa a las expresiones EL, solo etiquete el resultado, creo:

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

Nota: Aquí se puede encontrar otro enfoque del escape EL que usa transformaciones XSL para preprocesar archivos JSP:

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