PGP práctico con Firefox y Gmail

Para los que llevamos tiempo en el mundo de Linux seguro que hemos visto más de una vez mensajes en listas de correo o foros o por ejemplo últimamente para firmar la autenticidad de los paquetes de Ubuntu, las siglas PGP o GPG.

PGP es un algoritmo criptográfico de clave asimétrica que se creó alrededor de 1991 (aunque ha ido evolucionando) y ha llegado, no sin algunos entresijos legales, hasta nuestros días como uno de los mejores mecanismos de firma y encriptación existentes y de implementación abierta a través de OpenPGP y la RFC2440. Y GPG no es más que una de las implementaciones más populares del algoritmo, disponible para varias plataformas.

Y gracias a GPG tenemos en Firefox una estupenda extensión llamada FireGPG, como no podía ser de otra manera. De este modo, GPG se encarga de gestionar nuestras claves mientras que la extensión nos ofrece un menú contextual para encriptar o firmar el texto seleccionado y integración con Gmail.

Por un lado, el menú contextual permite firmar y verificar firmas, encriptar, encriptar y firmar y desencriptar, así como importar (seleccionando el texto de la fiarma) y exportar (pegando la clave pública) firmas.

A la hora de firmar, deberemos seleccionar la clave privada con la que queremos realizar la operación y nos preguntará la palabra secreta para poder desencriptar nuestra clave privada (se guarda cifrada en el disco) y firmar el mensaje. En este caso, cualquier persona con nuestra clave pública, que podemos haber facilitado nosotros o haberla colgado en un servidor de firmas (como puede ser el de RedIris o el de PGP.com).

Si lo que queremos es encriptar, deberemos seleccionar una o varias claves públicas de los destinatarios del mensaje (y si además queremos firmar, una clave privada). Solamente los propietarios de las claves privadas que corresponden a las claves públicas usadas podrán leer el mensaje, por lo que si no nos añadimos a nosotros mismos, no podremos saber qué hemos encriptado una vez lo hagamos.

En cuanto a la integración con Gmail se hace de dos modos. El primero es el modo de lecutra, en el que aparece un pequeño texto al lado de Reenviar que pone “Descrifar el mensaje” o nos indica si la firma es válida o no.

El segundo modo es a la hora de escribir. Aparecen una serie de botones al lado de los típicos de Gmail con las mismas opciones que encontramos en el menú contextual. Pulsando uno de ellos realizaremos la misma acción pero automáticamente seleccionará todo el texto, lo firmara y/o encriptará y después lo volverá a pegar en el cuadro de texto (y si además pulsamos en la opción más enviar, enviará el correo automáticamente). Por las pruebas que he hecho, es más fiable usar la opción de enviar automáticamente porque nos aseguramos que no escribimos texto adicional que pueda alterar el mensaje.

Existe también una extensión para Thunderbird llamada Enigmail que básicamente hace lo mismo que FireGPG pero para el cliente de correo y me consta que hay también otros plugins para Outlook y otros clientes de correo populares.

En resumen, es una buena forma de conseguir firma digital. Evidentemente no existe una gran empresa que verifique de nuestras firmas son válidas y reales, pero tampoco tienen el coste que tienen algunos certificados digitales de entidades reconocidas. Aun así, se pueden crear redes de confianza entre propietarios de firmas si por ejemplo se ven en persona y intercambian sus claves públicas.

Habrá que ver si son la popularización de las firmas digitales como las que vienen en el DNI-e (aunque hay que sacarlas del carné, lo que no es una tarea tan simple) se empiezan a firmar los correos electrónicos, por lo menos a nivel institucional y coporativo, para aumentar la confiabilidad de los correos electrónicos y evitar el fraude. O, qué narices, por divertirnos un poco.

Enlace | FireGPG

Miniguía de Live HTTP headers

El otro día comenté de pasada esta excelente y útil extensión de Firefox. Como todo, cada uno encuentra su uso particular a cada herramienta trabajando en el desarrollo de aplicaciones web resulta práctico y se echa de menos en otros navegadores. Aunque hay otras opciones, como Wireshark o WebScarab, no son tan sencillas ni se integran tan bien con el navegador.

Al instalar la extensión, aparece una nueva opción en el menú de Herramientas llamada Live HTTP headers. Al abrirla se ve algo parecido a esto:

Live HTTP headers main screen

Directamente aparece la utilidad capturando cabeceras hasta que se desmarque la opción de Capture. Arriba hay 4 pestañas que veremos con más detalle y abajo un botón Save All… para guardar un archvo de texto con todos los datos recopilados, otro Replay… para repetir un bloque y después Clear y Close para limpiar y cerrar.

La pestaña Generator nunca la he usado. Se supone que sirve para hacer un listado detallado de todos los accesos y luego pasarlo a alguna herramienta que genere tests de carga a partir de los datos. La otra pestaña de la que se puede prescindir es About, aunque está bien saber quién hay detrás de todo esto.

La pestaña de Config muestra algunas opciones como la configuración de los POST, que nunca he tocado pero es para no leer las peticiones de este tipo, leerlas rápidamente, completas o limitadas a 1k. Supongo que para depuración de envío de grandes cantidades de datos puede ser útil limitar de algún modo. Se puede elegir si usar una CSS para mostrar más bonito el listado, si abrir en una pestaña y opciones de filtrado para evitar capturar cierto tipo de peticiones. Finalmente se puede añadir a la barra lateral. En cualquier caso, las opciones por defecto suelen bastar.

