Mala semana para la seguridad de las extensiones en Firefox y Chrome

Investigadores de seguridad presentaron la semana pasada, en la Black Hat Asia 2016, bajo la ponencia «Automated Detection of Firefox Extension-Reuse Vulnerabilities» una extensión que reutiliza código de otras ya instaladas con fines maliciosos. Es una técnica nueva (extension-reuse) interesante.

En febrero presentaron un artículo sobre la misma vulnerabilidad (CrossFire: An Analysis of Firefox Extension-Reuse Vulnerabilities) en el simposium «The Network and Distributed System Security Symposium 2016» organizado por la Internet Society.

Y siguiendo con los ataques de seguridad a las extensiones, hoy se publica una noticia sobre una empresa que en febrero compró una extensión bastante popular (Better History) para inyectarle código malicioso que hace que los navegadores de sus usuarios sean redirigidos, a través de un enlace lnkr.us, a páginas con banners -al parecer a la página que más pague a la empresa- cada vez que pinchan en un enlace (realmente el 50% de la veces y no es una redirección simple, sino que la página original a la que el usuario se dirigía también se abre). El comportamiento no es maligno únicamente por esto, sino porque la empresa de esta extensión está recogiendo datos privados sobre las URL que los usuarios visitan. Para más inri, el código fuente de Better History en GitHub no refleja los añadidos maliciosos que la compañía ha introducido.

Google ha eliminado la extensión de la Chrome Store, pero los usuarios han advertido de que este comportamiento se repite en otras extensiones populares como Chrome Currency Converter, Web Timer, User-Agent Switcher, Better History, 4chan Plus, and Hide My Adblocker.

Google ha eliminado también User-Agent Switcher, pero el resto sigue online.

Instalando mod_wsgi en OSX El Capitan

Receta rápida:

$ git clone https://github.com/GrahamDumpleton/mod_wsgi.git
$ cd mod_wsgi
$ ./configure
$ make
$ sudo make install
$ sudo vim /etc/apache2/httpd.conf

Añadir las siguientes dos líneas:

LoadModule wsgi_module libexec/apache2/mod_wsgi.so
WSGIScriptAlias / /Library/WebServer/Documents/

Reiniciar Apache y comprobar:

$ sudo apachectl restart
$ apachectl -M | grep wsgi
 wsgi_module (shared)

Podemos probar con este Hello World (hello.py). Copiarlo en /Library/WebServer/Documents y abrirlo desde el navegador con http://localhost/hello.py :

import os, sys
sys.path.append('.')
def application(environ, start_response):
    status = '200 OK'
    output = 'Hello world!!\n'
    response_headers = [('Content-type', 'text/plain'),
        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]

Done.

Transmission, torrents, OSX y malware KeRanger

Captura de pantalla 2016-03-07 a las 22.49.09 Cuando necesito descargar torrents, uso Transmission en Linux y uTorrent en OSX. No es que uTorrent esté libre de pecado (Spigot -PUP-,  EpicScale -mining de bitcoin no deseado, y demás basura), pero la semana pasada (4 de marzo) Transmission para OSX llevaba de regalo  KeRanger, ransomware. Sí, malware que cifra el contenido de tu disco duro y te pide un rescate – pagado en bitcoin, por supuesto- para obtener la clave que lo descifra. Parece ser el primer caso de ransomware dirigido específicamente a usuarios de OSX. Fue la gente de Palo Alto Networks fueron los primeros en dar el aviso, indicando que la web de Transmission había sido comprometida, dejando un fichero de instalación .dmg(la versión 2.90 de Transmission) infectado con KeRanger. Lo «bonito» del asunto es que esta versión de KeRanger había sido firmada con un certificado válido de desarrollador de aplicaciones para OSX, saltándose el control básico de Apple Gatekeeper que impide a un usuario básico instalar una aplicación que no venga firmada (se salta abriendo el binario con el menú contextual mientras pulsas Control, pero es una primera barrera de seguridad). Si el usuario instaló la versión infectada de Transmission, esta ejecutará una versión incrustada de KeRanger, esperará 3 días (suele ser habitual esperar a ejecutar el castigo, para ocultar al usuario el origen de la infección) y se comunicará con un servidor C&C (Command & Control) sobre la red Tor. A partir de ahí, cifrado del disco y petición de rescate (400 dólares).

Apple ha actuado rápido. Lo primero, invalidar el certificado con el que se firmó la aplicación en cuestión. Lo segundo, añadir una regla a XProtect, el sistema de lista negra que usa OSX por defecto. Puedes consultar los bichos que pululan por Internet en este fichero de tu OSX: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plist. ¿El primero de la lista? Nuestro amigo KeRanger:

Captura de pantalla 2016-03-07 a las 23.21.41

El análisis técnico del bicho en la página de Palo Alto Networks merece mucho la pena. Verás que el desarrollador está preparando funciones específicas para buscar y cifrar backups de Time Machine (qué angelito…). Verás también que usa tanto cifrado asimétrico (RSA) para cifrar un número elegido al azar junto a un IV dependiente del contenido del fichero, con lo que formará la clave que usará para cifrar el contenido del fichero usando cifrado simétrico (AES).

El 5 de marzo la gente de Transmission eliminó el ejecutable infectado de su web. Apple también ha hecho su trabajo. Pero el secuestro de webs para implantar malware parece que está de moda. Hace un par de semanas fue el turno de Linux Mint. Esta semana ha caído Transmission. ¿Quién será el siguiente?

Formateo y validación de objetos JSON

En esta ocasión, aprovechando que esta semana se estudia el formato JSON en una de mis clases, os quería recomendar un par de utilidades que utilizo a menudo: la herramienta jq y el plugin JSONView.

jq es una utilidad de la línea de comandos disponible para Linux, OS X y Windows que permite validar y visualizar de forma muy agradable objetos JSON. La mejor forma de apreciar el uso de jq es por medio de un ejemplo. En la siguiente figura, muestro un objeto JSON en la terminal sin usar jq. A continuación lo vuelvo a mostrar, esta vez filtrándolo con jq. Mucho mejor, ¿no?

Captura de pantalla 2016-03-07 a las 21.29.34

 

jq también detecta objetos JSON inválidos, marcando dónde se encuentra el error:

Captura de pantalla 2016-03-07 a las 22.00.40

JSONView es similar a jq, pero funciona como plugin o extensión, tanto de Google Chrome como de Mozilla Firefox. Veamos un ejemplo con el resultado de una llamada al API de OpenWeatherMap.

Sin usar JSONView:

Captura de pantalla 2016-03-07 a las 21.44.06

Con la extensión JSONView instalada:

Captura de pantalla 2016-03-07 a las 21.43.51

Sí, representan exactamente el mismo resultado. Pero uno es legible por humanos y el otro no 🙂

¿Conocíais estas utilidades? ¿Qué extensiones usáis en vuestros desarrollos? (HTML5, JS, PHP, whatever…)

Demasiadas conexiones a MySQL desde R

Estoy desarrollando una nueva aplicación en R+Shiny. Entre otras cosas, el servidor Shiny necesita acceder a los datos de una BBDD en MySQL. Tengo código en R que accede a MySQL sin problemas, abre y cierra las conexiones bien, sin leaks  por dejar conexiones abiertas. Bueno, eso es lo que creía… cuando por alguna razón la aplicación fallaba, podían darse casos en los que alguna conexión se quedaba abierta. Por una o dos, no pasaba «nada». Pero probando y probando, llegué a este error:

«cannot allocate a new connection — maximum of 16 connections  already opened»

Vaya… el primer problema es: ¿cómo desconecto las conexiones abiertas? La respuesta a esto en la lista de distribución de R:

 cons <- dbListConnections(MySQL()) 
 for(con in cons) 
  dbDisconnect(con)

Y ahora, ¿cómo evitar el error? Lo ideal sería establecer una especie de conexión singleton que se reutilizara desde todo el código. La respuesta a esto, en StackOverflow (cómo no ;-))

library(RMySQL)
getConnection <- function(group) {
  if (!exists('.connection', where=.GlobalEnv)) {
    .connection <<- dbConnect(MySQL(), group=group)
  } else if (class(try(dbGetQuery(.connection, "SELECT 1"))) == "try-error") {
    dbDisconnect(.connection)
    .connection <<- dbConnect(MySQL(), group=group)
  }
  return(.connection)
}

Este código comprueba si existe una conexión en el entorno global. Si no existe, la crea y la devuelve.
Si existe, comprueba que se pueda usar. Si no se puede usar, desconecta y vuelve a crear la conexión, para devolverla.
Es decir, funciona como una caché (o puede verse también como un objeto singleton de tipo connection).
Podríamos ignorar el parámetro group de la función getConnection y en su lugar, usar:

 dbConnect(MySQL(), user=login, password=pass, db=database, host=host)

allí donde fuera necesario.