Ncat

De castillowiki
Saltar a: navegación, buscar

Se trata de una herramienta de propósito general para leer, escribir, redirigir o cifrar datos a través de una red. Puede:

  • Actuar como un simple cliente TCP/UPD/SCTP/SSL para interactuar con servidores de todo tipo a través de una red. Sirve para detectar problemas o analizar profundamente su funcionamiento. Permite ver el resultado sin filtros y tal cual es enviado.
  • Actuar como un simple servidor en la red TCP/IP. Sirve para entender las peticiones que pueden hacer los clientes.
  • Redirigir o hacer de proxy entre puertos. Puede ser una simple redirección a algún destino prefijado o actuar como un proxy SOCKS o HTTP donde el cliente especifica su destino.
  • Encriptar mediante SSL.
  • Actuar como puerta de enlace de comandos del sistema. Algo similar al cat, pero para la red.
  • Actuar como "connection broker" y actuar como un simple chat.
ncat es una implementación del netcat tradicional, la mayoría de sus funciones se pueden hacer también con nc [1]

Uso básico

Ncat puede operar en modo connect o listen.

  • En modo connect, ncat inicia una conexión o envia datos UTP a un servicio que está escuchando.
  • En modo listen, espera a una conexión.

Para usarlo en modo connect se hace:

$ ncat <host> [<puerto>]

El modo listen es igual, pero con -l

$ ncat -l [<host>] [<puerto>]

En modo listen, <host> indica la IP de la que escucha, es opcional. Su puerto por defecto, si no se especifica es el 31337. Normalmente, los usuarios no pueden abrir un puerto por debajo del 1024. Un puerto TCP normalmente acepta sólo una conexión y termina cuando el cliente desconecta. Si se da la opción --keep-open (-k), ncat acepta múltiples conexiones. Cuando envía algo, lo envía por igual a todos los clientes. Por defecto, ncat actúa con IPv4 y TCP a menos que se especifique -u para udp o -6 para IPv6.

Ejemplo de modo Connect

$ ncat -C scanme.nmap.org 80
GET / HTTP/1.0
HTTP/1.1 200 OK
Date: Thu, 05 Feb 2009 15:31:40 GMT
Server: Apache/2.2.2 (Fedora)
Last-Modified: Mon, 19 May 2008 04:49:49 GMT
ETag: "fc8c91-2e3-44d8e17edd540"
....

Hemos hecho la conexión y luego el GET / HTTP/1.0 para que nos devuelva algo. El -C es para que interprete el fin de línea como CRLF

La respuesta comienza con HTTP/1.1 200 OK, el protocolo, versión, código 200 y OK que significa que todo ha ido bien. A continuación, la cabecera HTTP y el HTML de la web.

Ejemplo de modo Listen

Vamos a simular un servidor HTTP. Creamos un fichero hello.httpd con este contenido:

 HTTP/1.0 200 OK

 <html>
   <body>
     <h1>Hello, world!</h1>
   </body>
 </html>
 

Ahora ejecutamos el comando:

$ ncat -l localhost 8080 < hello.http

Tan pronto como reciba una petición, ncat volcará el contenido del fichero hello.http. Se puede probar con un navegador web. El navegador puede que espere a que se cierre la conexión.

Esto tiene un problema. El problema es que el navegador no sabe el tamaño del documento y no cierra la conexión. Además, como es pequeño, no muestra nada a la espera de más contenido. Si informamos al navegador del tamaño, este cerrará en cuanto lo tenga todo.

{ echo -ne "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c <hello.html)\r\n\r\n"; cat hello.html; } | nc -l 8080

Como se puede observar, se indica la cabecera del protocolo HTTP junto con el tamaño exacto del html (wc -c)

ncat y SSL

Se pueden enviar los datos encriptados mediante la opción --ssl. Por ejemplo, para conectarse a un servidor HTTPS:

ncat -C --ssl <servidor> 443

También puede ser servidor con ssl

$ ncat -v -l --ssl

El -v sirve para ver más detalles de la conexión, como la clave que se va a usar. Com --ssl-cert y --ssl-key se puede usar una clave existente o verificada.

Ejecución de comandos

Ncat puede ejecutar comandos después de establecer la conexión. La entrada y salida estándar se redirigen a la conexión. Cualquier cosa recibida por la conexión se considerará como el stdin y cualquier cosa que salga por stdout se irá a parar a la conexión. Para ello se puede usar la opción -e o --exec.

$ ncat -l --exec "/bin/echo Hello"

Es necesario poner la ruta absoluta del comando, ya que --exec no lo busca en el PATH. Con --sh-exec sí busca en el PATH. Por ejemplo, para que muestre el directorio donde se ha ejecutado:

$ ncat -l --sh-exec 'pwd'

La opción -e se puede usar en modo connect y en modo listen.

Ejemplo. Crear el siguiente script:

#!/bin/bash
echo "Hola, dime tu nombre"
read nombre
echo "Hola: $nombre"

Ejecutar:

$ ncat -l --sh-exec './hola.sh'

En otra terminal:

$ ncat localhost 31337

Opciones de salida

Ncat lee de la entrada estándar y escribe en la estándar, menos cuando tiene la opción --exec que lo hace del comando o script que se ejecuta. Con -v se pueden ver detalles de la conexión, porque por defecto, ncat no muestra nada por la salida excepto errores.

Podemos volcar toda la comunicación con la opción -o a un fichero. La opción --hex-dump o -x lo guarda en hexadecimal, por si resulta más útil.


Control de acceso

Se puede establecer unas reglas de control de acceso para permitir o denegar el acceso a unas determinadas direcciones. Con --allow se permite a unas en concreto y se deniega a todas las demás. Con --deny se deniega a una y se permite a todas las demás. Se pueden poner direcciones de red o, incluso u fichero con una lista de hosts permitidos o denegados con --allowfile o --denyfile.

ncat -l --allow 192.168.0.125
ncat -l --allow 2001:db8::7d
ncat -l --allow trusted.example.com
ncat -l --allow 192.168.0.0/24
ncat -l --allow 192.168.0.0-255
ncat -l --allow 2001:db8::/32
ncat -l --allowfile trusted-hosts.txt
ncat -l --denyfile external-hosts.txt

Se puede establecer un límite de conexiones. El límite por defecto son 100, pero con --max-conns se puede modificar.


Haciendo de proxy

Ncat puede redireccionar sus conexiones como un proxy con --proxy

Transferencia de archivos

Aunque existen otros protocolos más adecuados como FTP, SSH, HTTP... para la transferencia de archivos, es posible que se pueda necesitar transmitir un archivo en "crudo" (raw) por una tubería de la red. Ncat puede proporcionar mucha flexibilidad.

   host2$ ncat -l > outputfile
   host1$ ncat --send-only host2 < inputfile
   host1$ ncat -l --send-only < inputfile
   host2$ ncat host1 > outputfile

El --send-only se pone para que cierre la conexión una vez ha terminado de transmitir.

Una elegante manera de transmitir varios ficheros comprimidos:

host2$ ncat -l | tar xzv
host1$ tar czv <ficheros> | ncat --send-only host2

Se puede crear un intermediario con --broker para, por ejemplo, evitar problemas con el NAT .

   host3$ ncat -l --broker
   host2$ ncat host3 > outputfile
   host1$ ncat --send-only host3 < inputfile

Usar Ncat para clonar un disco duro

Arrancar con un Live CD y averiguar qué partición queremos clonar, en el ejemplo es la sda1

En el destino:

$ nc -l -p 5000 | gunzip | dd of=/dev/sda1

En el origen:

$ dd if=/dev/sda1 | gzip -1 | nc <ip> 5000

Se puede incrementar la compresión, pero puede que la ralentice más que la velocidad de la red. Se puede ir probando.

Un Chat básico

La manera más simple de crear un chat con ncat:

host1$ ncat -l
host2$ ncat host1

Si queremos tener más clientes podemos poner --keep-open en el que hace de servidor. El problema es que el host 3 no verá los mensajes del host2

host1$ ncat -l --keep-open
host2$ ncat host1
host3$ ncat host1

Esto se puede solucionar poniendo --broker y todos pueden escuchar lo de todos. Para facilitar aun más, ncat tiene la opción --chat en la que se puede ver el usuario que hace cada comentario.

Este comando crea un chat básico para cinco clientes con encriptación ssl.

Servidor~$ ncat -vlm 5 --ssl --chat 9876
Cliente~$ ncat --ssl localhost 9876

Emular servicios

Servicio de eco

$ ncat -l 7 --keep-open --exec "/bin/cat"

Servicio de fecha

$ ncat -l 13 --keep-open --send-only --exec "/bin/date"

Servicio de terminal remoto

$ ncat -l -p 5000 -e /bin/bash

Esto puede ser bastante peligroso, ya que da acceso a un terminal del usuario que lo invoca. Imagina que lo invoca root.


Examinar una conexión TPC

En una terminal abriremos un servidor:

$ ncat -l -p 2048

En otra terminal abrimos el tcpdump:

$ sudo tcpdump -nn -x -i lo port 2048

Con -nn no traduce IP ni puerto, por lo que no genera tráfico con el DNS. Con -x muestra la salida en hexadecimal y con -i especificamos la interfaz, en este caso localhost.

En otra el cliente:

$ ncat localhost 2048


Este es el resultado de tcpdump:

10:22:36.849158 IP localhost.49214 > localhost.2048: Flags [S], seq 3363873998, win 32792, options [mss 16396,sackOK,TS val 372197 ecr 0,nop,wscale 5], length 0
	0x0000:  4500 003c 092b 4000 4006 338f 7f00 0001
	0x0010:  7f00 0001 c03e 0800 c880 a4ce 0000 0000
	0x0020:  a002 8018 fe30 0000 0204 400c 0402 080a
	0x0030:  0005 ade5 0000 0000 0103 0305
10:22:36.849179 IP localhost.2048 > localhost.49214: Flags [S.], seq 2086942391, ack 3363873999, win 32768, options [mss 16396,sackOK,TS val 372197 ecr 372197,nop,wscale 5], length 0
	0x0000:  4500 003c 0000 4000 4006 3cba 7f00 0001
	0x0010:  7f00 0001 0800 c03e 7c64 36b7 c880 a4cf
	0x0020:  a012 8000 fe30 0000 0204 400c 0402 080a
	0x0030:  0005 ade5 0005 ade5 0103 0305
10:22:36.849192 IP localhost.49214 > localhost.2048: Flags [.], ack 1, win 1025, options [nop,nop,TS val 372197 ecr 372197], length 0
	0x0000:  4500 0034 092c 4000 4006 3396 7f00 0001
	0x0010:  7f00 0001 c03e 0800 c880 a4cf 7c64 36b8
	0x0020:  8010 0401 fe28 0000 0101 080a 0005 ade5
	0x0030:  0005 ade5

Hay que tener en cuenta que las primeras 5 palabras de 32 bits son de la cabecera IP, a partir de la 6 comienza con el puerto de origen de la cabecera TCP.

300px-Tcp-handshake.png

Si aislamos y guardamos el resultado de uno de los paquetes, podemos luego ver los bits. En el siguiente comando, hemos aislado el primer paquete en el fichero connect:

$ for i in $(cat tcp.tcp | sed 's/^\t0x00..:  //g' | tr 'a-f' 'A-F'); do echo "obase=2; ibase=16; F$i" | bc | cut -c5-; done | tr -d "\n" | fold -32 |sed "s/\([01]\{8\}\)/\1 /g" | sed -n '6,15p' | cat -n

Este script sólo coge las líneas de la 6 a la 15. Las anteriores corresponden al protocolo IP de la capa de red.

Este script lo hace todo automáticamente:

#!/bin/bash

xterm -T "Servidor" -e ncat -l 2048 &
xterm -T "Tcpdump" -e 'echo "Cerrar esta terminal primero!"; tcpdump -nn -x -i lo port 2048 &> paquetes.txt' &
sleep 2
xterm -T "Client" -e ncat localhost 2048
for j in {0..2}
do
       echo "Paquete $j"
       cat paquetes.txt | sed -n '/0x0000/,/0x0030/ p' | sed -n "$((j*4+1)),$((j*4+4))p" | head -4 > tcp.tcp
       for i in $(cat tcp.tcp | sed 's/^\t0x00..:  //g' | tr 'a-f' 'A-F') 
       do 
            echo "obase=2; ibase=16; F$i" | bc | cut -c5-
       done | tr -d "\n" | fold -32 |sed "s/\([01]\{8\}\)/\1 /g" | sed -n '6,15p' | cat -n
       echo 
done

Ver las diferencias entre GET y POST gracias ncat

Si hacemos un documento con este contenido:

HTTP/1.1 200 OK

<html>
  <body>
   <form name="input" action="html_form_action.php" method="post">
     Username: <input type="text" name="user">
     <input type="submit" value="Submit">
   </form>
  </body>
</html>

Y ponemos el ncat a la escucha:

$ ncat -l -k 8080 < form.http 

En un navegador web podremos ver un formulario si ponemos http://localhost:8080. (Es posible que tengamos que cerrar la conexión con control-C antes de ver el formulario)

Si lo hemos cerrado, lo ponemos de nuevo a la escucha, ya no es necesario redirigir el fichero:

$ ncat -l -k 8080

Entonces se envía el formulario y se puede examinar el resultado. Se verá que dentro del mensaje está el contenido del input. Si se cambia el method post del formulario por GET se verá que los datos están en la URL y no dentro del mensaje.

Simple servidor web

Averiguar los puertos que están escuchando y aceptan conexiones

for i in $(sudo lsof -Pni4 | grep 'LISTEN' | cut -d":" -f2 | cut -d" " -f1); do nc -zv $(hostname) $i; done
Esto está hecho con el comando nc

Sin usar ncat:

: </dev/tcp/127.0.0.1/80

Da un fallo si el puerto está cerrado. /dev/tcp es un dispositivo especial que és creado cuando se le invoca en el que establece una conexión tcp con la IP y el puerto deseado. Es una alternativa simple a ncat. No obstante es de más bajo nivel y no tiene todas las opciones.

ncat como servidor de contraseñas

$ while [ 1 ]; do cat /dev/urandom | tr -dc ' -~' | head -c 10 | ncat -l 8080 &> /dev/null; test $? -gt 128 && break; done [2]


Usando ncat para hacer scripts cliente-servidor

Por un lado, creamos un fichero en /tmp al cual se redirige la salida de un ncat -l:

$ ncat -l 8080 > /tmp/aux

Por otro lado, dejamos escuchando ese fichero con tail -f

$ tail -f /tmp/aux | while read line; do echo $line; done

Está claro que esto no hace nada, pero dentro del while se puede poner el tratamiento que haga el servidor de las peticiones que se le pidan.

Para hacerlo mejor, podemos usar un fichero fifo:

$ fifo="/tmp/`date +%s`"
$ mkfifo $fifo
$ exec 8<> $fifo
$ ncat -l 8080 > $fifo 
$ while read c <&8; do echo $c; done

Netcat es muy efectivo para ponerlo a escuchar o para conectarse de manera interactiva a un puerto. Pero si se trata de automatizar el envío o la escucha en un puerto, es necesario herramientas como la anterior o la siguiente:

#Terminal 1
$ ncat -l 8080 > $fifo
#Terminal 2
$ exec 5<>/dev/tcp/127.0.0.1/8080
#Terminal 3
$ exec 8<> $fifo
$ while read c <&8; do echo $c; done
#Terminal 2
echo "Hola Mundo" >&5

En el ejemplo anterior, usamos 3 terminales para darle realismo a la red simulada. En la primera ponemos símplemente a escuchar a ncat y enviar los datos al archivo $fifo que préviamente se debería haber declarado. En la segunda terminal es donde está la novedad. Puesto que ncat, si actua como cliente, envía los ficheros de una y corta la comunicación, hay que recurrir a un mecanismo más primitivo para enviar paquetes a una IP. El exec en /dev/tcp, crea un fichero especial que representa una conexión TCP a la IP y el puerto especificados en los subdirectorios. Linux ya se encarga de establecer la comunicación. Otro Ejemplo

Enlaces