mozilla

Revision 335007 of Consideraciones de Seguridad

  • Revision slug: Persona/Security_Considerations
  • Revision title: Consideraciones de Seguridad
  • Revision id: 335007
  • Created:
  • Creator: ccarruitero
  • Is current revision? No
  • Comment
Tags: 

Revision Content

Cuando agregas a tu sitio web soporte para Persona, Persona toma tantas medidas de seguridad como puede. Sin embargo, algunas medidas de seguridad solo pueden ser manejados 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 pasada dentro de la función onlogin a través de

{{ domxref("navigator.id.watch()") }}

Siempre debes pasar la declaración a tu servidor para verificarla, y solo tu servidor debe decidir si autorizar 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 verifcar la declaración usando JavaScript ejecutandose 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 declaració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 declaració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 explicitamente audience en su código, o en su código de configuración. Especialmente:

  • No confie en el Host header enviado por el navegador del usuario.
  • No confie 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 envie el parametro audience, esto deja la posiblidad 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 declaració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 confiable de administrador. 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, asegurate que usas al menos la version 6.0 de libwww-perl. Dependiendo del lenguaje, librería, y sistema operativo que estas 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 login CSRF (Cross-Site Request Forgery), el atacante utiliza CSRF para logear al 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 http://www.google.com/login, dandole el username y password del atacante. Cuando el usuario envia el form, el pedido es enviado a Google, el login ocurre y el servidor de Google configura una cookie en el navegador del usuario. Ahora el usuario sin saberlo ha sido logeado 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 busqueda del usuario. Si el usuario se logea 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.

Ataques de CSRF login, y defensas potenciales contra esto, son documentados con mayor detalle en Robust Defenses for Cross-Site Request Forgery (PDF). Ellos no son especificos de Persona: la mayoría de mecanismos de login son potencialmente vulnerables a ellos.

Existen una variedad de técnicas, las cuales pueden ser usadas para proteger un sitio de ataques de CSRF login, 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 requierir al navegador que lo proporcione cuando realize un pedido de logeo. Por ejemplo:

  1. Tan pronto como el usuario visite su sitio, antes de intentar logearse cree una sesión para él en el servidor. Almacene el ID de la sesión en un cookie del navegador.
  2. En el servidor, genere un texto aleatorio de al menos 10 caracteres alfanumericos. un UUID generado aleatoriamente es una buena opción. Esto es un CSRF token. Almacene esto en la sesión.
  3. Envie el CSRF token al navegador a través de JavaScript embebido o HTML como una variable oculta del formulario.
  4. Asegurese que el envio AJAX o la petición POST del formulario incluya el CSRF token.
  5. En el lado del servidor, antes de aceptar la declaración, revise que el CSRF token enviado concuerde con el alojado por 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 necesito modificar su politica para permitir Persona. Dependiendo de su politica, puede necesitar:

  • Remover inline javascript: URIs y reemplazarlos con código cargado desde un archivo script adicional. El archivo puede ver elementos basandose en su ID, y luego atacar al elemento configurando {{ domxref("element.onclick", "onclick") }} o llamando {{ domxref("element.addEventListener()", "addEventListener()") }}.
  • Permitir https://login.persona.org como script-src y frame-src para que el archivo pueda cargar archivo remoto  include.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"

Revision Source

<p>Cuando agregas a tu sitio web soporte para Persona, Persona toma tantas medidas de seguridad como puede. Sin embargo, algunas medidas de seguridad solo pueden ser manejados por tu sitio web. Estas son listadas a continuación.</p>
<h2 id="Essential_practices" name="Essential_practices">Prácticas Esenciales</h2>
<h3 id="Verify_assertions_on_your_server" name="Verify_assertions_on_your_server">Verificar la confirmación en tu servidor</h3>
<p>Cuando utilizas Persona, las declaraciones de identidad son pasada dentro de la función <code>onlogin</code> a través de</p>
<p>{{ domxref("navigator.id.watch()") }}</p>
<p><em>Siempre</em> debes pasar la declaración a tu servidor para verificarla, y solo tu servidor debe decidir si autorizar al usuario permisos adicionales en base al resultado de la verificación:</p>
<pre class="brush:js;">
// 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.
},
</pre>
<p>Si trata de verifcar la declaración usando JavaScript ejecutandose 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.</p>
<p>Como mencionamos lineas arriba, <em>siempre</em> debe pasar la declaración a su servidor para la verificación. Incluso si está usando la API de verificación remota.</p>
<h3 id="Explicitly_specify_the_audience_parameter" name="Explicitly_specify_the_audience_parameter">Especifique explícitamente el parámetro <code>audience</code></h3>
<p>Para verificar la declaración, debe realizar un pedido <code>POST</code> a<code> https://verifier.login.persona.org/verify</code>. El pedido incluye el parámetro llamado <code>audience</code>:</p>
<pre>
<code>assertion=&lt;ASSERTION&gt;&amp;audience=https://mysite.com:443"</code></pre>
<p>El parámetro <code>audience</code> es requerido. Siempre debe especificar explicitamente audience en su código, o en su código de configuración. Especialmente:</p>
<ul>
  <li>No confie en el Host header enviado por el navegador del usuario.</li>
  <li>No confie en el parámetro explicito enviado por el navegador del usuario, pero generado usando JavaScript, e.g. <code>document.location</code>.</li>
