Proteger las contraseñas guardadas en Firefox con una contraseña maestra

Cada vez que guardamos una clave en Firefox, la misma está disponible para cualquier otra persona que tenga acceso al navegador. La solución más drástica sería desactivar el guardado de contraseñas en Firefox, pero como es algo realmente útil vamos a ir por otro camino.

Un usuario puede acceder a las contraseñas guardadas desde:

  • Botón de identidad del sitio: icono a la izquierda de la url en la barra de direcciones
    1. Presionar el icono
    2. Presionar el botón «Más información…»
    3. Presionar el botón «Ver contraseñas guardadas» en la solapa Seguridad
  • Opciones
    • Abrir el menú Herramientas > Opciones
    • Presionar el botón «Contraseñas guardadas» en la solapa Seguridad

Una vez allí, al presionar «Mostrar contraseñas» solicita una simple confirmación y listo, tenemos a la vista TODAS las contraseñas almacenadas en el navegador.

Adcionalmente, tenemos que saber que aún sin conocer las contraseñas, con el solo hecho de ingresar al login de un sitio donde se hayan almacenado las credenciales de acceso, podremos ingresar!

Para protegernos de ambos casos, Firefox provee de la posibilidad de establecer una contraseña maestra, la cual se solicitará antes de:

  • utilizar las credenciales guardadas para completar los campos de un formulario de login
  • mostrar las contraseñas guardadas

Para configurarla debemos:

  • Abrir el menú Herramientas > Opciones
  • Marcar la opción «Usar una contraseña maestra» en la solapa Seguridad
  • Ingresar la contraseña nueva y su confirmación
  • Confirmar con Aceptar la creación
  • Aceptar nuevamente para completar el cambio de las opciones

Evitar que el navegador solicite recordar los datos de acceso en formulario de login

Al ingresar los datos de acceso en un sitio, el navegador propondrá almacenarlos excepto cuando se haya desactivado el guardado de contraseñas. En la mayoría de los casos es el comportamiento deseado, dado que el usuario puede decidir si quiere o no hacerlo.

Existen contadas ocasiones donde sería bueno que el sitio pudiera indicar al navegador que no realice esta esta propuesta (por ejemplo, el sitio web de un banco). Al momento de escribir esta publicación, no hay una forma simple. Hasta hace un tiempo los navegadores se comportaban de esta manera cuando se agregaba el atributo autocomplete=»off» al formulario, pero ya no más a partir de IE11, Chrome 34 y Firefox 30.

Igualmente, la seguridad en el acceso debería pasar por otro lado y no por evitar que el navegador recuerde la clave. El usuario puede tener otras aplicaciones o plugins del navegador donde se almacenen, hasta puede tenerlas anotadas en un papel.

Lo que les propongo es un formulario de login que NO fomenta al navegador a solicitar recordar el usuario y la clave, compatible con casi todas las versiones de Firefox, Chrome e Internet Explorer que pude probar. Tengan en cuenta que podría funcionar hasta que cambien las reglas nuevamente.

 

Tomaremos como base el formulario de login seguro que fomenta el recordar datos de acceso, al cual le realizaremos una serie de modificaciones:

Modificaciones sobre el formulario

Modificación 1: cambiamos el tipo de input submit por button. Esto es lo que evita que la mayoría de los navegadores proponga recordar la clave.

Modificación 2: agregamos al formulario el atributo autocomplete=»off». Aunque no es esencial hacerlo, en versiones de los navegadores previas a las indicadas se contempla.

<form action="index.cgi" autocomplete="off" method="post" id="login_form" name="login_form">
  Email: <input type="text" name="e" id="email"  /><br />
  Password: <input type="password" name="p" id="password" /><br />
  <input type="hidden" name="ps" id="secret">
  <input type="button" value="Login" id="login_button" />
</form>

OBS: en el atributo action del formulario se indica el script que procesará los datos ingresados, en este caso index.cgi pero podría ser cualquiera.

Modificaciones sobre el código javascript

Modificación 3: establecemos el login_button como elemento a observar y el evento click (en lugar del submit del elemento login_form):

Event.observe( 'login_button', 'click', formProcess);

Modificación 4: agregaamos al final de la función formProcess la acción de submit del formulario

