Seguridad de front-end (3): prevención de secuencias de comandos entre sitios (XSS)

1. Cómo prevenir XSS

Los ataques XSS tienen dos elementos:

  • El atacante envía código malicioso.

  • El navegador ejecuta código malicioso.

Para el primer elemento: ¿podemos filtrar el código malicioso introducido por el usuario en el proceso de entrada del usuario?

Filtro de entrada

Cuando el usuario envía, la entrada es filtrada por el front-end y luego enviada al back-end. es posible? La respuesta es de ninguna manera. Una vez que el atacante pasa por alto el filtrado de front-end y construye directamente la solicitud, se puede enviar el código malicioso. Luego, cambie el tiempo de filtrado: el backend filtra la entrada antes de escribir en la base de datos y luego devuelve el contenido "seguro" al frontend. ¿Es esto factible? Tomemos un ejemplo: un usuario normal ingresó el contenido 5 <7, que se escapó antes de ser escrito en la base de datos y se convirtió en 5 <7. El problema es: en la etapa de envío, no estamos seguros de dónde generar el contenido.

Este "no estoy seguro de dónde generar el contenido" tiene dos significados:

  1. El contenido de entrada del usuario puede proporcionarse a la interfaz y al cliente al mismo tiempo, y una vez que se pasa escapeHTML (), el contenido mostrado por el cliente se vuelve confuso (5 <7).

  2. En la parte frontal, las diferentes posiciones requieren diferentes códigos.

  • Cuando se utiliza como una página de empalme HTML 5 <7, se puede mostrar normalmente:
<div title="comment">5 &lt; 7</div>
  • Cuando se devuelve 5 <7 a través de Ajax y luego se asigna a una variable de JavaScript, la cadena obtenida por la interfaz es el carácter de escape. Este contenido no se puede utilizar directamente para la visualización de plantillas como Vue, ni se puede utilizar directamente para calcular la longitud del contenido. No se puede utilizar para títulos, alertas, etc.

Por lo tanto, el filtrado del lado de entrada puede resolver problemas específicos de XSS en algunos casos, pero introducirá mucha incertidumbre y problemas confusos. Estos métodos deben evitarse al prevenir ataques XSS.

Por supuesto, para tipos de entrada claros, como números, URL, números de teléfono, direcciones de correo electrónico, etc., aún es necesario filtrar la entrada.

Dado que el filtrado de entrada no es completamente confiable, debemos evitar XSS "evitando que el navegador ejecute código malicioso". Esta parte se divide en dos categorías:

  • Evita la inyección en HTML.

  • Evite que se ejecute código malicioso cuando se ejecuta JavaScript.

Evite los ataques XSS de almacenamiento y reflexión

Los XSS almacenados y reflectantes se eliminan del servidor y se insertan en el HTML de respuesta. Los "datos" escritos por el atacante están incrustados en el "código" y ejecutados por el navegador.

Hay dos formas comunes de prevenir estas dos vulnerabilidades:

  • Cambie a la representación pura de front-end para separar código y datos.

  • Escapa completamente de HTML.

Renderizado puro de front-end

El proceso de renderizado puro de front-end:

  1. El navegador primero carga un HTML estático, que no contiene ningún dato relacionado con la empresa.

  2. Luego, el navegador ejecuta JavaScript en HTML.

  3. JavaScript carga datos comerciales a través de Ajax y llama a DOM API para actualizarlos en la página.

En el renderizado de front-end puro, le diremos claramente al navegador: si el contenido que se configurará a continuación es texto (.innerText), atributo (.setAttribute) o estilo (.style), etc. El navegador no se dejará engañar fácilmente y ejecutará un código inesperado. Pero la representación pura de front-end también debe prestar atención para evitar vulnerabilidades XSS de tipo DOM (como evento onload y javascript: xxx en href, etc., consulte la sección "Prevención de ataques XSS de tipo DOM" a continuación) . En muchos sistemas internos y de gestión, la representación pura de front-end es muy apropiada. Pero para las páginas con requisitos de alto rendimiento o requisitos de SEO, todavía tenemos que enfrentar el problema de empalmar HTML.

Escape HTML

Si es necesario empalmar HTML, debe usar una biblioteca de escape adecuada para escapar completamente de los puntos de inserción en la plantilla HTML. Los motores de plantilla de uso común, como doT.js, ejs, FreeMarker, etc., generalmente solo tienen una regla para el escape HTML, que es escapar del carácter & <> "'/, que de hecho puede reproducir un XSS determinado. La función de protección no es perfecto, por lo que para mejorar las medidas de protección XSS, necesitamos utilizar estrategias de escape más completas y detalladas. Por ejemplo, en los proyectos Java, la biblioteca de escape más utilizada es org.owasp.encoder. Las siguientes citas de código Use el código oficial instrucciones de org.owasp.encoder.

