skip to content
usubeni fantasy logo Usubeni Fantasy

Traducción al español: Fundamentos obligatorios de seguridad web en el desarrollo frontend: SOP, CSRF y CORS

/ 9 min read

This Post is Available In: CN EN ES JA

Este texto se refiere principalmente a tres conceptos clave:

  • Política de mismo origen (Same-origin policy, abreviado como SOP)
  • Falsificación de solicitudes entre sitios (Cross-site request forgery, abreviado como CSRF)
  • Compartir recursos entre orígenes (Cross-Origin Resource Sharing, abreviado como CORS)

Política de mismo origen (SOP)

Mismo origen

Primero, vamos a explicar qué significa mismo origen: si el protocolo, el nombre de dominio y el puerto son iguales, entonces es mismo origen.

urlMismo origen
https://niconico.comBase
https://niconico.com/spirit
https://sub.niconico.com/spiritNo
http://niconico.com/spiritNo
https://niconico.com:8080/spiritNo

Restricciones

El motivo por el cual te encuentras con el problema de la restricción de origen cruzado es precisamente debido a las diversas restricciones de SOP. Pero, ¿qué restricciones impone exactamente?

Si dices que SOP “restringe la obtención de recursos de origen no coincidente”, eso no es correcto. El ejemplo más simple es cuando se permite el acceso a recursos como imágenes, archivos CSS y JavaScript que se están referenciando desde otro origen.

Si dices que SOP “prohíbe las solicitudes de origen cruzado”, eso tampoco es correcto. En realidad, la esencia de SOP no es prohibir las solicitudes de origen cruzado, sino interceptar las respuestas de las solicitudes.

En realidad, SOP se puede dividir en dos casos:

  • Se permite la referencia normal de iframes, imágenes y otros recursos, pero se restringe la manipulación de su contenido.
  • Se restringen directamente las solicitudes AJAX, más precisamente, se restringe la manipulación de los resultados de las solicitudes AJAX, lo cual da lugar al CSRF que se mencionará más adelante.

Sin embargo, en esencia, estas dos situaciones son iguales: en resumen, los navegadores pueden “usar directamente” recursos que no son del mismo origen, pero los programadores y los usuarios no pueden manipular estos datos para evitar comportamientos maliciosos. Esto es una de las formas en que los navegadores modernos protegen a los usuarios.

A continuación se presentan tres ejemplos que se pueden encontrar en aplicaciones prácticas:

  • Realizar solicitudes AJAX a una API de origen cruzado, es el caso más común y una pesadilla para los principiantes en el desarrollo web.
  • Comunicación entre iframes y la página principal (como obtener el DOM o variables), esto ocurre con menos frecuencia y tiene soluciones más sencillas.
  • Manipulación de imágenes de origen cruzado (por ejemplo, imágenes provenientes de la etiqueta <img>), esto se encuentra al trabajar con imágenes en un lienzo (canvas).

Si no existiera SOP:

  • La información confidencial dentro de los iframes podría ser leída sin restricciones.
  • Se podrían realizar ataques de falsificación de solicitudes entre sitios (CSRF) de manera más desenfrenada.
  • Las interfaces podrían ser utilizadas de manera abusiva por terceros.

Evitar las restricciones de origen cruzado

Aunque SOP brinda mayor seguridad a los usuarios, también puede causar ciertos problemas para los programadores, ya que a veces es necesario tener solicitudes de origen cruzado para ciertos casos de uso. Debido a limitaciones de espacio y a la gran cantidad de artículos relacionados disponibles en línea, no se abordarán aquí las soluciones para evitar las restricciones de origen cruzado. Sin embargo, se proporcionarán algunas palabras clave:

Para solicitudes AJAX:

  • Utilizar JSONP
  • Configurar CORS en el servidor
  • Utilizar un proxy inverso en el servidor
  • Utilizar WebSockets

Para iframes:

  • Utilizar location.hash o window.name para la comunicación de información
  • Utilizar postMessage

Falsificación de solicitudes entre sitios (CSRF)

Descripción general

La falsificación de solicitudes entre sitios (Cross-site request forgery, CSRF) es una forma común de ataque. Se refiere a cuando un sitio web A ha iniciado sesión correctamente y ha guardado la información de inicio de sesión en una cookie, y otro sitio web B utiliza algún método para llamar a la API del sitio web A y realizar operaciones, y la API de A automáticamente incluye la cookie en la solicitud.

Como se mencionó anteriormente, SOP permite cargar recursos a través de etiquetas HTML y no bloquea las solicitudes de API, sino que intercepta las respuestas. CSRF aprovecha precisamente estas dos ventajas.

Para solicitudes GET, simplemente se pueden incluir en una etiqueta <img> para realizar solicitudes a una API de origen cruzado sin que nadie se dé cuenta.

Para solicitudes POST, muchos ejemplos utilizan el envío de formularios:

<form action="<nowiki>http://bank.com/transfer.do</nowiki>" method="POST">
<input type="hidden" name="acct" value="MARIA" />
<input type="hidden" name="amount" value="100000" />
<input type="submit" value="Ver mis fotos" />
</form>

Por lo tanto, SOP no puede ser utilizado como método de prevención de CSRF.

Al revisar las limitaciones de SOP, ambos ejemplos realizan solicitudes directamente utilizando etiquetas HTML, y los navegadores permiten esto debido a que no puedes operar directamente los resultados obtenidos mediante JavaScript.

SOP y AJAX

En el caso de las solicitudes AJAX, después de obtener los datos, puedes realizar operaciones de JavaScript libremente. En este caso, aunque la política de mismo origen evita la respuesta, aún se envía la solicitud. Esto se debe a que el navegador es el que ejecuta la respuesta de intercepción, no el programa del servidor. De hecho, tu solicitud ya ha sido enviada al servidor y ha devuelto un resultado, pero debido a las políticas de seguridad, el navegador no te permite continuar con las operaciones de JavaScript, por lo que muestra el mensaje que conoces: blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource..

