Archive

Archive for the ‘Services – Software’ Category

Generación personalizada de direcciones ONION de TOR con Shallot

junio 16, 2015 2 comentarios

Las direcciones ONION en TOR son cadenas con una longitud exacta de 16 caracteres, compuestas por los dígitos entre 2-7 y las letras en minúsculas de a-z. Dichas direcciones generalmente se crean de forma automática por cualquier cliente de TOR, pero en ocasiones, se pueden encontrar sitios en la web profunda de TOR con direcciones ONION que no parecen ser tan aleatorias como la mayoría, en ocasiones tienen patrones fijos que determinan el contenido y/o temática del servicio oculto. Un ejemplo es Facebook, que cuenta con un servicio oculto en la web profunda de TOR para aquellos que quieran acceder a esta popular red social y ya de paso, perder su privacidad y probablemente el anonimato que brinda TOR. La dirección ONION de facebook en la web profunda de TOR es esta: facebookcorewwwi.onion y como se puede apreciar, existe un patrón bastante claro que además, resulta fácil de memorizar. Ahora bien, lo cierto es que personalizar la dirección completa (16 caracteres) con la capacidad de computo que tenemos actualmente resulta imposible, tal como comentaba en un articulo que he escrito hace algún tiempo, calcular y en consecuencia, descubrir un servicio oculto en TOR, puede llevar millones de años, una escala de tiempo que evidentemente no es tolerable. No obstante, si que se puede personalizar una parte de dicha dirección en poco tiempo, todo depende del número de caracteres que se quiera aplicar al patrón. Para hacer esto, existe una herramienta muy fácil de instalar y utilizar, dicha utilidad es Shallot.

INSTALACIÓN Y USO DE SHALLOT

Shallot es una herramienta que permite aplicar un patrón para personalizar una parte de la dirección ONION de un servicio oculto. Los patrones que se pueden aplicar típicamente son expresiones regulares que permiten indicar la forma en la que se debe generar la clave privada del servicio oculto y en consecuencia, la dirección ONION del mismo. Es un programa que se encuentra escrito en lenguaje C y solamente tiene dos dependencias: libssl y libcrypto, librerías que son bastante comunes en sistemas Linux. El proyecto se puede descargar desde GitHub y el proceso de instalación es tan simple como ejecutar “configure” y “make”

>git clone https://github.com/katmagic/Shallot.git

>./configure
>make

Las opciones que admite Shallot se pueden ver a continuación

>./shallot

Usage: shallot [-dmopv] [-f <file>] [-t count] [-x time] [-e limit] pattern

-d : Daemonize (requires -f)

-m : Monitor mode (incompatible with -f)

-o : Optimize RSA key size to improve SHA-1 hashing speed

-p : Print ‘pattern’ help and exit

-f <file> : Write output to <file>

-t count : Forces exactly count threads to be spawned

-x secs : Sets a limit on the maximum execution time. Has no effect without -m

-e limit : Manually define the limit for e

Version: 0.0.3-alpha

 

El interruptor “-p” puede ser útil para conocer algunos de los patrones (expresiones regulares) que se pueden aplicar con Shallot.

./shallot -p

base32 alphabet allows letters [a-z] and digits [2-7]

pattern can be a POSIX-style regular expression, e.g.

xxx must contain ‘xxx’

bar$ must end with ‘bar’

^foo must begin with ‘foo’

b[a4]r may contain leetspeech ;)

^ab|^cd must begin with ‘ab’ or ‘cd’

[a-z]{16} must contain letters only, no digits

^dusk.*dawn$ must begin with ‘dusk’ and end with ‘dawn’

 

Como se puede apreciar, algunas de las expresiones de ejemplo permiten aplicar patrones muy variados, como por ejemplo que la dirección ONION debe comenzar y/o terminar con una cadena determinada, que contenga solamente números o letras o que contenga en cualquier posición de la dirección una cadena determinada.
También existen otras opciones que permiten controlar el tiempo máximo en el que se debe ejecutar la herramienta, si se debe ejecutar como un proceso en “background” y si el resultado (clave privada para el servicio oculto) se debe almacenar en un fichero. Algunos ejemplos del uso de estos interruptores se enseña a continuación

>./shallot -f /home/adastra/private_key ^hack

>./shallot -m -o ^hacker

>./shallot -m -t 15 ^hacker

En todos los casos, después de procesar y descubrir una clave privada cuya dirección ONION generada contenga el patrón, se pinta por pantalla o se crea un fichero con dicha clave privada para que sea utilizada por un servicio oculto.
Como comentaba antes, el número de caracteres especificados en el patrón es importante y determina si es posible obtener una clave privada que encaje con el patrón y cuánto tiempo puede tardar el calculo de dicha clave. En el proyecto de GitHub de Shallot se enseña la siguiente tabla que nos da una idea del número de caracteres que podemos personalizar en la dirección ONION.

characters time to generate (approx.)
1 less than 1 second
2 less than 1 second
3 less than 1 second
4 2 seconds
5 1 minute
6 30 minute
7 1 day
8 25 days
9 2.5 years
10 40 years
11 640 years
12 10 millenia
13 160 millenia
14 2.6 million years

Las pruebas anteriores las ha realizado el autor con un ordenador de 1.5Gh de procesador. Si bien es cierto que se puede utilizar ordenadores mucho más potentes, las estimaciones anteriores no sufren cambios considerables con una mayor capacidad de computo, además, solamente se ha llegado a calcular hasta 14 caracteres, la cifra con 15 y 16 caracteres puede llegar a billones de años. Muchísimo más de lo que estamos dispuestos a esperar, por mucho que estemos acostumbrados a utilizar sistemas Windows.
Suponiendo que se utiliza un patrón con pocos caracteres, se puede generar una clave privada en muy poco tiempo, de hecho, las dificultades comienzan a partir de 7 o 8 caracteres, pero cualquier patrón que esté por debajo de dicho valor, puede ser procesado por Shallot en un tiempo bastante razonable.
Uno de los resultados que da la herramienta tras aplicar el patrón “^hack” es el siguiente

—————————————————————-

Found matching domain after 998147 tries: hacktkeocgipcjvv.onion

—————————————————————-

—–BEGIN RSA PRIVATE KEY—–

MIICWwIBAAKBgQCmZx9BMoG55KOoyAa0T43rNRW4z8m9vjgdXRxX2ZOaFMbrMITC

U6zm5CaauB0RYvu0m99/J9YhfXJQor69/YUIWMWGOXdn3CfVPML5kJWdCF68jhyE

qmPJAaTuodv7rwlB0KyTzOYUGNLDN/yZey9aG2CKWLfTX/w3Aq7c/6Y20QIDBKSB

AoGABFqfSWmx3CIHU40PJCv2ecf61m7LZcAQErvXddYZDCodEYKXDypWJZatQjKm

Whl9DGCZIMR3jpfVrKlIVjwT8+ERk35DXdRGzWi0n/y8be5XokYMnTreEbkcsprR

H8TeN6cJPwrjgXnd4g9Z2q9luKkDegdGLbsKY9nnh8lf5oUCQQDZi+lDL7S/jEoX

k5Xs805cTLPnqdGT0RelivchoGm03U2ggIUycCLv0SM6VaRcKNsBrGBtWg5jznu9

Xm9865xvAkEAw9DuwqkXK+WixHVY+uoT+LUHmBRJiVV+ZHKUzCOvF4yTxqGNCMAM

LcuCZtiamFbA4YQnBHAMRpMJt12/OSuAvwJAQjs2GYeqUmYE0MFt99KYhA2HHDny

DpSzwriBqAKC/lzk/SnEyYw5nBb/+zLYS3+zNUEAEZ8ktwIF1eFVriczdQJAE6qG

q9J5kLbmVuyhkBB0zO5hcCE5EFVren5/XUGrzOz1hJbv4Q+9TkqDO3xaQ/v+iIqt

hmu8XPNRhi50Q4vXhwJAQywFaZosVqFLUPJB4AmMeKQ2nPHpSLVVWFVPNNTypDZC

LDJgX849UGd0Nu9bCTWFtJaFROGUOa8U2cIsa8N6iQ==

—–END RSA PRIVATE KEY—–

A continuación, solamente es necesario incluir el contenido anterior en un fichero con nombre “private_key” que se deberá ubicar en el directorio que se declara en la propiedad “HiddenServiceDir” del fichero de configuración de TOR (torrc).

HidenServiceDir /home/adastra/servicioOculto

HiddenServicePort 80 127.0.0.1:80