$('login_form').submit();

 

Un detalle de color: podemos darle el toque final capturando el Enter en los campos del formulario para procesarlo (esto se hace automáticamente cuando está presente el input submit).

Agregamos el atributo onkeypress en cada uno invocando a una nueva función checkEnter, la cual al detectar que se presionó Enter invoca la función de procesamiento del formulario:

Email: <input type="text" name="e" id="email" onkeypress="checkEnter(event)" /><br />
Password: <input type="password" name="p" id="password" onkeypress="checkEnter(event)" /><br />
function checkEnter(e){
  var codigoCaracter = (e && e.which) ? e.which : event.keyCode;
  if(codigoCaracter == 13) {
    formProcess();
  }
  else {
    return true;
  }
}

 

Formulario completo

A continuación les dejo el código del formulario completo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Test Site</title>
    <script type="text/javascript" src="sha512.js"></script>
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript">
      Event.observe(window, 'load', function(){
        Event.observe( 'login_button', 'click', formProcess);
      });
      function formProcess(){
        //agregar validaciones
        $('secret').value = hex_sha512($('password').value);
        $('password').value = '';
        $('login_form').submit();
      }
      function checkEnter(e){
        var codigoCaracter = (e && e.which) ? e.which : event.keyCode;
        if(codigoCaracter == 13) {
          formProcess();
        }
        else {
          return true;
        }
      }
    </script>
  </head>

  <body>
    <form action="index.cgi" autocomplete="off" method="post" id="login_form" name="login_form">
      Email: <input type="text" name="e" id="email" onkeypress="checkEnter(event)" /><br />
      Password: <input type="password" name="p" id="password" onkeypress="checkEnter(event)" /><br />
      <input type="hidden" name="ps" id="secret">
      <input type="button" value="Login" id="login_button" />
    </form>
  </body>
</html>

Formulario de login seguro que fomenta el recordar datos de acceso

A menos que hayamos desactivado el guardado de contraseñas, los navegadores propondrán almacenarla cuando formulario de login se presente en la pantalla.

La idea es plantear un formulario de login, ver los inconvenientes que se presentan y analizar soluciones, compatibles con casi todas las versiones de Firefox, Chrome e Internet Explorer (no puedo asegurar que lo que aquí se exponga funcione en todos los casos ni tampoco que sea para siempre).

Cuestiones genéricas a saber sobre el administrador de contraseñas de los navegadores

  • Aplica solamente en el ámbito del navegador que se esté usando
  • Solicita confirmación para guardar con los datos que están en los campos al momento de hacer el submit, principalmente cuando existe un input submit.
  • Tiene que haber un input password para que entre en acción.
  • Asocia el password al valor ingresado en el input de texto inmediatamente superior al de tipo password en el dominio en que se encuentra.
    • Si no lo hubiera, o bien no tuviera un valor, entonces se asocia el password directamente al dominio en que se encuentra.
  • En IE no se activa cuando el submit se realiza mediante javascript.

Formulario de login

<form action="index.cgi" method="post" id="login_form" name="login_form">
  Email: <input type="text" name="e" id="email" /><br />
  Password: <input type="password" name="p" id="password" /><br />
  <input type="submit" value="Login" id="login_button" />
</form>

OBS: en el atributo action del formulario se indica el script que procesará los datos ingresados, en este caso index.cgi pero podría ser cualquiera.

El problema en este caso es que la clave se comunica de manera plana.

  • Solución 1: Si se usara el protocolo HTTPS para la comunicación, la conexión de extremo a extremo estaría cifrada. Es lo más recomendado, pero vamos a considerar que no contamos con el certificado requerido para implementarlo y utilizamos HTTP común, a fin de hacer más interesante el ejemplo.
  • Solución 2: Cifrar la clave utilizando la función criptográfica que deseen. En el ejemplo utilizaremos SHA-512 que es bastante seguro y se puede obtener rápidamente mediante javascript.

OBS: Utilizaremos el framework Prototype de javascript para simplificar el código, pero pueden utilizar javascript puro o algún otro framework como jQuery.

Para implementar la solución 2, invocamos una función cuando se realice el submit del formulario para que lo procese. En ella ciframos la clave, de manera que cuando se comuniquen los datos, la misma viaje solamente de manera cifrada.