Por lo tanto, es importante enfatizar nuevamente que la política de mismo origen no puede ser utilizada como método de prevención de CSRF.

Sin embargo, todavía hay excepciones que pueden prevenir el CSRF. El navegador no permite que todas las solicitudes se envíen correctamente, y la situación anterior solo se aplica a solicitudes simples, lo cual se explicará en detalle en la siguiente sección sobre CORS.

Contramedidas contra CSRF

SOP se ve afectado por CSRF, pero ¿realmente no tiene ningún beneficio?

¡No es así! ¿Recuerdas que SOP limita el espacio de nombres de las cookies? Aunque la solicitud automáticamente incluye las cookies, el atacante aún no puede acceder directamente al contenido de las cookies en sí.

Entonces, para hacer frente al CSRF, se puede utilizar el siguiente enfoque: el método de autenticación comúnmente utilizado en la separación entre el frontend y el backend, que es la autenticación mediante tokens, y no almacenar el token en las cookies, sino agregarlo manualmente en el encabezado de la solicitud.

Otro método es: incluir la información de la cookie en la solicitud a través de la consulta, el cuerpo o el encabezado. Cuando la solicitud llega al servidor, no se verifica la información enviada por la cookie, solo se verifica el campo personalizado. Si es correcto, entonces es una solicitud enviada por el dominio local que puede ver la cookie, lo cual no es posible con CSRF. (Este método se utiliza para la separación entre el frontend y el backend, mientras que en la representación del backend se puede escribir directamente en el DOM)

El código de ejemplo es el siguiente:

var csrftoken = Cookies.get("csrfToken");
function csrfSafeMethod(method) {
// estos métodos HTTP no requieren protección CSRF
return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method);
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("x-csrf-token", csrftoken);
}
},
});

Compartir recursos de origen cruzado (CORS)

El origen cruzado es una restricción del navegador, y el intercambio de recursos de origen cruzado (Cross-origin resource sharing, CORS) es el resultado de la coordinación entre el servidor y el navegador.

Si el servidor ha configurado la configuración relacionada con CORS, se agregará Access-Control-Allow-Origin en el encabezado de respuesta enviado al navegador. Si el valor de este campo coincide con el origen actual, el navegador desbloqueará la restricción de origen cruzado.

HTTP/1.1 200 OK
Fecha: Dom, 24 Abr 2016 12:43:39 GMT
Servidor: Apache
Access-Control-Allow-Origin: http://www.acceptmeplease.com
Keep-Alive: timeout=2, max=100
Conexión: Keep-Alive
Tipo de contenido: application/xml
Longitud del contenido: 423

En cuanto a CORS, hay dos tipos de solicitudes.

Solicitud simple

  • El método de solicitud es GET, POST o HEAD
  • El Content-Type se establece como application/x-www-form-urlencoded, multipart/form-data o text/plain

Todas las solicitudes que cumplan con estas dos condiciones se consideran solicitudes CORS simples. Las solicitudes simples se envían directamente al servidor, lo que puede causar CSRF.

Solicitud de pre-vuelo

Las solicitudes que no cumplen con los requisitos de una solicitud simple deben enviar primero una solicitud de pre-vuelo (Preflight Request). El navegador envía una solicitud de método OPTIONS al servidor antes de enviar la solicitud real para preguntar si el origen actual cumple con el objetivo CORS. Solo después de que se haya verificado se envía la solicitud formal.

Por ejemplo, una solicitud POST que utiliza application/json para los parámetros no es una solicitud simple y será interceptada durante la solicitud de pre-vuelo.

Otro ejemplo es una solicitud PUT, que también enviará una solicitud de pre-vuelo.

La excepción mencionada anteriormente, que puede prevenir CSRF, se refiere a la solicitud de pre-vuelo. Incluso si se realiza una solicitud de pre-vuelo exitosa para una solicitud de origen cruzado, la solicitud real no se enviará, lo que garantiza que el CSRF no tenga éxito.

CORS y cookies

A diferencia de las solicitudes en el mismo dominio, las solicitudes CORS no envían de forma predeterminada cookies ni información de autenticación HTTP. Tanto el cliente como el servidor deben configurar la solicitud para incluir cookies.

Por eso, cuando se realiza una solicitud CORS con axios, es necesario establecer withCredentials: true.

A continuación se muestra la configuración CORS del framework de backend de node.js, Koa:

/**
* Middleware de CORS
*
* @param {Object} [options]
* - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, el valor predeterminado es el encabezado Origin de la solicitud
* - {String|Array} allowMethods `Access-Control-Allow-Methods`, el valor predeterminado es 'GET,HEAD,PUT,POST,DELETE,PATCH'
* - {String|Array} exposeHeaders `Access-Control-Expose-Headers`
* - {String|Array} allowHeaders `Access-Control-Allow-Headers`
* - {String|Number} maxAge `Access-Control-Max-Age` en segundos
* - {Boolean} credentials `Access-Control-Allow-Credentials`
* - {Boolean} keepHeadersOnError Agregar encabezados establecidos a `err.header` si se produce un error
* @return {Function} Middleware de CORS
* @api public
*/

Por cierto, cuando Access-Control-Allow-Credentials se establece en true, Access-Control-Allow-Origin no puede ser * por motivos de seguridad. Es un poco complicado…

Próximamente

Por ahora, eso es todo. Si tienes alguna pregunta, por favor, déjala en los comentarios. En el futuro, también hablaré sobre temas como XSS, CSP y http/https.

Referencias

评论组件加载中……