Jugando con IMAP en Python

Hilos Hace no mucho parecía que POP iba a ser el protocolo preferido para el correo. Sin embargo, con la movilidad permanente y la necesidad de consultar nuestro correo en cualquier parte parece que todo ha cambiado y las soluciones preferidas son los sistemas de correo basados en proveedores con sus aplicaciones (y típicamente su reflejo en webmail para el escritorio. Si nuestro proveedor no tiene aplicación, parece que la solución más adecuada es el IMAP. POP estaba orientado a la descarga, e IMAP estaba pensando para que el correo permaneciera en el servidor y se accediera a él mediante conexión.

A mi me gusta seguir viviendo la ficción de que una parte de mi correo es más o menos privada y eso pasa por usar los servidores del trabajo (o de un proveedor privado) con algunos inconvenientes: por un lado, malas herramientas de filtrado y gestión del correo; por otra parte, limitaciones en el espacio (todavía hay otra, y es la capacidad de buscar que pude solucionar -más o menos- con mairix).

Estas limitaciones me llevaron a montar un servidorcillo de correo (lo que viene llamándose en los últimos tiempos hacer un Hillary Clinton). Empecé montando los servicios por mi cuenta hasta que probé Zentyal que no es exactamente lo que necesito (tiene muchas más cosas y está pensada para algo más grande, pero me libera de algunas tareas de gestión). Miro con simpatía iniciativas como mailinabox o el fallido -por ahora- ownmailbox. Zentyal me proporciona un sistema con SOGo, Dovecot, filtrado (pronto, espero, otra entrada específica sobre el tema), antispam (no va demasiado bien, al menos en mi experiencia) y algunas herramientas más.

De todas formas, lo que quiero presentar hoy aquí puede ser de utilidad para cualquier cuenta de correo. Se trata de borrar algunos mensajes de una carpeta IMAP basado en reglas sencillas: en nuestro caso, recibimos mensajes de diversas tareas de cron que repetitivamente (sobre todo cuando todo va bien) llegan a nuestro correo. Lo que haremos será recorrer las carpetas donde se reciben las copias de seguridad y borrarlas.

La primera tarea es buscar un poco para ver si existe algún proyecto que nos ayude en la tarea de programación. Python incluye la imaplib que permite hacer las tareas necesarias. El proceso será:

  1. Leer la configuración de las cuentas que vamos a examinar
  2. Solicitar las contraseñas
  3. Seleccionar los mensajes y borrarlos

Además, para añadirle un poco de gracia a la cosa hemos añadido un uso muy básico de threading de manera que se hace el borrado de manera concurrente en las cuentas que haya configuradas. El código de la versión actual del programita se puede encontrar en deleteCronMesgs.py.

Comenzamos leyendo la configuración

config = ConfigParser.ConfigParser()
config.read([os.path.expanduser('~/IMAP.cfg')])

En este fichero está la información de las cuentas de correo, tantas como sea necesario:

[IMAP1]
server:imap.server.com
user:myAccount@server.com
[IMAP2]
server:imap.otherServer.com
user:myUsername

Ahora recorremos las cuentas configuradas y pedimos la contraseña (se podrían poner también en el fichero de configuración pero no termino de sentirme confortable con eso)

for section in config.sections():
	SERVER = config.get(section, 'server')
	USER   = config.get(section, 'user')

	print SERVER
	PASSWORD = getpass.getpass()

El código para borrar los mensajes se encuentra en la función mailFolder y para ello realiza los siguientes pasos:

Primero nos conectamos al servidor, con los datos leídos del fichero de configuración y del teclado.

	M = imaplib.IMAP4_SSL(SERVER)
	M.login(USER , password)

Seleccionamos la carpeta sobre la que vamos a trabajar (en este caso el INBOX) y en ella buscamos los mensajes que nos interesan (los que contienen la cadena ‘Cron Daemon’ en el campo ‘FROM’):

	M.select()
	typ,data = M.search(None,'FROM', 'Cron Daemon')

En search se devuelven dos valores, el estado (¿ha ido todo bien?) y una lista que contiene una cadena de caracteres con los números que identifican a los mensajes que cumplen las condiciones de búsqueda.

Ahora, para borrarlos recorremos la lista y actualizamos la marca (flag) para que refleje la condición de borrado:

	if data[0]: 
		for num in data[0].split():
			M.store(num, '+FLAGS', '\\Deleted')

Además hemos incluido código para ir contando cuántos mensajes borramos y mostrar una actualización cada diez (que no mostramos aquí). Finalmente, cerramos la conexión y terminamos:

	M.close()
	M.logout()

La parte concurrente es muy sencilla, consta de tres pasos.

Para cada cuenta de correo se crea un hilo:

	t = threading.Thread(target=mailFolder, args=(SERVER, USER, PASSWORD,space*i))

En target está la función que se ejecutará cuando se active el hilo y en args los parámetros de esa función.

Ahora acivamos los hilos (hemos separado la creación de la activación para que no haya interferencias de la salida que refleja la actividad con la entrada; podríamos prescindir de la realmientación y lanzarlas sobre la marcha):

for t in threads:
	t.start()

Finalmente, necesitamos esperar a que terminen los hilos, con un par de instrucciones como:

for t in threads:
	t.join()

Siguientes pasos: no tengo claro que el código de los hilos vaya a sobrevivir. Estuvo bien recordar un poquito (¡muy poquito!) de concurrencia pero en este caso no tiene demasiado interés. Tendría sentido poder incluir más reglas de borrado para otros mensajes e incluirlo en la configuración en lugar de en el propio código (por ejemplo, una lista de cademas para buscar o incluso algo más sofisticado).

También me gustaría explorar sistemas alternativos de autentificación (GMail permite utilizar OAuth, si no me equivoco). Como mínimo, poder tener la contraseña cifrada en el fichero de configuración y tener sólo una contraseña manestra.

¿Ideas? ¿Comentarios? Estaremos escuchando en @mbpfernand0 o en @fernand0.

Actualización (2015-12-07) quise terminar esta entrada rápido y olvidé otro ejemplo que tengo a mano. En este caso se trataría de borrar basado en el contenido. Recibimos ciertos mensajes repetidos que querríamos eliminar de nuestras coias de seguridad. Para examinar el contenido de los mensajes utilizaríamos:

	typ, data = M.fetch(num, '(BODY.PEEK[TEXT])')

Para determinar si el mensaje en cuestión es repetido, calculamos el hash (que tenemos precalculado) y lo comparamos:

	m = hashlib.md5()
	m.update(data[0][1])	
	if (binascii.hexlify(m.digest())==HASH):
		M.store(num, '+FLAGS', '\\Deleted')
		i = i + 1

Eliminar la aleatoriedad en un juego

Juegos

En Deterministic Doom hace la prueba de eliminar la aleatoriedad del conocido juego Doom. Para ello, primero observa que el juego no utiliza ninguna fuente de aleatoriedad externa, sino que incluye una tabla de valores de donde se toman los valores para diversas acciones en el juego:

Rather than consume system randomness, Doom has a fixed 256-value random number table from which numbers are pulled by aspects of the game logic

Por otra parte, los efectos son los que uno podría imaginar (y algunos otros): desde el comportamiento de los atacantes a diversos efectos de imagen, pasando por las armas que se utilizan.

Prueba con distintos valores, por ejemplo:

With 0x00, monsters never make their idle noises (breathing etc.) On the other hand, with 0xFF, they always do: so often, that each sample collides with the previous one, and you just get a sort-of monster drone. This is quite overwhelming with even a small pack of monsters.

Curioso.

Más fallos con una larga historia

Bicho

Es un tema recurrente hablar sobre el mito de los miles de ojos mirando. Ni en código abierto Bugs con una larga historia. El caso de LZO ni, por supuesto, en código propietario (supuestamente profesionalmente controlado).

Traemos esta vez un fallo con casi 20 años, 18-year-old bug can be exploited to steal credentials of Windows users en el que no entraremos en los detalles técnicos:

A new technique for exploiting an 18-year-old bug in Windows Server Message Block (SMB), which would allow attackers to intercept user credentials, had been uncovered by Cylance researcher Brian Wallace.

Pero que muestra que a veces los fallos son muy resistentes al paso del tiempo. Y algún día se descubren.

Para los interesandos, más detalles técnicos en SPEAR: Redirect to SMB.

Firmar el código que se ejecuta en el cliente o en el servidor

Firmas Desde hace tiempo tengo una idea un poco loca: en estos tiempos en los que tanto software se ejecuta directamente en un servidor y no tenemos ninguna forma de verificar lo que sucede sería interesante poder ‘certificar’ de alguna forma que el código que se ejecuta es el debido. Por ejemplo, si alguien está usando el servidor web Apache, tal vez debería ser posible en algunos casos poder verificar que efectivamente se ejecuta el código sin modificar, etc. Ya que no podemos auditar el programa que utilizamos, sería una forma de poder ver el código (que tal vez estaría disponible en algún repositorio) y estar seguros de que lo que se ejecuta es justamente lo que vemos.

Por eso me llamó la atención la propuesta/pregunta de Propuesta: ¿Un plugin para autorizar JS en cifrados online? donde se limita el problema a la ejecución de código en JavaScript:

En todos estos casos se emplea código javascript (JS) que se descarga y ejecuta en el navegador del usuario, de manera que el servidor nunca llega a conocer su pasword, desarrollándose todo el proceso de cifrado y descifrado siempre del lado del cliente.

El punto débil de este criptosistema ocurre cuando la web ve comprometida su seguridad y con ella la de su código JS, ya sea por la intervención de un programador deshonesto de la misma organización, ya sea por la intervención de terceros que pueden introducir fragmentos de código malicioso con objeto, por ejemplo, de abrir un socket durante el proceso de cifrado para capturar y enviar la clave del usuario a un determinado sitio.

No se si la propuesta ha avanzado en alguna dirección pero a lo mejor valía la pena probar.

Motivos por los que debería gustarnos Java

Libro: De Euclides a Java Nunca he sido un gran fan de Java. Tampoco he hecho programas de tamaño suficinte como para poder criticarlo o alabarlo con criterio, la verdad. El otro día leía una ‘queja’ que ahora no soy capaz de encontrar donde alguien decía que Oracle no le estaba prestando suficiente atención. Y también otra ¿Se ha convertido Java en un problema para el acceso a la administración electrónica? aunque en este caso no termino de tener clara la conclusión porque me resisto a creer que nadie haya sido capaz de superar el problema de los certificados utilizando algo que no sea el navegador y Java.

A pesar de todo lo dicho, me gustó leer una serie de diez entradas que se pueden leer a partir de 10 Reasons Why Java Now Rocks More Than Ever: Part 1 – The Java Compiler donde se van desgranando diversos motivos por los que debería gustarnos la plataforma.

Para perezosos y personas interesadas sólo en alguna de las partes (o como anzuelo para, a partir de ahí, leerlas todas), el índice:

  1. The Java Compiler
  2. The Core API
  3. Open-Source
  4. The Java Memory Model
  5. High-Performance JVM
  6. Bytecode
  7. Intelligent IDEs
  8. Profiling Tools
  9. Backwards Compatibility
  10. Maturity With Innovation

Lo de la compatibilidad hacia atrás me ha recordado una historia vieja de Joel Spolsky How Microsoft Lost the API War. Lo enlazámabos en su día en la bitácora de BarraPunto, que allí sigue: Joel, la API de Windows y el desarrollo web. Pocas veces nos acordamos cuando empezamos un proyecto nuevo que su vida debería larga y que eso tiene consecuencias cuando apostamos por tecnologías muy novedosas.

Actualización (2015-11-25): El amigo @vrruiz me señala Even If Oracle Is Losing Interest In Java, Should You Worry? como una posible fuente acerca de lo que comentaba arriba de la pérdida de interés en Java por parte de Oracle. Allí se enlaza a esta nota Insider: Oracle has lost interest in Java que creo que es la que yo vi en su momento. Quede aquí referenciada por completitud.

Las actualizaciones ... ¿como ventaja competitiva?

En la carretera Seguimos con el tema de las actualizaciones.

En la introducción de la parte de la asignatura de desarrollo seguro en la que participo, comentábamos el otro día (transparencias en [PDF] Algunos datos sobre desarrollo y seguridad de aplicaciones que no podemos esperar que los usuarios actualicen (y mucho menos que lo hagan rápidamente).

En los últimos años se ha conseguido que determinados grupos de usuarios estén pendientes, al menos, de las últimas versiones de sus sistemas e instalen las actualizaciones, pero todavía parece que no es lo habitual entre la generalidad de los usuarios (ejercicio: observar la reacción de cualquier usuario medio ante las alertas de actualización de su dispositivo móvil; leer los mensajes con ellos para ver qué interpretan y sus intenciones al respeto).

Si pasamos al internet de las cosas (internet of things, IoT) con dispositivos de lo más variopinto conectados la cosa se complica: las interfaces son más escuetas y los sistemas de actualización pueden ser algo más complicados.

Recientemente se descubrían fallos de seguridad que permitían atacar a algunos modelos de Jeep Cherokee. También otros fallos que permitirían realizar algo parecido a través del sistema de información y entretenimiento del Tesla Model S (lo cuentan en How the Jeep Hack Reveals Tesla’s Biggest Advantage.

En el caso de los primeros la firma se vio obligada a hacer una llamada a los propietarios de los vehículos y/o a enviarles un USB con la actualización:

But the big difference between these scenarios is what happened next. Fiat Chrysler had to recall 1.4 million Jeeps that could potentially be vulnerable to the hack, but the “recall” actually amounted to mailing Jeep owners a USB stick that they could plug into their vehicle’s dashboard port in order to give the car the necessary patch.

En el segundo caso, al tratarse de coches conectados y que reciben actualizaciones a través de internet (OTA, Over The Air) la actualización fue envíada por ese sistema y los coches actualizados (parece que tenían que aceptar, pero seguramente están en ese sector que actualiza y agradece las novedades; estaría bien poder conocer el porcentaje de los que dijo ‘no’):

Tesla, on the other hand, was able to automatically send a patch to all its Model S vehicles on Wednesday through an over-the-air update, a method more akin to how your smartphone gets software fixes.

En Researchers Hacked a Model S, But Tesla’s Already Released a Patch hablan de ventaja en seguridad (‘Tesla cars have one security advantage that a lot of other cars don’t’) y cuentan más detalles de los fallos.

En todo caso, parece una ventaja desde el punto de vista de la seguridad clara para Tesla, con la preocupación que siempre tendremos de que no sabemos qué ocurre realmente con esas actualizaciones ni qué incluyen.

Lo que no tengo tan claro es que alguien pueda terminar decidiéndose por un modelo u otro en función de esos factores; sí que puede ser un factor determinante para las marcas, que empiecen a darse cuenta del ahorro que puede suponer (¿con sus riesgos asociados?) instalar en los vehículos sistemas de actualización adecuados.

Esta entrada está basada en Las actualizaciones … ¿como ventaja competitiva?.

Actualizando. Espere

Actualización Como por efecto mágico, nuestro sistema siempre decide actualizarse cuando menos conviene. Es paradigmático y forma parte de casi cualquier acto que se organiza cuando esos PCs proporcionados por la organización empiezan a mandar avisos diversos, muchos de ellos de actualizaciones de programas.

En este caso no sabemos si es la típica excusa (‘mi perro se comió los deberes’, ‘falló el ordenador’) pero nos contaban en German pro basketball team relegated to lower division due to Windows update de un equipo de baloncesto que habría visto afectada su participacińo en la liga cuando el equipo que manejaba el marcador comenzó a actualizarse antes de empezar el partido y retrasó todo.

“But as both teams warmed up, the computer crashed,” he said. “When we booted it again at 7:20pm, it started automatically downloading updates. But we did not initiate anything.”

After all the updates were installed, Paderborn was ready to start the game at 7:55pm.

¿Quién no tiene alguna anécdota que contar relacionada con las actualizaciones?

Confíamos en que los equipos están allí dispuestos para atender nuestras necesidades sin proporcionales ni prestar atención a las suyas más básicas.

Al final, no es más que dedicar tiempo e incluir en nuestros procesos el mantenimiento para que no nos sucedan estas situaciones desagradables

Elogio de Python por el equipo de ingeniería de PayPal

Portada Libro Python Desde hace algún tiempo, cuando tengo que hacer un programita para resolver un problema de manera rápida mi lenguaje elegido es Python. También voy encontrándome mis limitaciones, esencialmente por no dedicarle atención suficiente a todo el entorno que ofrece para trabajar. De hecho, ya algunas entradas sobre Python en esta bitácora. Principalmente desarrollos que he ido haciendo pequeñitos que tal vez podrían servirle a alguien más alguna vez.

Por eso me gustó leer 10 Myths of Enterprise Python que es un elogio por parte del equipo de ingeniería de PayPal, tratando de aclarar algunas ideas erróneas sobre el lenguaje. Las listo:

  1. Python is a new language
  2. Python is not compiled
  3. Python is not secure
  4. Python is a scripting language
  5. Python is weakly-typed
  6. Python is slow
  7. Python does not scale
  8. Python lacks good concurrency support
  9. Python programmers are scarce
  10. Python is not for big projects

Vale la pena leerlas y echarles un vistazo para ver los argumentos.

Mi relación con Python se basa fundamentalmente en que es rápido para hacer pruebas (con la ventaja del intérprete para terminar de comprender cosas que no tienes muy controladas) y, a la vez, permitiría evolucionar a proyectos más grandes (que con scripts de shell no es trivial). También sus ‘batteries included’ con bibliotecas disponibles casi para cualquier cosa que podamos querer hacer.

Mis quejas con el lenguaje, que también las hay, tendrían que ver con su incómodo sistema de gestión de codificaciones (quién no se haya enfrentado nunca al problema que nos diga como lo hizo), y la transición a Python 3 que no termina de llegar del todo.

Entre mis carencias, la gestión y pruebas con distintas versiones del lenguaje y el lío que (creo que) tengo montado en mis sistemas con la instalación de bibliotecas de terceros de manera poco adecuada. Estoy empezando a explorar Virtual Environments y pyenv para ver si controlo estas cosas un poco mejor.

Demandas por fallos de software: los coches

Portada Geekonomics De ven en cuando se habla de la responsabilidad de los desarrolladores de programas informáticos. El otro día preparando una clase recuperaba y actualizaba un par de enlaces sobre el tema: Is It Time For Software Liability? y Should Software Companies Be Legally Liable For Security Breaches? al que añadiré este que comento aquí. También se publicó hace unos años el libro Geekonomics: The Real Cost of Insecure Software (es un extracto del primer capítulo) donde se hacía un análisis sobre el tema desde diversas perspectivas.

En Lawsuit seeks damages against automakers and their hackable cars hablan justamente del tema en la industria del automóvil basándose en que los fabricantes no han tomado las medidas necesarias para proteger los vehículos de los atacantes. Incluso un Senador de los EEUU respaldaría esa idea:

The lawsuit also cites a study released last month by Sen. Edward Markey (D-Mass.) that claims automakers have fallen far short in their responsibility to secure their vehicles’ electronics

El informe está en [PDF] Analysis of automobile manufacturers’ efforts reveals security and privacy gaps Tracking & Hacking: Security & Privacy Gaps Put American Drivers at Risk.

Eso sin hablar de las limitaciones informáticas de los coches modernos, en los que normalmente (y afortunadamente, si hacemos caso a los riesgos aparecidos) hay muy pocas de las posibilidades que nos ofrece un ordenador aprovechadasa adecuadamente:

“You can get into five-year-old luxury car and it…feels like a Nintendo game…compared to the experience on your smartphone,” Morrison said in an earlier interview with Computerworld.

Que también tiene que ver con lo rápido que se quedarían anticuados (¿imaginas una pantalla como la de tu teléfono móvil de hace 5 años para tener en el vehículo durante otros cinco años más?).

En Senate Bill Seeks Standards For Cars’ Defenses From Hackers nos cuentan los planes sobre cómo abrodar el problema. Sin embargo, parece que las propuestas irían más bien en la línea de buscar ‘standards’ y buenas prácticas que las propias leyes (que era algo que se comentaba también en Informe sobre ciberseguridad nacional en EEUU.

No se cómo andará la reclamación legal pero desde luego parece que hay un problema y ya han aparecido los primeros intentos de soluciones legales. Hemos hablado de coches en mbpfernand0 y coches en esta bitácora.

Al final, todo tiene mucho que ver con las consecuencias económicas que tendrían ciertas consecuencias drásticas: probablemente la informática costaría más (dinero y/o tiempo) y todo tendría que ir algo más despacio tomando, tal vez, menos riesgos. Pero seguramente este es un debate que vamos a seguir presenciando en los próximos tiempos.

Command and Control con GMail

Cuadro de mandos Una de las tareas que tienen los ‘malos’ para organizar sus ataques es la gestión de los equipos comprometidos. No hace tanto esto se hacía mediante canales de IRC, y la cosa ha ido evolucionando hacia redes sociales y otros sistemad de comunicacación (nuestro propio bot -no malicioso-, del que hemos hablado a veces no es más que un sistema de control de un computador remoto, mediante XMPP Segundo bot: avanzamos). Un ataque de este tipo sólo necesita que el programa malicioso pueda escuchar de alguna manera las instrucciones y pueda comunicarnos las respuestas.

En este caso podíamos leer hace algún tiempo ¿Gmail como server de C&C? OMG! – Parte I. Lamentablemente la parte II no se ha llegado a materializar aún donde se comenta sobre Pyexfil - Using Python to make Gmail a C&C server .

Se trata de un programa en Python que permite controlar un equipo infectado mediante el envío y recepción de mensajes de correo electrónico. El programa es capaz de leerlos, ejecutar las instrucciones y responder, si es necesario. Si conseguimos hacer que se ejecute en el equipo de vez en cuando tendremos un mecanismo para comunicarnos que además puede ser bastante sigilioso (¿cómo va a despertar la sospecha una consulta a un servidor de correo de amplia implantación?).

Curioso.