validate - Prevención de ataques de inyección CSRF, XSS y SQL en JSF
token csrf (2)
Tengo una aplicación web construida en JSF con MySQL como DB. Ya implementé el código para evitar CSRF en mi aplicación.
Ahora que mi framework subyacente es JSF, creo que no tengo que manejar el ataque XSS ya que UIComponent
maneja. No estoy usando ningún JavaScript en ninguna de las páginas de vista. Incluso si uso, ¿realmente necesito implementar código para evitar ataques XSS?
Para DB estamos usando declaraciones preparadas y procedimientos almacenados en todas las interacciones de DB.
¿Hay algo más que deba manejarse para prevenir estos 3 ataques comunes? Ya he OWASP sitio de OWASP y sus hojas de trucos .
¿Debo ocuparme de otros posibles vectores de ataque?
No estoy usando ningún JavaScript en ninguna de las páginas de vista. Incluso si uso, realmente necesito implementar código para eludir el ataque XSS.
Puede ser vulnerable a XSS incluso si no usa JavaScript en sus páginas. XSS ocurre cuando incorpora contenido controlado por un atacante sin una codificación adecuada.
Cada vez que haces algo como
response.write("<b>" + x + "</b>")
donde un atacante puede hacer que x
contenga HTML que contenga JavaScript, entonces usted es vulnerable a XSS.
La solución generalmente no es escribir grandes cantidades de código. Normalmente, la solución es codificar $x
y cualquier otro valor controlado por un atacante antes de incluirlos en el HTML que genere.
response.write("<b>" + escapePlainTextToHtml(x) + "</b>")
Filtrar o desinfectar las entradas puede ayudar a proporcionar una capa adicional de protección.
<shameless-plug>
También puede usar un lenguaje de plantilla que codifica la salida automáticamente para proteger contra XSS.
La plantilla de cierre es una de esas opciones para Java.
El autoescalado contextual funciona al aumentar las plantillas de cierre para codificar adecuadamente cada valor dinámico en función del contexto en el que aparece, defendiendo así contra las vulnerabilidades XSS en valores controlados por un atacante.
EDITAR
Como está utilizando JSF, debe leer sobre la mitigación de XSS en JSF :
Texto de salida de escape
<h:outputText/>
y<h:outputLabel/>
de forma predeterminada tiene el atributo de escape establecido en True. Al usar esta etiqueta para mostrar resultados, puede mitigar la mayoría de la vulnerabilidad XSS.SeamTextParser y
<s:formattedText/>
Si desea permitir que los usuarios utilicen algunas de las etiquetas html básicas para personalizar sus entradas, JBoss Seam proporciona una etiqueta
<s:formattedText/>
que permite algunas etiquetas y estilos html básicos especificados por los usuarios.
XSS
JSF está diseñado para tener incluida la prevención XSS. Puede volver a mostrar de forma segura todas las entradas controladas por el usuario (solicitar encabezados (¡incluidas las cookies!), Solicitar parámetros (también los guardados en DB!) Y cuerpos de solicitud (archivos de texto cargados, etc.) utilizando cualquier componente JSF.
<h:outputText value="#{user.name}" />
<h:outputText value="#{user.name}" escape="true" />
<h:inputText value="#{user.name}" />
etc...
Tenga en cuenta que cuando usa JSF 2.0 en Facelets, puede usar EL en el texto de la plantilla de esta manera:
<p>Welcome, #{user.name}</p>
Esto también será implícitamente escapado. No necesariamente necesitas <h:outputText>
aquí.
Solo cuando está explícitamente extrayendo la entrada controlada por el usuario usando escape="false"
:
<h:outputText value="#{user.name}" escape="false" />
¡entonces tienes un potencial agujero de ataque 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 etiquetas HTML como <b>
, <i>
, <u>
, etc., debe desinfectar la entrada mediante un lista blanca El analizador de HTML Jsoup es muy helpful en esto.
itemLabelEscaped
en Mojarra <2.2.6
Las versiones anteriores de Mojarra anteriores a la 2.2.6 tenían el error por el cual <f:selectItems itemLabel>
incorrectamente deja la etiqueta sin guardar cuando proporcionaba una List<T>
través de <f:selectItems var>
lugar de List<SelectItem>
o SelectItem[]
como valor ( problema 3143 ). En otras palabras, si está redistribuyendo datos controlados por el usuario como etiquetas de elementos a través de una List<T>
, entonces tiene un posible agujero XSS. Si la actualización a Mojarra 2.2.6 como mínimo no es una opción, entonces debe establecer explícitamente el atributo itemLabelEscaped
en true
para evitar eso.
<f:selectItems value="#{bean.entities}" var="entity" itemValue="#{entity}"
itemLabel="#{entity.someUserControlledProperty}" itemLabelEscaped="true" />
CSRF
JSF 2.x ya ha incorporado la prevención de CSRF en el sabor del campo oculto javax.faces.ViewState
en el formulario cuando se usa el ahorro de estado del lado del servidor. En JSF 1.x este valor era bastante débil y demasiado fácil de predecir (en realidad nunca fue pensado como prevención de CSRF). En JSF 2.0, esto se ha mejorado mediante el uso de un valor autogenerado largo y fuerte en lugar de un valor de secuencia bastante predecible y, por lo tanto, una sólida prevención de CSRF.
En JSF 2.2, esto se mejora aún más al convertirlo en una parte requerida de la especificación JSF, junto con una clave AES configurable para encriptar el estado del lado del cliente, en caso de que el ahorro de estado del lado del cliente esté habilitado. Consulte también la especificación JSF número 869 y Reutilización del valor de ViewState en otra sesión (CSRF) . Nuevo en JSF 2.2 es la protección CSRF en las solicitudes GET por <protected-views>
.
Solo cuando usa vistas sin estado como en <f:view transient="true">
, o hay un agujero de ataque XSS en alguna parte de la aplicación, entonces tiene un posible agujero de ataque CSRF.
inyección SQL
Esto no es responsabilidad de JSF. Cómo evitar esto depende de la API de persistencia que esté utilizando (JDBC sin formato, JPA moderna o Hibernate antiguo), pero todo se reduce a que nunca debe concatenar la entrada controlada por el usuario en cadenas de SQL como lo hace
String sql = "SELECT * FROM user WHERE username = ''" + username + "'' AND password = md5(" + password + ")";
String jpql = "SELECT u FROM User u WHERE u.username = ''" + username + "'' AND u.password = md5(''" + password + "'')";
Imagine lo que sucedería si el usuario final elige el siguiente nombre:
x''; DROP TABLE user; --
Siempre debe usar consultas parametrizadas donde corresponda.
String sql = "SELECT * FROM user WHERE username = ? AND password = md5(?)";
String jpql = "SELECT u FROM User u WHERE u.username = ?1 AND u.password = md5(?2)";
En JDBC simple necesita usar PreparedStatement
para llenar los valores de los parámetros y en JPA (e Hibernate), el objeto Query
ofrece setters para esto.