<script type="text/javascript">
  Event.observe(window, 'load', function(){
    Event.observe( 'login_form', 'submit', formProcess);
  });
  function formProcess(){
    //agregar validaciones
    $('password').value = hex_sha512($('password').value);
    return true;
  }
</script>

OBS: Se debe reemplazar el comentario //agregar validaciones por las validaciones del lado del cliente, correspondientes al procesamiento del formulario

Un detalle de color: tal como planteamos la solución, a la vista aparecen por un instante más caracteres en el campo justo antes de empezar a cargar la página después del submit (resultado del cifrado de la clave)

Mejora visual 1: podemos agregar un input hidden:

<input type="hidden" name="ps" id="secret">

donde guardamos la clave cifrada y luego borramos el contenido del campo password (de lo contrario viajaría la clana nuevamente)

$('secret').value = hex_sha512($('password').value);
$('password').value = '';

Entonces la clave ingresada desaparece por un instante justo antes de empezar a cargar la página después del submit.

Mejora visual 2: contamos la cantidad de caracteres de la clave ingresada y los reemplazamos por el caracter ‘x’:

$('secret').value = hex_sha512($('password').value);
var pass_len = $('password').value.length;
$('password').value = Array(pass_len+1).join("x");

A la vista, no cambia nada cuando hacemos el submit, pero hemos cifrado la clave.

OBS: Si pensaron hacer un disable del input password es posible que en ciertos navegadores no proponga recordarles la contraseña (ej. chrome). La mejora 2, se podría realizar también agregando OTRO input hidden y disabled (ubicado inmediatamente despúes de password) que se complete con la clave antes de borrarla, y que el procesamiento del formulario oculte el input password y se ponga visible el disabled.

Formulario completo

A continuación les dejo el código del formulario completo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Test Site</title>

    <script type="text/javascript" src="sha512.js"></script>
    <script type="text/javascript" src="prototype.js"></script>

    <script type="text/javascript">
      Event.observe(window, 'load', function(){
        Event.observe( 'login_form', 'submit', formProcess);
      });
      function formProcess(){
        //agregar validaciones
        $('secret').value = hex_sha512($('password').value);
        var pass_len = $('password').value.length;
        $('password').value = Array(pass_len+1).join("x");
        return true;
      }
    </script>
  </head>
  <body>
    <form action="index.cgi" method="post" id="login_form" name="login_form">
      Email: <input type="text" name="e" id="email" /><br />
      Password: <input type="password" name="p" id="password" /><br />
      <input type="hidden" name="ps" id="secret">
      <input type="submit" value="Login" id="login_button" />
    </form>
  </body>
</html>

 

Obtener la clave pública a partir de una clave privada

Para los que no sepan, rápidamente les comento que el tener un par de claves permite aplicar un tipo de criptografía denominado asimétrica. La misma se basa en tener una clave pública que comunicamos y una privada (secreta) que guardamos nosotros, ambas relacionadas. Se puede usar de 2 maneras diferentes:

  • con la clave pública encriptamos un contenido y con la privada lo desencriptamos
  • con la clave privada generamos una firma digital y con la pública, la verificamos

Para generar un par de claves en linux, accedemos a la línea de comandos y escribimos:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
3b:d6:67:66:0c:43:b5:5a:c7:ed:de:4e:87:db:f6:d5 user@user-pc
The key's randomart image is:

 +--[ RSA 2048]----+
 |            .    |
 |           . o . |
 |          . o o .|
 |         . o . . |
 |        S +     .|
 |         o +   oo|
 |        + . * . E|
 |       . . =   =+|
 |              ..=|
 +-----------------+

De esta manera obtendremos las 2 claves en el directorio .ssh del usuario: id_rsa es la clave privada y id_rsa.pub la pública. Tengan en cuenta que para este ejemplo no especificamos una passphrase que sería lo recomendable.

Ahora bien, suponiendo que entregamos la clave pública y nos olvidamos de dejarnos una copia de ella, podemos volver a generar la clave pública  a partir de la clave privada y guardarla en un archivo invocando el comando ssh-keygen de la siguiente manera:

