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.
1 2 3 4 5 6 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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.
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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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):
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.
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!
Fuente http://thehackerway.com/2014/12/04/3243/