</ul>
<p>Si dejas que el navegador del usuario te envie el parametro <code>audience</code>, esto deja la posiblidad de que un sitio web malicioso pueda reusar las declaraciones de su sitio web para autenticarse en tu sitio web.</p>
<h3 id="Verify_SSL_certificates" name="Verify_SSL_certificates">Verifica los certificados SSL</h3>
<p>Para verificar una declaración, debes realizar un petición POST a <code>https://verifier.login.persona.org/verify</code>. Debes asegurarte que tu petición HTTPS verifique el certificado enviado desde el servidor contra un certificado confiable de administrador. Si no lo haces, un atacante podría presentarse como <code>verifer.login.persona.org</code> y realizar verificaciones falsas.</p>
<p>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.</p>
<p>Por ejemplo, el <a class="external" href="http://docs.python.org/release/2.7.3/library/urllib2.html#urllib2.urlopen" title="http://docs.python.org/release/2.7.3/library/urllib2.html#urllib2.urlopen">modulo urllib2</a> estándar de Python 2.7 no valida certificados del servidor. En lugar de ello, recomendamos utilizar los módulos "<a class="external" href="http://pypi.python.org/pypi/requests">requests</a>" o "<a class="external" href="http://pypi.python.org/pypi/urllib3" title="http://pypi.python.org/pypi/urllib3">urllib3</a>" en Python 2.x, o la clase estándar <code>http.client.HTTPSConnection</code> en Python 3.x. Para Perl, asegurate que usas al menos la version 6.0 de <code>libwww-perl</code>. Dependiendo del lenguaje, librería, y sistema operativo que estas usando, vas a necesitar utilizar algún CA (Certificate Authority) confiable o el CA simple usado por <code>verifier.login.persona.org</code>.</p>
<h3 id="Implement_CSRF_protection" name="Implement_CSRF_protection">Implementar protección CSRF</h3>
<p>En un ataque de login CSRF (Cross-Site Request Forgery), el atacante utiliza CSRF para logear al usuario dentro del sitio web usando las credenciales del atacante.</p>
<p>Por ejemplo: un usuario visita una web maliciosa&nbsp; que contiene un elemento <code>form</code>. El atributo <code>action</code> del <code>form</code> está configurado para hacer una petición HTTP POST a <a class="external" href="http://www.google.com/login" title="http://www.google.com/login">http://www.google.com/login</a>, dandole el username y password del atacante. Cuando el usuario envia el <code>form</code>, el pedido es enviado a Google, el login ocurre y el servidor de Google configura una cookie en el navegador del usuario. Ahora el usuario sin saberlo ha sido logeado con la cuenta Google del atacante.</p>
<p>El ataque puede ser usado para reunir información sensible del usuario. Por ejemplo, <a class="link-https" href="https://www.google.com/history/">Web History</a> de Google tiene la característica de registrar todos los términos de busqueda del usuario. Si el usuario se logea 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.</p>
<p>Ataques de CSRF login, y defensas potenciales contra esto, son documentados con mayor detalle en <a class="external" href="http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf">Robust Defenses for Cross-Site Request Forgery</a> (PDF). Ellos no son especificos de Persona: la mayoría de mecanismos de login son potencialmente vulnerables a ellos.</p>
<p>Existen una variedad de técnicas, las cuales pueden ser usadas para proteger un sitio de ataques de CSRF login, las cuales son documentadas con mayor detalle en el estudio antes mencionado.</p>
<p>Una propuesta es crear un identificador secreto en el servidor, compartido con el navegador, y requierir al navegador que lo proporcione cuando realize un pedido de logeo. Por ejemplo:</p>
<ol>
  <li>Tan pronto como el usuario visite su sitio, antes de intentar logearse cree una sesión para él en el servidor. Almacene el ID de la sesión en un cookie del navegador.</li>
  <li>En el servidor, genere un texto aleatorio de al menos 10 caracteres alfanumericos. un UUID generado aleatoriamente es una buena opción. Esto es un CSRF token. Almacene esto en la sesión.</li>
  <li>Envie el CSRF token al navegador a través de JavaScript embebido o HTML como una variable oculta del formulario.</li>
  <li>Asegurese que el envio AJAX o la petición POST del formulario incluya el CSRF token.</li>
  <li>En el lado del servidor, antes de aceptar la declaración, revise que el CSRF token enviado concuerde con el alojado por la sesión.</li>
</ol>
<h2 id="Enhancements" name="Enhancements">Mejoras</h2>
<h3 id="Content_Security_Policy_(CSP)" name="Content_Security_Policy_(CSP)">Politicas de seguridad del contenido (Content Security Policy o CSP)</h3>
<p><a href="/en-US/docs/Security/CSP" title="Security/CSP">Content Security Policy</a> (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.</p>
<p>SI utilizas CSP en tu siitio, es posible que necesito modificar su politica para permitir Persona. Dependiendo de su politica, puede necesitar:</p>
<ul>
  <li>Remover inline <code>javascript:</code> URIs y reemplazarlos con código cargado desde un archivo script adicional. El archivo puede ver elementos basandose en su ID, y luego atacar al elemento configurando {{ domxref("element.onclick", "onclick") }} o llamando {{ domxref("element.addEventListener()", "addEventListener()") }}.</li>
  <li>Permitir <code>https://login.persona.org</code> como <code>script-src</code> y <code>frame-src</code> para que el archivo pueda cargar archivo remoto&nbsp; <code>include.js</code>&nbsp; y ese archivo pueda comunicarse con la llamada a la implementación de Persona.</li>
</ul>
<p>Un ejemplo de la configuración de Apache puede incluir:</p>
<pre>
<span class="diff-content"><span class="idiff">Header set X-Content-Security-Policy: "default-src 'self'; frame-src 'self' https://login.persona.org ; script-src 'self' https://login.persona.org"</span></span></pre>
Revert to this revision