$ ssh-keygen -yf <CLAVE_PRIVADA> > <CLAVE_PUBLICA>

Ejemplo:

$ ssh-keygen -yf /home/user/.ssh/id_rsa > /home/user/.ssh/id_rsa.pub

 

Basado en:

http://systemadmin.es/2014/08/obtener-la-clave-publica-desde-una-clave-privada-ssh

Desactivar el guardado de contraseñas en los navegadores

Los principales navegadores tienen una funcionalidad incluida que permite guardar las contraseñas (y el nombre usuario) en los formularios de acceso de las aplicaciones web. Por lo general, se encuentra activada por defecto y es muy cómo contar con ella en la computadora del hogar. Cuando detecta que nos hemos identificado, nos consulta si queremos guardar los datos ingresados para no tener que volver a escribirlos en futuras ocasiones.

Pero si el equipo es compartido o nos encontramos en la empresa tal vez no deseemos contar con dicha característica. Para desactivar el guardado de contraseñas (y borrar las que se hayan guardado) debemos seguir los siguientes pasos, dependiendo el navegador:

Chrome

  1. Escribir en la barra de navegación chrome://settings/, o bien
    1. Abrir el menú de Chrome (desde el icono de las 3 líneas horizontales)
    2. Seleccionar la opción «Configuración»
  2. Buscar «Contraseñas» mediante el buscador situado arriba a la derecha, o bien
    1. Ir hasta el final y hacer click sobre «Mostrar opciones avanzadas…»
    2. Buscar el apartado Contraseñas y formularios
  3. Desmarcar la opción «Preguntar si quieres guardar tus contraseñas web»
  4. Presionar sobre «Administrar contraseñas guardadas»
    1. Borrar cada uno de los registros

Internet Explorer

  1. Ir a «Herramientas» desplegando la barra de menú, o bien
    1. Abrir el menú de Herramientas (desde el icono de engranaje)
  2. Seleccionar «Opciones de Internet»
  3. Abrir la solapa Contenido
  4. Presionar el botón Configuración en el apartado Autocompletar
  5. Desmarcar la opción «Nombres de usuario y contraseñas en formularios». Se desactiva la opción «Preguntar antes de guardar las contraseñas»
  6. Presionar el botón «Eliminar el historial de Autocompletar…»
    1. Desmarcar la opción «Conservar los datos de sitios web favoritos»
    2. Marcar solamente la opción «Contraseñas» (se pueden marcar otras opciones si así se lo desea)
    3. Confirmar con Eliminar
  7. Confirmar con Aceptar
  8. Cuando se concluya la limpieza, aparece en la parte inferior del navegador el mensaje «Internet Explorer terminó de eliminar el historial de exploración seleccionado»

Firefox

  1. Ir a «Herramientas» desplegando la barra de menú, o bien
    1. Abrir el menú de Firefox (desde el icono de las 3 líneas horizontales)
  2. Seleccionar Opciones
  3. Elegir el bloque de Seguridad
  4. Desmarcar la opción «Recordar contraseñas para los sitios» en el apartado Contraseñas
  5. Presionar el botón «Contraseñas guardadas…»
    1. Presionar el botón «Eliminar todo»
    2. Presionar Cerrar
  6. Confirmar con Aceptar

Si nos encontramos en un lugar temporal como ser la casa de un amigo, una notebook de un compañero o un cibercafé, lo mejor es usar la navegación privada y evitar todo tipo de inconvenientes.

Iniciar Windows automáticamente con un usuario con contraseña

Cuando tenemos más de un usuario configurado en Windows o al establecerle una contraseña al único existente (para recursos compartidos en red por ejemplo) en cada arranque debemos elegir el usuario e ingresar la contraseña.

Esto se puede evitar estableciendo el usuario con el cual Windows iniciará por defecto. Para ello desde Inicio > Ejecutar… ingresamos:

control userpasswords2

En la pantalla de configuración de Cuentas de usuario que aparece, desmarcamos la opción «Los usuarios deben escribir su nombre y contraseña para usar el equipo».

Al confirmar con Aceptar, se requiere ingresar la información para iniciar sesión automáticamente.

Ingresamos el nombre y la contraseña (con su confirmación) del usuario con el que queremos que Windows inicie por defecto y listo.