Pero entrando en materia, lo útil es la inspección de cabeceras, es decir, la pantalla principal y ese pequeño botoncito donde pone Replay. Muchas veces me he encontrado con protecciones de datos por javascript que, de acuerdo, con un navegador normal a un usuario normal, funcionan bien y evitan errores. Pero ni todos los navegadores son como querríamos ni todos los usuarios tienen las mismas intenciones.

Pongamos por ejemplo un simple formulario de registro. Se comprueba por javascript que los datos son correctos, no de dejan el nombre en blanco, ponen una contraseña, ponen un mail aparentemente correcto, aceptan el aviso legal y todo lo que el cliente desee. Luego estos datos deben validarse en el servidor, por lo menos para evitar sorpresas, pero ¿cómo se puede probar eso si solamente se puede entrar por el navegador? Una opción es desactivar javascript, pero igual ni siquiera funciona el formulario, así que entra en juego la opción de repetir una petición de la herramienta que nos ocupa.

Formulario simple

Simplemente hay que capturar el momento en que se pulsa enviar y capturar el flujo de información. En algún sitio habrá una petición de POST (si es GET, probar las cosas es tan sencillo como ir modificando los parámetros y para eso no se necesita ninguna herramienta). Se situa el cursor sobre la petición y se pulsa el botón de Replay…

Live HTTP headers replay screen

Y mágicamente aparece un desglose de la petición. Por un lado las cabeceras arriba (que son completamente modificables, de hecho he cambiado las URL y información sobre las cookies que aparecía) y abajo el contenido del POST.

Un ejemplo podría ser dejar el nombre en blanco. Solamente hay que borrar Prueba después de tNombre= todo lo que hay hasta & y es como si estuviera en blanco. Al hacer esto, abajo hay un contador de Content-Length que es sumamente importante ya que ese dato se ha de copiar al valor de arriba. En este caso, antes era 94 y al borrar Prueba se queda en 88, por lo que hay que modificar el valor 94 de la cabecera por 88 para que funcione, de lo contrario cosas extrañas van a pasar.

Hecho esto, simplemente hacer click sobre Replay a se volverá a lanzar la petición en el navegador y mostrará el resultado de esta. En el mejor de los casos nos indicará que pongamos el nombre y en el peor aparecerá un bonito error. Suerte. (En mi caso no ha pasado nada especial pero sospecho que el correo que contacto se ha enviado a algún sitio, mañana veré).

Y eso es todo, espero que resulte de utilidad… y ¡no hagáis maldades!

Wapiti, auditoría web sencilla

WapitiDe un tiempo a esta parte habían empezado a llegar a una cuenta de correo que tenemos configurada para recibir los informes de error de las distintas aplicaciones web una serie de errores bastante sospechosos. Eran todo URLs con cadenas de texto en parámetros numéricos que hacían fallar la página. Esto se producía evidentemente por nuestra pobre comprobación de los parámetros que producía que en algunos casos el valor numérico en cuestión llegase tal cual a una consulta en la base de datos, fallando estrepitosamente.

Lo curioso del caso es que solamente ocurría en algunas webs concretas y siguiendo siempre el mismo patrón: claramente usaban una herramienta que buscaba posibles vectores de inyección SQL o similares. Era un mecanismo bastante burdo pero seguro que en algún sitio algo encontraron. Además las IPs eran variadas así que posiblemente se debía a la aparición de alguna herramienta en algún foro de script kiddies.

Y me dije: yo quiero hacer lo mismo. Así que me puse a buscar y encontré algunas herramientas, siendo la más interesante Wapiti, un fuzzer sencillo hecho en Python con las siguientes funcionalidades:

  • Detección de errores en la gestión de ficheros (fopen, includes…)
  • Inyección SQL
  • Inyección XSS
  • Inyección LDAP
  • Ejecución de comandos (eval(), system()…)
  • Inyección CRLF (HTTP splitting)

Además muestra un mensaje de alerta cada vez que se produce un error 500, con lo que es ideal para analizar aplicaciones hechas en ASP (ehem).

Así pues hice un testado exhaustivo con esta herramienta a nuestro código base y la verdad que encontré cosas interesantes, como un error de lo más ingenuo que daba paso a un bonito ataque XSS o unas cuantas entradas sin proteger que proporcionaban posibles ataques SQL jugando con los parámetros. Otros errores no eran tan evidentes y se basaban en jugar con los datos enviados por POST, que por cierto para las pruebas encontré imprescindible la extensión Live HTTP Headers que permite ver el tráfico HTTP y luego repetir una llamada modificando las cabeceras (con calculadora automática del Content-Length, afortunadamente).

He de decir que esto evidentemente no es una herramienta de revisión de código pero si me tengo que poner a revisar toda nuestra base de código antiguo apaga y vámonos. Más vale un poco de protección que ninguna protección, por lo menos la valla un poco más alta que la del vecino.

Posiblemente aun queden muchos agujeros que tapar pero en general ya solemos usar protección para todos los parámetros que entran como comprobar que los números son valores numéricos y que las cadenas de texto son como deben ser y no tienen gato encerrado (ver el XSS FAQ para un método bastante competo de protección).

En resumen, que a lo largo de los años se ha descuidado muchas veces la seguridad de aplicaciones web (las prisas, la poca importancia atribuida, el desconocimiento, etc) y cada vez hay más y mejores técnicas para sacar provecho de nuestros fallos, por lo que cualquier comprobación no está de menos.

Actualización 08/03/2008: Kriptópolis se hace eco de un artículo interesante llamado “El mito de la seguridad web total”. Interesante lectura.