Con las dos directivas anteriores se define un servicio oculto que va a procesar peticiones de los clientes por el puerto 80 en la dirección ONION generada. En este caso, el fichero “private_key” con la clave RSA generada por Shallot debe ubicarse en el directorio “/home/adastra/servicioOculto”. Una vez hecho esto, basta con arrancar la instancia de TOR utilizando el fichero torrc con las directivas anteriores y se podrá ver que en el directorio “/home/adastra/servicioOculto” existe un nuevo fichero llamado “hostname”, con la dirección ONION generada a partir de la clave privada definida en el fichero “private_key”.
Con estos sencillos pasos se puede personalizar una parte de la dirección ONION de un servicio oculto en TOR, algo que en algunos casos viene bien para tener direcciones que sean un poco más fáciles de recordar y compartir.

Saludos y Happy Hack!
Adastra.

Análisis de trafico con Netsniff-ng

junio 11, 2015 1 comentario

Netsniff-ng es una de esas herramientas que aunque tiene unas características muy interesantes y es muy potente, es más bien poco conocida. También es una de las tantas herramientas que llevo tiempo con ganas de mencionar aquí, pero por cuestiones de tiempo (y también porque se me olvida) no lo había hecho antes, hoy le ha llegado su turno. Se trata de un sniffer diseñado especialmente para sistemas Linux, muy similar a herramientas como TCPDump o TShark, pero con algunas ventajas adicionales. Una de ellas es su rendimiento, el cual es mucho más óptimo que otros sniffers existentes, ya que los paquetes manejados por Netsniff-ng no son copiados entre el espacio del kernel y el espacio del usuario, algo que es tan común en librerías como libpcap (De hecho, netsniff-ng no requiere de libpcap para su correcto funcionamiento).

Algunos sniffers realizan una serie de invocaciones a las system calls desde el espacio del usuario para realizar el proceso de captura de paquetes, los cuales son procesados en primera instancia por el kernel y almacenados en el kernel space. Este proceso es muy ineficiente, ya que se debe invocar a una (en algunos casos varias) system calls de la API de sockets del sistema operativo. Debido a esto, en las últimas versiones de la rama 2.4 y en prácticamente todas de la rama 2.6 del kernel de Linux se ha introducido PACKET_MMAP, un mecanismo que se encarga de crear un buffer compartido entre el kernel space y el user space para la captura y procesamiento de paquetes de red. Se trata de una característica antigua y que se encuentra integrada en prácticamente todos los sistemas Linux modernos por medio de la opción CONFIG_PACKET_MMAP. No obstante, para el correcto funcionamiento de netsniff-ng también se recomienda utilizar versiones recientes del kernel de Linux (>= 2.6.31) ya que implementan el concepto de “rings” del tipo RX y TX, los cuales permiten un control mucho más eficiente de los buffers utilizados para la recepción y transmisión de paquetes de datos. El tamaño de cada uno de estos rings puede variar dependiendo de las limitaciones físicas de la interfaz de red y típicamente se calcula en base al ancho de banda soportado por la interfaz de red.

INSTALACIÓN