<!-- HTML 标签内⽂字内容 --> 
<div><%= Encode.forHtml(UNTRUSTED) %></div> 
<!-- HTML 标签属性值 --> 
<input value="<%= Encode.forHtml(UNTRUSTED) %>" /> 
<!-- CSS 属性值 -->
 <div style="width:<= Encode.forCssString(UNTRUSTED) %>"> 
 <!-- CSS URL --> 
 <div style="background:<= Encode.forCssUrl(UNTRUSTED) %>"> 
 <!-- JavaScript 内联代码块 --> 
 <script> var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>"; alert(msg); </script> 
 <!-- JavaScript 内联代码块内嵌 JSON --> 
 <script> var INITIAL_STATE = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>'); </script> 
 <!-- HTML 标签内联监听器 --> 
 <button onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');"> click me </button>
 <!-- URL 参 数 --> 
 <a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top"> 
 <!-- URL 路 径 --> 
 <a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>"> 
 <!--URL. 注意:要根据项⽬情况进⾏过滤,禁⽌掉 "javascript:" 链接、⾮法 scheme 等 --> 
 <a href='<%= urlValidator.isValid(UNTRUSTED) ? Encode.forHtml(UNTRUSTED) : "/404" %>'>link </a>

Sin embargo, la codificación de HTML es muy complicada y las reglas de escape correspondientes deben usarse en diferentes contextos.

Prevenir ataques XSS de tipo DOM

Los ataques XSS de tipo DOM son en realidad que el código JavaScript en la parte frontal del sitio web no es lo suficientemente riguroso y los datos que no son de confianza se ejecutan como código. Tenga especial cuidado al usar .innerHTML, .outerHTML, document.write (), no inserte datos que no sean de confianza como HTML en la página, pero intente usar .textContent, .setAttribute (), etc.

Si usa la pila de tecnología Vue / React y no usa las funciones v-html y dangerouslySetInnerHTML, puede evitar los peligros ocultos XSS de innerHTML y outerHTML en la etapa de renderizado de front-end.

Los detectores de eventos en línea en el DOM, como ubicación, onclick, onerror, onload, onmouseover, etc., el atributo href de la etiqueta y eval (), setTimeout (), setInterval (), etc. de JavaScript, pueden operar todos en cadenas como código. Si los datos que no son de confianza se empalman en una cadena y se pasan a estas API, es fácil generar riesgos de seguridad, así que evítelo.

<!-- 内联事件监听器中包含恶意代码 --> 
![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/3e724ce0.data:image/png,) 
<!-- 链接内包含恶意代码 --> 
<a href="UNTRUSTED">1</a> 
<script> 
// setTimeout()/setInterval() 中调⽤恶意代码 
setTimeout("UNTRUSTED") 
setInterval("UNTRUSTED") 
// location 调⽤恶意代码
location.href = 'UNTRUSTED' 
// eval() 中调⽤恶意代码 
eval("UNTRUSTED") </script>

Si estos elementos se utilizan en el proyecto, asegúrese de evitar la concatenación de datos que no sean de confianza en la cadena.

Otras medidas preventivas XSS

Aunque un escape cuidadoso puede evitar la aparición de XSS al renderizar páginas y ejecutar JavaScript, no es suficiente confiar únicamente en la precaución del desarrollo. A continuación, se muestran algunos escenarios comunes que pueden reducir los riesgos y las consecuencias de XSS.

Política de seguridad de contenido

La CSP estricta puede desempeñar las siguientes funciones en la prevención de XSS:

  • Está prohibido cargar códigos de dominio externo para evitar una lógica de ataque compleja.

  • Está prohibido el envío desde dominios externos. Después de que el sitio web sea atacado, los datos del usuario no se filtrarán a dominios externos.

  • La ejecución de scripts en línea está prohibida (las reglas son más estrictas y actualmente GitHub las usa).

  • Se prohíbe la ejecución de scripts no autorizados (nueva función, la versión móvil de Google Map está en uso).

  • El uso adecuado de los informes puede descubrir XSS a tiempo, lo que ayudará a solucionar el problema lo antes posible.

2. Control de longitud del contenido de entrada

Para las entradas que no son de confianza, debe haber un límite razonable. Aunque es imposible evitar por completo que se inicie XSS, puede aumentar la dificultad de los ataques XSS.

3. Otras medidas de seguridad

  • Cookie solo HTTP: JavaScript está prohibido para leer algunas cookies sensibles. Los atacantes no pueden robar esta cookie incluso después de completar el registro XSS.

  • Código de verificación: Evite que los scripts que se hacen pasar por usuarios envíen operaciones peligrosas.

Supongo que te gusta

Origin blog.csdn.net/imagine_tion/article/details/110952024
Recomendado
Clasificación