Cuando agregas soporte para Persona en tu sitio web, ella toma tantas medidas de seguridad como puede. Sin embargo, algunas medidas de seguridad solo pueden ser manejadas por tu sitio web. Estas son listadas a continuación.
Prácticas Esenciales
Verificar la confirmación en tu servidor
Cuando utilizas Persona, las declaraciones de identidad son pasadas dentro de la función onlogin
a través de
Siempre debes pasar la aserción a tu servidor para verificarla, y solo tu servidor debe decidir si autoriza al usuario permisos adicionales en base al resultado de la verificación:
// Inside navigator.id.watch({ ... onlogin: function(assertion) { // A user wants to log in! Here you need to: // 1. Send the assertion to your backend for verification and to create a session. // 2. Update your UI. },
Si trata de verificar la aserción usando JavaScript ejecutándose en el navegador del usuario, algún usuario malicioso podría suplantar por otro usuario legítimo de su sitio inyectando código bloqueando tu código JavaScript. Esto es posible debido a que no se tiene control del navegador del usuario, donde se ejecuta el código.
Como mencionamos lineas arriba, siempre debe pasar la aserción a su servidor para la verificación. Incluso si está usando la API de verificación remota.
Especifique explícitamente el parámetro audience
Para verificar la aserción, debe realizar un pedido POST
a https://verifier.login.persona.org/verify
. El pedido incluye el parámetro llamado audience
:
assertion=<ASSERTION>&audience=https://mysite.com:443"
El parámetro audience
es requerido. Siempre debe especificar explícitamente audience en el código, o en la configuración del código. Específicamente:
- No confie en la cabecera o header Host enviado por el navegador del usuario.
- No confíe en el parámetro explicito enviado por el navegador del usuario, pero generado usando JavaScript, e.g.
document.location
.
Si dejas que el navegador del usuario te envíe el parámetro audience
, esto deja la posibilidad de que un sitio web malicioso pueda reusar las declaraciones de su sitio web para autenticarse en tu sitio web.
Verifica los certificados SSL
Para verificar una aserción, debes realizar un petición POST a https://verifier.login.persona.org/verify
. Debes asegurarte que tu petición HTTPS verifique el certificado enviado desde el servidor contra un certificado raíz confiable. Si no lo haces, un atacante podría presentarse como verifer.login.persona.org
y realizar verificaciones falsas.
Revisa que la libreria que usas para hacer el pedido verifique los certificados correctamente, y que has iniciado esto con un certificado de administrador apropiado.
Por ejemplo, el modulo urllib2 estándar de Python 2.7 no valida certificados del servidor. En lugar de ello, recomendamos utilizar los módulos "requests" o "urllib3" en Python 2.x, o la clase estándar http.client.HTTPSConnection
en Python 3.x. Para Perl, asegúrate que usas al menos la versión 6.0 de libwww-perl
. Dependiendo del lenguaje, librería, y sistema operativo que estés usando, vas a necesitar utilizar algún CA (Certificate Authority) confiable o el CA simple usado por verifier.login.persona.org
.
Implementar protección CSRF
En un ataque de inicio de sesión por CSRF (Cross-Site Request Forgery), el atacante utiliza CSRF para iniciar la sesión del usuario dentro del sitio web usando las credenciales del atacante.
Por ejemplo: un usuario visita una web maliciosa que contiene un elemento form
. El atributo action
del form
está configurado para hacer una petición HTTP POST a https://www.google.com/login, dándole el username y password del atacante. Cuando el usuario envía el form
, el pedido es enviado a Google, se inicia sesión y el servidor de Google configura una cookie en el navegador del usuario. Ahora el usuario sin saberlo ha iniciado sesión con la cuenta Google del atacante.
El ataque puede ser usado para reunir información sensible del usuario. Por ejemplo, Web History de Google tiene la característica de registrar todos los términos de búsqueda del usuario. Si el usuario inicia sesión dentro de la cuenta Google del atacante y el atacante tiene la característica Web History activada, el usuario le estará enviando toda su información al atacante.
Los ataques de inicio de sesión CSRF, y defensas potenciales contra éstos son documentados con mayor detalle en Robust Defenses for Cross-Site Request Forgery (PDF). Estos ataques no son específicos de Persona: la mayoría de mecanismos de inicio de sesión son potencialmente vulnerables a ellos.
Existen una variedad de técnicas, las cuales pueden ser usadas para proteger un sitio de ataques de inicio de sesión CSRF, las cuales son documentadas con mayor detalle en el estudio antes mencionado.
Una propuesta es crear un identificador secreto en el servidor, compartido con el navegador, y requerir al navegador que lo proporcione cuando realice un pedido de inicio de sesión. Por ejemplo:
- Tan pronto como el usuario visite su sitio, antes de intentar iniciar sesión cree una sesión para él en el servidor. Almacene el ID de la sesión en una cookie del navegador.
- En el servidor, genere un texto aleatorio de al menos 10 caracteres alfanuméricos. un UUID generado aleatoriamente es una buena opción. Esto es un token CSRF. Almacene esto en la sesión.
- Envie el CSRF token al navegador a través de JavaScript embebido o HTML como una variable oculta del formulario.
- Asegurese que el envio AJAX o la petición POST del formulario incluya el token CSRF.
- En el lado del servidor, antes de aceptar la aserción, revise que el token CSRF enviado concuerde con el almacenado en la sesión.
Mejoras
Politicas de seguridad del contenido (Content Security Policy o CSP)
Content Security Policy (CSP) es una capa extra de seguridad que ayuda a detectar y mitigar ciertos tipos de ataques, incluyendo Cross Site Scripting (XSS) y ataques de inyección de datos. Estos ataques son usados para todo desde robo de datos a desconfiguración del sitio o distribución de malware.
SI utilizas CSP en tu siitio, es posible que necesites modificar tu politica para permitir Persona. Dependiendo de tu política, puedes necesitar:
- Eliminar inline
javascript:
URIs y reemplazarlos con código cargado desde un archivo script adicional. El archivo puede ver elementos basándose en su ID, y luego atacar al elemento configurandoonclick
o llamando aaddEventListener()
. - Permitir
https://login.persona.org
comoscript-src
yframe-src
para que el archivo pueda cargar el archivo remotoinclude.js
y ese archivo pueda comunicarse con la llamada a la implementación de Persona.
Un ejemplo de la configuración de Apache puede incluir:
Header set X-Content-Security-Policy: "default-src 'self'; frame-src 'self' https://login.persona.org ; script-src 'self' https://login.persona.org"