El proceso de instalación es muy simple, basta con descargar la última versión estable desde el sitio web oficial (http://pub.netsniff-ng.org/netsniff-ng/) y descomprimir en cualquier directorio del sistema. También es posible instalar la versión de desarrollo que se encuentra en su repositorio GitHub (https://github.com/netsniff-ng/netsniff-ng.git) pero pueden haber errores y problemas a la hora de instalar, así que se recomienda tirar de la última versión estable.

>./configure

>make

>sudo make install

Con las instrucciones anteriores es suficiente para tener netsniff-ng instalado en el sistema local. A continuación, se puede ejecutar el comando “netsniff-ng” especificando la interfaz de red que será utilizada para el proceso de captura.

>sudo netsniff-ng -i eth0

Para ver todas las opciones de configuración disponibles en la herramienta, basta con ejecutar el comando con la opción “-h”

>sudo netsniff-ng -h

Esta herramienta tiene varias dependencias a librerías que se tienen que encontrar instaladas en el sistema, dichas dependencias se pueden ver en el fichero INSTALL (https://github.com/netsniff-ng/netsniff-ng/blob/master/INSTALL).

Uso básico y análisis de trafico con Netsniff-ng

La herramienta permite la captura de paquetes desde un dispositivo o un fichero de capturas (típicamente formato PCAP) y dicha información también puede ser inyectada/redireccionada a un dispositivo de red o un fichero de capturas. Un ejemplo muy sencillo seria el siguiente:

>netsniff-ng –in eth0 –out /home/adastra/Escritorio/dump.pcap -s icmp

En este caso se van a capturar todos los paquetes que utilicen el protocolo ICMP y que se transfieran por medio de la interfaz de red “eth0”. Con la opción “–out” se indica el destino al que deben redirigirse dichos paquetes, los cuales en este caso concreto, serán almacenados en un fichero PCAP. En el caso de que se indicase, por ejemplo, una interfaz de red, dichos paquetes serían inyectados a dicha interfaz de red. Finalmente, con la opción “-s” la información correspondientes a los paquetes capturados ya no serán enseñados por pantalla.

Hay que tener en cuenta que además de las opciones estándar que admite la herramienta, también es posible aplicar filtros sobre los paquetes capturados, como en este caso concreto en el que se han capturado todos los paquetes que utilicen protocolo ICMP. Estos filtros deben seguir las normas definidas en el estándar BPF (Berkeley Packet Filters) algo que es tan común en este tipo de herramientas (véase por ejemplo TCPDump o Wireshark). No obstante, por línea de comandos no es la única forma de especificar este tipo de filtros, también existe la posibilidad de crear ficheros con los filtros que se desea aplicar y pasarlos a la herramienta por medio de la opción “-f”. Existen algunos de estos ficheros que vienen con la herramienta y que permiten aplicar filtros que son bastante comunes cuando se trabaja con redes.

>netsniff-ng –in eth0 -f /etc/netsniff-ng/rules/icmp.bpf

 

Además de los filtros BPF, también soporta filtros especiales sobre el tipo de trafico a capturar aplicando el interruptor “-t”. Los posibles valores que puede asumir “-t” son los siguientes:

broadcast: Permite filtrar solamente el trafico broadcast.
multicast: Permite filtrar solamente el trafico multicast.
host: Permite filtrar solamente los paquetes cuyo destino es la máquina desde donde se ejecuta la herramienta.
others: Permite filtrar los paquetes cuyo origen o destino es distinto de la máquina desde donde se ejecuta la herramienta.
outgoing: Permite filtrar solamente los paquetes cuyo origen es la máquina desde donde se ejecuta la herramienta.

>netsniff-ng –in eth0 -t others -s

Por otro lado, tal como mencionaba anteriormente, también es posible la reinyección de trafico utilizando esta herramienta, para ello se puede utilizar un fichero PCAP o una interfaz de red que contendrá/capturará los paquetes de datos que serán reinyectados en una interfaz de red determinada. Para ello, se debe utilizar también el interruptor “–mmap” tal como se enseña en el siguiente comando

>netsniff-ng –in /home/adastra/Escritorio/dump.pcap –mmap –out eth0 -k1000 –silent

De esta forma, la herramienta leerá los paquetes de datos incluidos en el fichero PCAP especificado con la opción “–in” y dichos paquetes serán inyectados a la interfaz de red especificada con el interruptor “–out”. Esto evidentemente sirve para generar trafico en el segmento de red y posiblemente, generar estímulos sobre un objetivo determinado. Todo depende de los contenidos del fichero PCAP, pero desde luego es una opción bastante interesante si se desea producir algún tipo de respuesta por parte de un objetivo determinado en el segmento de red.
Existen algunas otras opciones en el comando netsniff-ng, sin embargo no es la única herramienta que incluye el paquete Netsniff-ng, existen otras herramientas que son igualmente interesantes y que merece la pena conocer.

Ifpps

Se trata de una herramienta que permite generar estadísticas en tiempo real sobre los “rings” TX y RX del sistema operativo. Permite la visualización de datos directamente desde la consola o exportar dicha información a ficheros CVS o GNUPlot. Además, como prácticamente todas las herramientas incluidas en Netsniff-ng, permite utilizar varias CPUs para un mejor desempeño.

>ifpps -d eth0 –promisc

>ifpps -d eth0 –promisc -c

 

Astraceroute

Funciona como traceroute para tracear los sistemas por los que pasa un paquete antes de llegar a su destino, el beneficio adicional de esta herramienta es que permite resolver el AS (Sistema Autónomo) de origen y utiliza la librería GeoIP para intentar obtener las referencias geográficas de cada AS encontrado.
Antes de poder utilizar esta herramienta, es necesario actualizar la base de datos de georeferencias con el siguiente comando.

>sudo astraceroute -i eth0 –update

Después de actualizar la base de datos, se puede utilizar el comando astraceroute con las opciones de configuración admitidas.

>astraceroute -i eth0 -N -F -L -H netsniff-ng.org

En este caso, se han utilizando las opciones -N y -F para ejecutar una resolución DNS inversa y enviando paquetes con la flag FIN habilitada respectivamente, luego -L y H permiten pintar las referencias geográficas encontradas (latitud y longitud) así como especificar el objetivo del análisis.
Espero que os haya gustado y que juguéis con esta estupenda herramienta.

Saludos y Happy Hack!
Adastra.

Pentesting contra servicios ocultos en TOR – Parte 2

junio 9, 2015 Deja un comentario

Tal como mencionaba en el artículo anterior sobre pentesting contra servicios ocultos en TOR, es posible que algunos crean que atacar un servicio oculto es una tarea compleja y que requiere de muchos conocimientos para llevarla a cabo, pero lo cierto es que no difiere de un proceso de pentesting convencional. Es importante tener en cuenta que cualquier servicio en la web profunda de TOR puede contener vulnerabilidades criticas que pueden afectar a su desempeño y seguridad, sin embargo, son muchos los usuarios de TOR, I2P o Freenet que creen que por utilizar este tipo de redes ya se encuentran “protegidos” y relajan o descuidan la seguridad de los servicios ocultos que crean y administran. Esto es un error y cualquier servicio que contenga vulnerabilidades puede ser igualmente explotable, aunque se encuentre en la “cyphernet” de TOR o I2P.

En el artículo anterior se explica como utilizar SOCAT para crear un túnel entre la máquina local y el servicio oculto que se desea atacar, utilizando por medio el proxy socks que típicamente se levanta cuando se arranca una instancia de TOR. Este es el mecanismo más sencillo y eficaz que se puede utilizar para realizar pruebas de pentesting contra servicios ocultos, no obstante es necesario mapear en puertos distintos cada una de las direcciones ONION que se desea atacar, no es cómodo pero desde luego resulta sencillo y fácil de implementar. En el post anterior explicaba cómo hacer esto contra un servicio oculto del tipo HTTP, el cual era soportado por una aplicación web vulnerable con Django-moth. En dicho post se explicaba el uso de Nikto y W3AF para comprometer el servicio oculto y ya de paso su anonimato, pero también es posible hacer esto mismo con otros servicios ocultos que no son el típico servidor web, sino también con cualquier servidor que funcione utilizando protocolo TCP. En este artículo se realizarán pruebas sencillas contra servicios ocultos del tipo FTP y SSH

Atacando un servicio oculto en TOR del tipo FTP

Existen muchas implementaciones del protocolo FTP tanto desde el lado del cliente como desde el lado del servidor y también, han sido muchas las vulnerabilidades que se han encontrado y explotado en dichas implementaciones. Si un servidor FTP vulnerable se expone en la web profunda de TOR, es probable que pueda seguir siendo utilizado sin mayores problemas en el caso de que solamente un grupo reducido de usuarios conozca su dirección ONION y no pretendan vulnerarlo, pero si un atacante descubre dicha dirección ONION no tardará demasiado en hacerse con el control de dicho servicio.
Las directivas utilizadas para crear un servicio FTP no son diferentes a las de cualquier otro tipo de servicio oculto, lo único que probablemente cambiará será el puerto y obviamente el directorio.

HiddenServiceDir /home/adastra/Escritorio/hidden_service_ftp/HiddenServicePort 21 127.0.0.1:21

Las líneas anteriores se incluirán en el fichero “torrc” y en la máquina donde se levanta la instancia de TOR, deberá existir un proceso vinculado al puerto 21. La dirección ONION generada, también responderá únicamente a las peticiones entrantes por el puerto 21.
Nuevamente se puede utilizar SOCAT para crear un túnel entre el servicio oculto y la máquina del atacante, pero eso si, es necesario que en la máquina del atacante se arranque una instancia de TOR que tenga la propiedad SOCKSPort establecida (bastante frecuente) para poder utilizar dicho proxy SOCKS y conseguir llegar al servicio oculto.

>socat TCP4-LISTEN:8000,reuseaddr,fork SOCKS4A:127.0.0.1:ondsyq4v4xcr6ct6.onion:21,socksport=9150

El puerto que se abrirá en la máquina del atacante será el 8000 y cualquier petición que llegue a dicho puerto, será automáticamente enrutada al servicio oculto en el puerto 21 cuya dirección ONION es “ondsyq4v4xcr6ct6”, evidentemente para que dicho enrutamiento funcione correctamente se debe establecer el proxy SOCKS, que en este caso es el puerto 9150 (puerto por defecto que utiliza TOR Browser).

Con todos los elementos dispuestos, se puede utilizar cualquier herramienta para realizar pruebas de penetración contra el servicio oculto, no obstante antes de hacer nada, es mejor comprobar que el túnel funciona correctamente y para ello, basta con realizar una petición al servidor FTP utilizando cualquier cliente.

pentestingserviciosocultos-II-1Conexión con el servicio oculto del tipo FTP utilizando SOCAT.

Después de verificar que la conexión se puede establecer, se puede utilizar una herramienta como Metasploit Framework para realizar pruebas automatizadas utilizando los módulos auxiliares que se encuentran incluidos en el framework.

pentestingserviciosocultos-II-2Ejecutando el módulo “auxiliary/scanner/ftp/ftp_login” de MSF contra el servicio oculto FTP

pentestingserviciosocultos-II-3Ejecutando otros módulos auxiliares de MSF contra el servicio oculto FTP

Atacando un servicio oculto en TOR del tipo SSH

SSH es un protocolo bastante conocido y utilizado por prácticamente todos los administradores de sistemas y también es un protocolo muy utilizado en la web profunda de TOR. No es sencillo encontrar direcciones ONION con este tipo de servicios, pero hay bastantes y a veces no se encuentran debidamente configurados.  Como mencionaba antes, la principal dificultad a la hora de atacar los servicios ocultos en TOR es que es muy difícil encontrar la dirección ONION de un servicio a atacar y más aun cuando se trata de servicios cuyas funciones son principalmente de administración, como es el caso de cualquier servicio SSH, normalmente son direcciones ONION que solamente las conocen aquellas personas que crean el servicio oculto y que intentan administrar sus servidores de forma remota y anónima. Sin embargo, una vez se descubre la dirección del servicio oculto en cuestión, nuevamente basta con crear un túnel cuyo endpoint será el servicio oculto y a continuación realizar pruebas de pentesting con las herramientas habituales. Suponiendo que la dirección del servicio oculto SSH a atacar es “klebohg2zv4b5j5u”, la siguiente imagen enseña la forma en la que se debe crear el túnel con SOCAT y cómo utilizar el cliente SSH en sistemas Linux para realizar la conexión contra el servicio oculto.

pentestingserviciosocultos-II-4Conexión al servicio oculto del tipo SSH

Después de verificar que el servicio se encuentra activo y que el túnel enruta las peticiones adecuadamente, se puede realizar un proceso de pentesting básico utilizando MSF.

pentestingserviciosocultos-II-5Ejecutando el módulo “ssh_version” de MSF contra el servicio oculto.

pentestingserviciosocultos-II-6Ejecutando el módulo “ssh_enumusers” de MSF contra el servicio oculto.

pentestingserviciosocultos-II-7Ejecutando el módulo “ssh_login” de MSF contra el servicio oculto.

Además de utilizar MSF también se pueden utilizar otras herramientas comunes, como por ejemplo THC Hydra.

pentestingserviciosocultos-II-8Ataque de fuerza bruta contra el servicio oculto utilizando THC Hydra.

Como se puede apreciar, realizar procesos de pentesting contra servicios ocultos en TOR no es una tarea demasiado compleja, aunque si que lo es descubrir las direcciones dichos servicios ocultos. Muchas veces creemos que por utilizar TOR las vulnerabilidades o una mala configuración del sistema es menos evidente o será más difícil de explotar. La realidad es que un servicio oculto en TOR o en cualquier otra red anónima es perfectamente explotable si dicho servicio contiene alguna vulnerabilidad, los vectores de ataque no cambian, solamente cambia el medio utilizado por el atacante.
Si tienes publicado un servicio oculto en cualquier red anónima, presta atención a las vulnerabilidades o malas configuraciones que pueda tener.

Un saludo y Happy Hack!
Adastra.

Pentesting contra servicios ocultos en TOR – Parte 1

junio 2, 2015 1 comentario

El sábado 30 de mayo realice una pequeña charla con los chicos de GR2Dest en la que hablé sobre anonimato con TOR y pentesting contra servicios ocultos. En dicha charla me centre especialmente en actividades de pentesting contra servicios ocultos en la red de TOR y si bien es cierto que no es algo complicado, creo que muchas personas no saben o no entienden como hacerlo. Por ese motivo me he animado a escribir un par de artículos explicando la forma en la que puedes utilizar algunas de las herramientas de pentesting más habituales para atacar los servicios ocultos que se encuentran en la red de TOR. Este es el primero de ellos, espero que sea de tu agrado y te resulte informativo.

Antes de comenzar, intentaré aclarar algunas cuestiones que son importantes sobre TOR. Tal como mencionaba en el artículo ataca un servicio oculto si te atreves los servicios ocultos en TOR se registran en las autoridades de directorio, donde cada registro se incluye en una tabla hash que se compone por la clave pública del servicio y su dirección onion, la cual estará compuesta por letras entre la a y la zeta en minúsculas y los números entre 2 y 7. Este valor se genera al aplicar el algoritmo Base32 sobre el hash SHA de la clave privada del servicio oculto. Suena complejo, pero en realidad es algo de lo que no tenemos que preocuparnos ya que el cliente de TOR se encarga de la generación de la dirección onion de forma automática. No obstante, conocer esa dirección “onion” es otra historia y ahí es donde reside la verdadera dificultad de atacar servicios ocultos en TOR: Su disponibilidad y que en algunos casos, solamente unos pocos usuarios tienen conocimiento de las direcciones que utilizan para transmitir información. Por poner un ejemplo, imaginaros por un segundo a un grupo de islamistas radicales que necesitan transferir documentos e información entre ellos y que se encuentran ubicados en distintos países. Evidentemente, su dios les exige que luchen contra el infiel y se oculten adecuadamente si quieren disfrutar de las 40 mujeres (o cabras) que están reservadas para ellos en el paraíso, por ese motivo el anonimato es una de sus prioridades principales. En este sentido, solamente un grupo reducido de usuarios conocen la dirección del servicio que utilizarán para intercambiar información y adicionalmente, dicho servicio puede estar disponible en una franja horaria determinada y el resto del tiempo puede encontrarse inactivo, con lo cual las probabilidades de que el servicio sea encontrado por cualquier usuario en la red de TOR son realmente bajas. En Tortazo, existe el modo “onion repository” que intenta descubrir direcciones de forma aleatoria o incremental y aunque funciona de un modo similar a otras aplicaciones como Shallot (https://github.com/katmagic/Shallot) el problema del descubrimiento sigue estando latente.

No obstante, si conoces la dirección ONION del servicio que quieres atacar, las cosas cambian muchísimo, ya que puedes utilizar las herramientas de pentesting que utilizas para auditar cualquier servicio en Internet. Puedes usar Metasploit Framework, W3AF, OpenVAS, NeXpose, Nikto, Nmap, etc, etc. Lo único que necesitas es conocer la dirección ONION del servicio que quieres atacar y arrancar una instancia de TOR levantando un proxy SOCKS. El mecanismo es muy sencillo, basta con crear un túnel que permita conectar el servicio oculto con un puerto arbitrario en la máquina local utilizando el proxy SOCKS levantado por la instancia de TOR. A partir de aquí, basta con ejecutar las herramientas anteriormente mencionadas o cualquier otra contra un puerto en la máquina local. Es tan fácil como suena y no requiere de configuraciones especiales. Eso si, todo debe funcionar con protocolo TCP, ya que UDP o ICMP no se encuentran soportados por TOR. En este artículo, explicaré cómo atacar un servicio HTTP utilizando herramientas de pentesting comunes.

Atacando un servicio oculto en TOR del tipo HTTP

Crear un servicio oculto en TOR no tiene ninguna dificultad, basta con especificar las directivas “HiddenServiceDir” y “HiddenServicePort” en el fichero de configuración utilizado para arrancar la instancia de TOR y poco más. Evidentemente, tienes que tener un servidor ejecutándose en el puerto indicado, de lo contrario solamente tendrás una dirección ONION pero nada que responda a las peticiones de los clientes.
Al utilizar las propiedades anteriores, la instancia de TOR se encargará de crear el directorio del servicio oculto y en él incluirá la clave privada del servicio (private_key) y el fichero en el que se incluye la dirección onion del servicio (hostname). En el caso de que el directorio indicado en la propiedad “HiddenServiceDir” ya exista, la instancia de TOR entiende que el servicio ha sido creado previamente y no intenta machacar el directorio, por el contrario, intenta utilizar los ficheros que en él se encuentran incluidos (hostname y private_key). Las siguientes directivas pueden ser utilizadas el fichero de configuración “torrc” que se utilizará para levantar la instancia de TOR.

HiddenServiceDir /home/adastra/Escritorio/hidden_service_django/HiddenServicePort 80 127.0.0.1:8080

Como se puede apreciar, es realmente simple. No requiere ninguna otra opción de configuración adicional, aunque evidentemente en el fichero “torrc” se incluirán muchas más opciones de configuración para personalizar el comportamiento de la instancia, pero esa es otra historia.

En el directorio “/home/adastra/Escritorio/hidden_service_django/ ” se crearán dos ficheros (hostname y private_key) que contienen la dirección ONION del servicio y su clave privada. Por otro lado, cuando un usuario de TOR ingrese a la dirección ONION del servicio por el puerto “80”, la instancia de TOR que recibe dicha petición se encargará de redirigirla al endpoint correspondiente, que en este caso será la máquina local en el puerto “8080”. Evidentemente, es necesario arrancar un servicio en dicho puerto y dicho servicio puede ser de cualquier tipo (SSH, HTTP, SMB, FTP, etc.) Lo que realmente importa es que funcione sobre TCP.
En este caso, para demostrar el uso de algunas herramientas de pentesting contra un servicio oculto vulnerable en la web profunda de TOR, vamos a arrancar una aplicación web con múltiples vulnerabilidades que utiliza el equipo de W3AF para realizar pruebas, dicha aplicación web vulnerable es Django-moth (https://github.com/andresriancho/django-moth)

>python manage runserver 8080

Después de arrancar la aplicación, se podrá acceder al servicio oculto utilizando cualquier otra instancia de TOR que permita el acceso a la web profunda de TOR, como por ejemplo “TOR Browser”.

pentestingserviciosocultos-1Django-moth como servicio oculto en la red de TOR

Ahora que el servicio vulnerable se encuentra levantado y es accesible en la web profunda de TOR, lo siguiente es intentar atacar dicho servicio de la misma forma que atacamos cualquier aplicación o servidor web en Internet por medio de herramientas de pentesting comunes. Utilizar herramientas de reconocimiento para aplicaciones web puede ser un buen inicio, como por ejemplo Nikto o algún script NSE de Nmap. No obstante, antes de hacerlo es necesario aplicar algún mecanismo para acceder a cualquier servicio oculto en la web profunda de TOR utilizando dichas herramientas. Para hacer esto, pueden aplicarse 2 enfoques, o bien la herramienta que se va a utilizar soporta el enrutamiento de peticiones por medio de un proxy SOCKS (algo que no todas soportan) o crear un túnel transparente que permita enrutar todas las peticiones al servicio oculto utilizando el proxy SOCKS levantado por una instancia de TOR (siempre y cuando dicha instancia tenga activa la propiedad SOCKSPort). La segunda alternativa resulta ser la más fiable, ya que no hay que aplicar ningún tipo de configuración adicional para que las herramientas funcionen correctamente, todo se hace de forma transparente por medio del proxy SOCKS de la instancia de TOR.
Para montar un túnel de estas características hay varias alternativas, una de ellas es creando un túnel SSH y habilitando el soporte para servidores proxy (algo bastante común en OpenSSH), utilizando un proxy transparente con librerías como Twisted o utilizando directamente SOCAT. Dado que utilizar SOCAT es lo más cómodo, fácil y conveniente, es una de las mejores alternativas.

>socat TCP4-LISTEN:7000,reuseaddr,fork SOCKS4A:127.0.0.1:fieqd7c2ljyyo54f.onion:80,socksport=9150

 

El comando anterior abrirá el puerto “7000” en la máquina local y utilizará el puerto 9150 (Proxy SOCKS de TOR) para enrutar todas las peticiones entrantes por el puerto “7000” al servicio oculto en el puerto 80. Esto se traduce a que se puede utilizar cualquier herramienta de pentesting web tirando directamente contra la máquina local en el puerto “7000” y SOCAT se encargará de redirigir todas peticiones realizadas desde dicho puerto al servicio oculto definido. Además de enrutar las peticiones desde el cliente hacia el endpoint (servicio oculto) otra de las características que tiene SOCAT es que los túneles creados con esta herramienta son bidireccionales, es decir, que no solamente es capaz de enrutar las peticiones a su correspondiente destino, sino que también es capaz de transmitir las respuestas que emite el servidor. A partir de aquí, realizar un proceso de pentesting contra el servicio oculto es mucho más fácil.

pentestingserviciosocultos-2Utilizando Nikto contra un servicio oculto en la red de TOR.

Dado que en este caso concreto el servicio oculto se encuentra soportado por la aplicación web vulnerable Django-moth, qué mejor forma de atacarlo que utilizando W3AF.

>./w3af_console

w3af>>> plugins audit os_commanding

w3af>>> target set target http://localhost:7000/audit/os_commanding/param_osc.py?param=-la

w3af>>> start

OS Commanding was found at: “http://localhost:7000/audit/os_commanding/param_osc.py&#8221;, using HTTP method GET. The sent data was: “param=%7C%2Fbin%2Fcat%20%2Fetc%2Fpasswd” The modified parameter was “param”. This vulnerability was found in the request with id 39.

Scan finished in 14 seconds.

Stopping the core…

Como se puede apreciar, se ha encontrado una vulnerabilidad y se ha registrado en la “Knowledge Base” de W3AF. A continuación, se puede intentar explotar dicha vulnerabilidad utilizando el plugin “os_commanding”

pentestingserviciosocultos-3Generando una consola contra el servicio oculto vulnerable utilizando W3AF

Como se puede apreciar, se ha generado una consola contra el servicio oculto utilizando W3AF. A partir de aquí, el atacante podrá ejecutar comandos directamente contra el servicio oculto vulnerable y de esta forma, romper su anonimato.

pentestingserviciosocultos-4Ejecutando comandos directamente contra el servicio oculto.

En este caso se está atacando a un servicio oculto del tipo HTTP, pero en la web profunda de TOR existen toda clase de servicios vulnerables, los cuales evidentemente también se pueden comprometer. Algunos de ellos los explicaré en el próximo post.

Un saludo y Happy Hack!
Adastra.

Serialización de objetos utilizando la Streaming Library y desarrollo de plugins I2P

mayo 19, 2015 Deja un comentario

En la entrada anterior se ha venido hablado de los beneficios que aporta la Streaming Library si eres un usuario de I2P y quieres automatizar el proceso de crear “peers” descentralizados que, utilizando la red de I2P, puedan comunicarse y transferir información. Esta librería se encuentra escrita en Java y cuenta con todas las características necesarias para poder interactuar con el protocolo I2CP y poder desplegar servicios que utilicen/establezcan puentes de entrada y salida desde la instancia local de I2P. Tal como mencionaba en el artículo anterior, el procedimiento para crear un emisor y un receptor es bastante simple y si el lector alguna vez ha tenido que trabajar con sockets y programación en entornos de red en cualquier lenguaje, rápidamente podrá apreciar que aunque la librería aporta clases nuevas, su funcionamiento es muy similar a los clásicos sockets “servidor” y “cliente”, de hecho, las clases principales de la Streaming library son “wrappers” de las las clases “ServerSocket” y “Socket” de Java, aunque evidentemente implementando toda la lógica necesaria para poder interactuar con I2P.
No obstante, cuando se navega por Internet en busca de información sobre el uso avanzado de está librería normalmente es muy complicado encontrar detalles técnicos que permitan adentrarse en su uso y casi en todos los casos, se implementa el típico ejemplo del servidor “echo”, en el que existe un cliente que actúa como emisor, un servidor que actúa como receptor y el receptor devuelve los mensajes de texto que envía el emisor, funcionando como un servidor “echo” muy simple, no obstante, uno de los principales beneficios con los que cuenta Java, es que tiene un sistema muy potente de serialización de objetos que permite compartir información entre diferentes JVM, algo que potencio enormemente la evolución de tecnologías tales como RMI, CORBA, JINI y posteriormente los tan conocidos EJB en el mundo de J2EE. En este caso, también es posible serializar objetos entre emisores y receptores I2P, lo que supone un abanico de posibilidades enorme a la hora de crear aplicaciones que utilicen la capa de anonimato que aporta I2P a sus usuarios, ya que se pueden crear objetos debidamente preparados para transmitir mucha más información que una cadena de texto. Para los que no lo sepáis, para poder serializar un objeto en Java, dicho objeto, sus atributos y todas las clases padre de las que hereda deben ser serializables también, lo cual se consigue implementando la interfaz “java.io.Serializable”, además, si alguno de los atributos de dicha clase no es serializable, debe utilizarse el modificador de acceso “transient” con el fin de indicarle a la JVM que dicho atributo debe utilizarse únicamente en el contexto de la JVM local y no se debe incluir en el proceso de serialización del objeto.
Dicho esto, queda claro que una de las labores más importantes a la hora de diseñar una aplicación que aproveche los beneficios de la Streaming Library, consiste precisamente en definir una estructura de objetos que contenga todas las relaciones y atributos necesarios para transmitir información entre los túneles de entrada y salida de la instancia de I2P. La estructura de clases en cuestión, además de ser serializable, debe de ser conocida por todos los “peers” que la utilicen, ya que de no ser así, un emisor puede enviar un objeto Java a un receptor, perfectamente serializado, pero dado que el receptor no cuenta el “.class” de la clase, simplemente no sabrá cómo se debe deserializar el objeto. Lo que normalmente se suele hacer, es distribuir un fichero JAR con todos los elementos necesarios en cada uno de los peers, esto quiere decir que aunque la comunicación entre todos los receptores y emisores en I2P sea descentralizada, tienen que haber elementos de comunicación comunes que les permitan comprender los mensajes que se transmiten por sus túneles, exactamente igual que ocurre con las normas que se definen en cualquier protocolo de red con el fin de garantizar la interoperabilidad en las capas de transporte y aplicación. Además de esto, los receptores y emisores deben conocer los “destinations” de las entidades con las que se desean comunicar. Es posible implementar un mecanismo de descubrimiento automático utilizando un servicio oculto en I2P que sea accesible únicamente por aquellas personas que se desean comunicar y en dicho servicio, cada uno podría depositar el “destination” correspondiente a su instancia de I2P con el fin de que otros usuarios puedan enviarse información.

Para el ejemplo de esta entrada, se creará en primer lugar una clase muy simple que funcionará simplemente como un contenedor de información, también conocido en la terminología de Java como un POJO (Plain Old Java Object) el cual simplemente contendrá algunos atributos básicos y una serie de métodos de establecimiento y acceso (setters y getters)

			
package net.privanon.common; 
public class UserInfo implements java.io.Serializable { 
	private String username; 
	private String name; 
	private String lastname; 
	private Integer age; 
	private String privateMessage;	 
	public void setUsername(String username) { 
		this.username = username; 
	} 
			
	public void setName(String name) { 
		this.name = name; 
	} 
	public void setLastname(String lastname) { 
		this.lastname = lastname; 
	} 
	public void setAge(Integer age) { 
		this.age = age; 
	} 
	public void setPrivateMessage(String privateMessage) { 
		this.privateMessage = privateMessage; 
	} 
	public String getUsername() { 
		return this.username; 
	} 
	public String getName() { 
		return this.name; 
	} 
	public String getLastname() { 
		return this.lastname; 
	} 
			
	public Integer getAge() { 
		return this.age; 
	} 
	public String getPrivateMessage() { 
		return this.privateMessage; 
	} 
} 

La clase en si misma no es demasiado interesante, sin embargo representa la piedra angular del proceso de transmisión de datos entre clientes y receptores, ya que contiene los atributos necesarios para obtener/establecer datos y además, implementa la interfaz Serializable, lo que le permitirá “moverse” libremente entre diferentes JVM.
Modificando un poco la estructura del programa receptor visto en el articulo anterior, el resultado final seria el siguiente.

package testing.i2p; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.InputStreamReader; 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.ObjectOutputStream; 
import java.io.ObjectInputStream; 
import java.net.ConnectException; 
import java.net.SocketTimeoutException; 
import net.i2p.I2PException; 
import net.i2p.client.streaming.I2PSocket; 
import net.i2p.util.I2PThread; 
import net.i2p.client.I2PSession; 
import net.i2p.client.streaming.I2PServerSocket; 
import net.i2p.client.streaming.I2PSocketManager; 
import net.i2p.client.streaming.I2PSocketManagerFactory; 
import net.i2p.client.I2PSessionException; 
import net.privanon.common; 
			
public class Server { 
    public static void main(String[] args) { 
        I2PSocketManager manager =
			I2PSocketManagerFactory.createManager(); 
        I2PServerSocket serverSocket =
			manager.getServerSocket(); 
        I2PSession session = manager.getSession(); 
	System.out.println(session.getMyDestination().toBase64()); 
        I2PThread t = new I2PThread(new
			ClientHandler(serverSocket)); 
        t.setName("clienthandler1"); 
        t.setDaemon(false); 
        t.start(); 
    } 
			
    private static class ClientHandler implements Runnable { 
        public ClientHandler(I2PServerSocket socket) { 
            this.socket = socket; 
        } 
			
        public void run() { 
            while(true) { 
                try { 
                    I2PSocket sock = this.socket.accept(); 
                    if(sock != null) { 
			    ObjectOutputStream oos = new
			ObjectOutputStream(sock.getOutputStream()); 
			    ObjectInputStream ois = new
			ObjectInputStream(sock.getInputStream()); 
				UserInfo info = null; 
			    while ((info = (UserInfo) ois.readObject()) != null) { 
				      if(info != null && info.getUsername() != null
			&& info.getUsername().equals("Adastra")) { 
						UserInfo response = new UserInfo(); 
				   	        response.setName("unknown"); 
					        response.setLastname("unknown"); 
  					        response.setUsername("unknown"); 
					        response.setAge(0); 
					        response.setPrivateMessage("Send the report
			and close the operation");				 
						oos.writeObject(response);		 
 				       } 
			    } 
			    ois.close(); 
			    oos.close(); 
			    sock.close(); 
                    } 
                } catch (I2PException ex) { 
                    System.out.println("General I2P
			exception!"); 
                } catch (ConnectException ex) { 
                    System.out.println("Error
			connecting!"); 
                } catch (SocketTimeoutException ex) { 
                    System.out.println("Timeout!"); 
                } catch (IOException ex) { 
                    System.out.println("General
			read/write-exception!"); 
                } catch (ClassNotFoundException ex) { 
                    System.out.println("Class Not found
			exception!"); 
                } 
            } 
        } 
        private I2PServerSocket socket; 
    } 
} 

Hay que notar que las principales diferencias se pueden ver en el uso de la clase “UserInfo” que se ha creado anteriormente y la serialización/deserialización de dicho objeto utilizando las clases ObjectOutputStream y ObjectInputStream. En este caso, se deserializa el objeto recibido por el emisor, se realiza una verficación muy simple sobre el nombre del usuario y a continuación, se responde al emisor con un objeto del mismo tipo.

Por otro lado, el receptor por su parte puede tener una estructura como la siguiente:

package testing.i2p; 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.InterruptedIOException; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.net.ConnectException; 
import java.net.NoRouteToHostException; 
import net.i2p.I2PException; 
import net.i2p.client.streaming.I2PSocket; 
import net.i2p.client.streaming.I2PSocketManager; 
import net.i2p.client.streaming.I2PSocketManagerFactory; 
import net.i2p.data.DataFormatException; 
import net.i2p.data.Destination; 
import java.io.ObjectOutputStream; 
import java.io.ObjectInputStream; 
import net.privanon.common; 
			
public class Client { 
    public static void main(String[] args) { 
        I2PSocketManager manager =
			I2PSocketManagerFactory.createManager(); 
        System.out.println("Please enter a Destination:");
        BufferedReader br = new BufferedReader(new
			InputStreamReader(System.in)); 
        String destinationString; 
        try { 
            destinationString = br.readLine(); 
        } catch (IOException ex) { 
            System.out.println("Failed to get a
			Destination string."); 
            return; 
        } 
        Destination destination; 
        try { 
            destination = new Destination(destinationString); 
        } catch (DataFormatException ex) { 
            System.out.println("Destination string
			incorrectly formatted."); 
            return; 
        } 
        I2PSocket socket; 
        try { 
            socket = manager.connect(destination); 
        } catch (I2PException ex) { 
            System.out.println("General I2P exception
			occurred!"); 
            return; 
        } catch (ConnectException ex) { 
            System.out.println("Failed to connect!");
            return; 
        } catch (NoRouteToHostException ex) { 
            System.out.println("Couldn't find host!");
            return; 
        } catch (InterruptedIOException ex) { 
            System.out.println("Sending/receiving was
			interrupted!"); 
            return; 
        } 
        try { 
	    ObjectOutputStream oos = new
			ObjectOutputStream(socket.getOutputStream()); 
   	    UserInfo info = new UserInfo(); 
   	    info.setName("Ad"); 
            info.setLastname("Astra"); 
            info.setUsername("Adastra"); 
            info.setAge(30); 
            info.setPrivateMessage("exposure done. Waiting
			for indications"); 
	    oos.writeObject(info); 
	   ObjectInputStream ois = new
			ObjectInputStream(socket.getInputStream()); 
		UserInfo response = null; 
	    while ((response = (UserInfo) ois.readObject()) != null) {
		      System.out.println("Name: "+
			response.getName()); 
		      System.out.println("Last Name: "+
			response.getLastname()); 
		      System.out.println("Username: "+
			response.getUsername()); 
		      System.out.println("Age: "+
			response.getAge()); 
		      System.out.println("Private message: "+
			response.getPrivateMessage()); 
	    } 
	    ois.close(); 
oos.close(); 
	    socket.close(); 
        } catch (IOException ex) { 
            System.out.println("Error occurred while
			sending/receiving!"); 
        }  catch (ClassNotFoundException ex) { 
                    System.out.println("Class Not found
			exception!"); 
                } 
    } 
} 

Nuevamente, las diferencias más destacables entre el programa emisor del articulo anterior y éste, se centran en la serialización/deserializacion de la clase “UserInfo” por medio de los objetos ObjectInputStream y ObjectOutputStream.

Después de iniciar I2P y de ejecutar tanto el emisor como el receptor, se puede ver el flujo de datos transmitidos entre ambas entidades en la siguiente imagen.

streaming1

 

Aunque ambos programas se ejecutan en la misma máquina y sobre la misma instancia de I2P, el funcionamiento será el mismo en instancias y máquinas separadas.

Otro escenario interesante en el que también se puede utilizar la Streaming Library, es en el desarrollo de plugins que se puedan desplegar directamente desde la consola de administración de I2P. Sobre estas cosas hablaré en un próximo articulo.

Saludos y Happy Hack!
Adastra.

Uso de Streaming Library para aplicaciones en I2P

mayo 6, 2015 2 comentarios

Se ha hablado en varias ocasiones sobre los beneficios que aporta I2P al anonimato y en alguna ocasión se ha hablado sobre cómo crear rutinas simples que permitan acceder a I2P utilizando la librería “Streming Library”, la cual se encuentra escrita en Java. Si quieres hacer cualquier tipo de prueba con Python contra I2P, actualmente hay pocas librerías que realmente te lo permitan y que sean estables. Por lo que he podido apreciar en los foros oficiales de desarrolladores, al parecer las personas clave en el desarrollo de plugins, utilidades y el propio core de la red no muestran mucho interés en desarrollar otra librería en un lenguaje distinto para hacer lo que sobradamente ya hace la Streaming Library y francamente tienen toda la razón del mundo, ya que tienen un “roadmap” con cientos de frentes abiertos y es mucho más interesante crear cosas nuevas y mejorar las existentes que reinventar la rueda. Al equipo de I2P le ha costado muchísimo desarrollar la Streaming Library y la cantidad de errores que se reportaban al principio era enorme, es normal que después del número de horas invertidas y el nivel de estabilidad en el que se encuentra ahora, haya sido declarada como la librería de referencia para crear aplicaciones que requieran el uso del protocolo de control de I2P (I2CP) sobre TCP. No obstante, seguimos con los mismos problemas:

1. Aun sigue siendo poca, muy poca la documentación sobre su uso. Si realmente quieres aprender los elementos clave de la librería, tienes que meterte en los JavaDocs y empezar a crear un mapa mental de como están relacionadas las clases y cómo puedes usarlas.

2. Si eres un desarrollador en Python o tienes alguna herramienta para acceder a la web profunda de I2P aunque sea para consultar “Destinations”. Bueno, lo tienes un poco complicado por lo que comentaba antes. Aunque existe el proyecto python-i2cp (https://github.com/majestrate/python-i2cp) para utilizar directamente el protocolo interno de I2P, pero no avanza al ritmo que se esperaría y aun no funciona correctamente a la hora de consultar un destination. Además, utilizar directamente I2CP está desaconsejado por el equipo de I2P. Nos queda utilizar Jython o la JSR de Java correspondiente para ejecutar código de scripting con Python desde la máquina virtual de Java.

Es este artículo intentaré centrarme en el primer punto y explicaré algunas características interesantes en Streaming library para Java y en un próximo articulo, intentaré explicar algunas alternativas a la hora de acceder a I2P desde Python.

No en todos los casos resulta viable utilizar la Streaming Library de I2P, pero por norma general, cuando se habla de aplicaciones punto a punto, como es el caso de descargas de torrents y cosas similares, resulta bastante conveniente y óptimo utilizar esta librería, de hecho, un ejemplo bastante claro lo tenemos con el proyecto I2PSnark, un cliente bittorrent que utiliza la Streaming Library para descargar y compartir torrents utilizando la red de I2P. El código fuente del proyecto se encuentra licenciado con la GNU/GPL y se está disponible en el siguiente repositorio GitHub: https://github.com/i2p/i2p.i2p/tree/master/apps/i2psnark Si se mira con atención las clases y métodos que se incluyen en el proyecto, es mucho más fácil comprender el funcionamiento de la Streaming Library y cómo utilizarla.

En primer lugar, cualquier rutina de código utilizando esta librería puede funcionar en uno de dos modos, o bien como cliente que consulta “destinations” (un destino en I2P es similar a la combinación de una dirección IP y un puerto) o simplemente como servidor. Las principales clases disponibles en la API son “wrappers” de las clases SocketServer y Socket de Java, aunque evidentemente las clases en la Streaming Library adicionan las funcionalidades necesarias para que todas las conexiones se lleven a cabo utilizando la red de I2P.
Por otro lado, en una instancia de I2P, un programa escrito en Java y utilizando la Streaming Library puede actuar como emisor o receptor (recordar que I2P es una red que basada en paquetes y no en circuitos como TOR), con lo cual desde un programa se puede generar el “destination” para que otros usuarios envíen paquetes a la instancia o se pueden buscar (lookup) destinos y enviarles paquetes. El siguiente código sería la clase más simple que se puede crear utilizando la Streaming Library para crear un emisor.

import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.I2PSession;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory; 

public class Server {
	public static void main(String[] args) {
		I2PSocketManager manager = I2PSocketManagerFactory.createManager();
		I2PServerSocket serverSocket = manager.getServerSocket();
		I2PSession session = manager.getSession();
System.out.println(session.getMyDestination().toBase64());
	}
}

Como se puede apreciar, se crea una instancia de la clase “I2PSocketManager” utilizando la factoría “I2PSocketManagerFactory” y posteriormente se crea un objeto “I2PServerSocket”, el cual será utilizado para atender a las peticiones de otros usuarios en la red de I2P. Finalmente, se pinta por pantalla el destination local del proceso recién iniciado. La clase “net.i2p.data.Destination” cuenta con los métodos “toBase64” y “toBase32” que serán utilizados por el cliente para comunicarse con la instancia de I2P.

El código anterior solamente se encarga de obtener una sesión I2P y pintar por pantalla el destination generado, pero una vez hecho esto, el hilo principal del programa termina. Las siguientes instrucciones que se deben añadir, deben permitir que el proceso se quede en estado de escucha para procesar los mensajes que envían los clientes, para ello la clase I2PThread permite crear un hilo de ejecución ininterrumpido que permitirá al emisor actuar como servidor y recibir mensajes.

import net.i2p.client.I2PSession;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.util.I2PThread;
public class Server {
	public static void main(String[] args) {
		I2PSocketManager manager = I2PSocketManagerFactory.createManager();
		I2PServerSocket serverSocket = manager.getServerSocket();
		I2PSession session = manager.getSession();
System.out.println(session.getMyDestination().toBase64());
		I2PThread thread = new I2PThread(new
			ClientHandler(serverSocket));
		thread.setDaemon(false);
		thread.start();
	}
	private static class ClientHandler implements Runnable {
		private I2PServerSocket socket;
		public ClientHandler(I2PServerSocket socket) {
			this.socket = socket;
		}
		public void run() {
			while(true) {
		//Procesar las conexiones de los clientes.
                        }
                }
	}
}

En este caso se crea una nueva clase que procesará los mensajes de los clientes de forma indefinida en un bucle “while true”. En dicho bucle se aceptarán las conexiones de los clientes por I2P y posteriormente, se realizará algún tipo de procesamiento, el cual, típicamente consiste en recibir las conexiones por parte de los clientes y responder a los mensajes.

	while(true) {
		try {
			I2PSocket sock = this.socket.accept();
			if(sock != null) {
				//Receive
				BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
				//Send
				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
				String line = br.readLine();
				if(line != null) {
                                    System.out.println(line);
                                    bw.write(line);
			            bw.flush();
				}
				sock.close();
			}
		} catch (I2PException ex) {
		System.out.println("General I2P exception!");
		} catch (ConnectException ex) {
		System.out.println("Error connecting!");
		} catch (SocketTimeoutException ex) {
                System.out.println("Timeout!");
		} catch (IOException ex) {
                System.out.println("read/write-exception!");
		}
       }

Por otro lado, el cliente debe conocer cuál es la dirección (destination) del emisor para poder transmitirle un mensaje y recibir su respuesta. El código necesario en la parte del cliente es mucho más simple, ya que solamente requiere utilizar la clase I2PSocket y conectarse con el destination especificado.

package testing.i2p;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination; 

public class Client {
	public static void main(String[] args) {
		I2PSocketManager manager =
I2PSocketManagerFactory.createManager();
		System.out.println("Destination:");
		BufferedReader br = new BufferedReader(new
			InputStreamReader(System.in));
		String destinationString;
		try {
			destinationString = br.readLine();
		} catch (IOException ex) {
			System.out.println("Failed to get the Destination.");
			return;
		}
		Destination destination;
		try {
			destination = new Destination(destinationString);
		} catch (DataFormatException ex) {
			System.out.println("Destination string incorrectly formatted.");
			return;
		}
		I2PSocket socket;
		try {
			socket = manager.connect(destination);
		} catch (I2PException ex) {
			System.out.println("General I2P exception occurred!");
			return;
		} catch (ConnectException ex) {
			System.out.println("Failed to connect!");
			return;
		} catch (NoRouteToHostException ex) {
			System.out.println("Couldn't find host!");
			return;
		} catch (InterruptedIOException ex) {
			System.out.println("Sending/receiving was interrupted!");
			return;
		}
		try {
			//Write to server
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			bw.write("Hello I2P!\n");
			BufferedReader br2 = new BufferedReader(new
		InputStreamReader(socket.getInputStream()));
			String s = null;
			while ((s = br2.readLine()) != null) {
				System.out.println("Received from server: " + s);
			}
			socket.close();
		} catch (IOException ex) {
			System.out.println("Error occurred while
			sending/receiving!");
		}
	}
}

El código anterior es la base para crear cosas mucho más elaboradas, por ejemplo, en lugar de utilizar las clases BufferedReader y BufferedWriter se podría utilizar clases como ObjectInputStream y ObjectOutputStream que permiten enviar objetos serializados (aquellos que extienden de la interfaz java.io.Serializable) y de esta forma, construir aplicaciones muy robustas al interior de I2P. Por otro lado, también se puede utilizar para crear plugins que se puedan desplegar directamente desde la consola de administración de I2P. Sobre estas cosas hablaré en un próximo articulo.

Saludos y Happy Hack!
Adastra.

Bridges en TOR y una introducción a los “Pluggable transports”

abril 28, 2015 1 comentario

TOR se caracteriza por ser una red centralizada, en la que cada hora, una serie de servidores de confianza llamados “autoridades de directorio” se encargan de generar información sobre los repetidores que conforman la red y algunos datos adicionales sobre el estado general de la misma. Dicha información es pública y se puede consultar fácilmente ejecutando peticiones HTTP contra cualquiera de las autoridades de directorio o sus espejos. Dado que la información sobre los repetidores la puede consultar cualquiera, una de las principales medidas que toman las entidades represoras a la hora instaurar controles y censurar contenidos, consiste simplemente en incluir dichas direcciones IP en una lista negra para impedir que se puedan realizar conexiones contra cualquier repetidor de TOR. Es una medida que se utiliza muchísimo y que según algunos artículos publicados en el blog de TOR (https://blog.torproject.org/) es una de las medidas más utilizadas en países como Cuba, China, Etiopía, Corea del Norte, etc. Con el fin de hacer que la red sea resistente a este tipo de censura, el equipo de TOR ha desarrollado un sistema para que los ciudadanos de países como los anteriores puedan seguir utilizando TOR sin problemas, aunque las direcciones IP de los repetidores incluidos en los consensos o incluso las direcciones IP de las autoridades de directorio se encuentren bloqueadas. Dicho sistema es conocido como “Automatic Bridging” y es un mecanismo en el que se busca eludir la censura por parte de adversarios fuertes, como es el caso del gobierno de un país. Para conseguir esto, las autoridades de directorio utilizan unos repetidores especiales llamados “Bridges” o puentes, los cuales funcionan exactamente igual que cualquier repetidor que hace parte de un circuito en TOR, pero con la diferencia de que no se exponen públicamente en los descriptores emitidos cada hora por las autoridades de TOR. Los bridges pueden ser creados por cualquier usuario de TOR y si estás a favor de la libertad de expresión y te asquea ver como en ciertos países la gente no puede expresar libremente sus ideas sin temor a que sus vidas o las de sus familiares corran peligro, te recomiendo que configures tus instancias de TOR para que también funcionen como puentes y sean utilizadas por aquellas personas que desean reportar los abusos que se comenten en ciertos lugares del mundo.
Para aquellos que desean obtener un listado de bridges de TOR, dado que no se pueden conectar directamente con las autoridades de directorio o con los repetidores que conforman la red, existen dos formas:

1. Consultar los puentes en “BridgeDB”, el proyecto oficial de TOR para acceder a un conjunto reducido de puentes que servirán para eludir la censura. Dicho proyecto se encuentra ubicado en el siguiente enlace: https://bridges.torproject.org. Para obtener los bridges basta con pinchar sobre el botón en el que pone “Get Bridges” u “Obtener puentes” y después de ingresar un captcha, se enseñarán dos puentes que deben ser configurados en la instancia de TOR que no consigue llegar a las autoridades de directorio o a los repetidores de la red.

2. En el caso (bastante frecuente) de que el proyecto “BridgeDB” también se encuentre censurado, la otra alternativa para recibir un par de puentes validos es escribir un correo a la dirección “bridges@torproject.org”. El mensaje no tiene que tener un contenido, es simplemente una dirección de correo que responde de forma automática al remitente con lo que ha solicitado. En el asunto del mensaje se debe especificar un “comando” para obtener información sobre BridgeDB. Si se envía un mensaje a dicha dirección, sin asunto, la respuesta automática contendrá los posibles comandos que puede enviar el comando a la plataforma de BridgeDB.
El contenido del mensaje devuelto, en el caso de no incluir un asunto es el siguiente:


Hey, debiadastra! Welcome to BridgeDB!

COMMANDs: (combine COMMANDs to specify multiple options simultaneously)
get bridges Request vanilla bridges.
get transport [TYPE] Request a Pluggable Transport by TYPE.
get help Displays this message.
get key Get a copy of BridgeDB’s public GnuPG key.
get ipv6 Request IPv6 bridges.

Currently supported transport TYPEs:
obfs2
obfs3
obfs4
scramblesuit
fte

BridgeDB can provide bridges with several types of Pluggable Transports[0],
which can help obfuscate your connections to the Tor Network, making it more
difficult for anyone watching your internet traffic to determine that you are
using Tor.

Some bridges with IPv6 addresses are also available, though some Pluggable
Transports aren’t IPv6 compatible.

Additionally, BridgeDB has plenty of plain-ol’-vanilla bridges – without any
Pluggable Transports – which maybe doesn’t sound as cool, but they can still
help to circumvent internet censorship in many cases.

[0]: https://www.torproject.org/

<3 BridgeDB

En el caso de indicar el asunto “get bridges”, lo que se puede ver es lo siguiente:

“Hey, debiadastra!
[This is an automated message; please do not reply.]
Here are your bridges:

83.212.111.114:443 0A6EF34EDF047BFD51319268CD423E
194.132.208.140:1418 E6F48300BB17180451522069F16BD5
192.36.31.74:22656 FEB63CA5EBD805C42DC0E5FBDDE82F

To enter bridges into Tor Browser, first go to the  Tor Browser download
page [0] and then follow the instructions there for downloading and starting
Tor Browser.

When the ‘Tor Network Settings’ dialogue pops up, click ‘Configure’ and follow
the wizard until it asks:

> Does your Internet Service Provider (ISP) block or otherwise censor connections
> to the Tor network?

Select ‘Yes’ and then click ‘Next’. To configure your new bridges, copy and
paste the bridge lines into the text input box. Finally, click ‘Connect’, and
you should be good to go! If you experience trouble, try clicking the ‘Help’
button in the ‘Tor Network Settings’ wizard for further assistance.

[0]: https://www.torproject.org/

Como se puede ver, ha devuelto tres repetidores con la dirección IP, puerto y fingerprint del puente. Ahora, para que una instancia de TOR pueda utilizar dichos puentes, basta con especificar las siguientes líneas de configuración en el fichero “torrc”.

Bridge 83.212.111.114:443
Bridge 194.132.208.140:1418
Bridge 192.36.31.74:22656
UseBridges 1

Si estas interesado en crear tu instancia de TOR para que funcione como puente, el procedimiento es bastante sencillo, sin embargo, no se puede configurar una instancia de TOR que funcione como repetidor y puente al mismo tiempo, lo cual es lógico, ya que los repetidores son públicos y los puentes privados y establecer una instancia que actúe como repetidor y puente es equivalente a crear un puente de acceso público y fácil de censurar, lo cual evidentemente no tiene ningún sentido.

Es necesario incluir las siguientes líneas de configuración en el fichero “torrc”:

SocksPort 0

ORPort 8080

Exitpolicy reject *:*

DataDirectory /home/adastra/workspace/bridge/

BridgeRelay 1

Como se puede ver, tanto configurar como utilizar un puente es una tarea bastante simple y es una solución que se ajusta bastante bien al problema de la censura. Sin embargo, algunos “rivales fuertes”, tales como los gobiernos de China o Corea del Norte, ahora ya no solamente bloquean las direcciones IP que se encuentren relacionadas con la red de TOR, ahora aplican técnicas de análisis de paquetes que detectan si los paquetes intercambiados utilizan el protocolo de TOR. Ante una medida así, los puentes por si solos pierden efectividad y se hace muy difícil ocultar el trafico. Aquí entra en juego lo que se conoce como “Pluggable Transports”.

Introducción a los Pluggable Transports

Las técnicas DIP (Deep Packet Inspection) se han vuelto cada vez más comunes en aquellos países en los que el nivel de censura es alto. Las rutinas DIP se encargan de analizar un conjunto de paquetes y reensamblarlos para clasificarlos partiendo de patrones conocidos. De esta forma, con DIP es posible determinar que un conjunto de paquetes se encuentran transmitiendo datos en la red de TOR aunque la dirección IP no se encuentre bloqueada.

Ahora bien, la especificación de “Pluggable Transports” define a esta tecnología como la capacidad de convertir flujos de trafico de TOR entre el cliente y un puente, en flujos admitidos y no reconocidos por técnicas de DIP, como por ejemplo, una conversación inocente con cualquier servidor web en Internet. Notar que aunque el rival (censor), pueda monitorizar el trafico y analizar los paquetes en profundidad, no verá ningún patrón conocido que le permita determinar con exactitud que se trata de un paquete que viaja por TOR.

El objetivo de los PT (Pluggable Transports) consiste básicamente en ofuscar el trafico entre el cliente y sus puentes. Para ello, se utiliza un componente de software adicional tanto en el cliente como en la instancia de TOR que funciona como puente. Dichos componentes deben conocer una serie de reglas para poder ofuscar el trafico (cliente) y posteriormente, poder desofuscarlo (servidor). Actualmente existen varias herramientas y frameworks desarrollados siguiendo la especificación de PT ubicada en el siguiente enlace https://gitweb.torproject.org/torspec.git/tree/pt-spec.txt y seguramente la más conocida y popular es OBFSPROXY, un framework implementado en Python del que os hablaré en un próximo articulo.

Un saludo y Happy Hack!
Adastra.

Seguir

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

Únete a otros 1.582 seguidores

A %d blogueros les gusta esto: