Inspección de tráfico con tcpdump y tcpflow Sat, 08 Nov 2008

Antes de seguir con el segundo post sobre ossec, voy a dar un par de pistas sobre cómo ver el tráfico que pasa por una sesión tcp. Esto sí que es todo un mundo, así que me limito, como casi siempre, a dar cuatro detalles para que quien quiera se haga una idea de lo que se puede hacer y siga investigando.

Por supuesto, el que se pueda "espiar" lo que se está trasmitiendo no significa que debamos (ni podamos) hacerlo, al menos si no queremos tener problemas legales.

Vamos a empezar por lo básico. Necesitamos capturar tráfico para poderlo analizar después con cierta tranquilidad. Para esto usamos el conocido tcpdump, aunque podemos usar otros, como por ejemplo, snort.

  tcpdump -n -i eth1 -s 1515 -U -w /tmp/captura.pcap '(tcp port 20) or (tcp port 21) or (tcp port 25)'
  tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 1515 bytes

Para saber lo que hacen los parámetros nada mejor que el manual :-)

Dejamos esta terminal abierta y con el comando en ejecución. Vamos a ir analizando lo que se vuelca en captura.pcap en otra terminal.

Primera prueba.

Desde otra máquina vamos a hacer un telnet al puerto 25 y a mandar un correo.

  telnet 192.168.10.1 25
  Trying 192.168.10.1...
  Connected to 192.168.10.1.
  Escape character is '^]'.
  220 smtp.example.com ESMTP Postfix
  helo prueba.example.com
  250 smtp.example.com
  rset
  250 2.0.0 Ok
  helo prueba.example.com
  250 smtp.example.com
  mail from: prueba@example.com
  250 2.1.0 Ok
  rcpt to: prueba1@example.com
  250 2.1.5 Ok
  data
  354 End data with .
  Subject: Titulo del correo
  Este texto se ve en la captura
  .
  250 2.0.0 Ok: queued as 1F7426C420
  quit
  221 2.0.0 Bye
  Connection closed by foreign host.

Nuestro volcado tiene datos.... vamos a ver que tiene usando tcpflow.

  # tcpflow -r captura.pcap -c port 25
  192.168.010.001.00025-192.168.010.002.41403: 220 smtp.example.com ESMTP Postfix
  192.168.010.002.41403-192.168.010.001.00025: helo prueba.example.com
  192.168.010.001.00025-192.168.010.002.41403: 250 smtp.example.com
  192.168.010.002.41403-192.168.010.001.00025: rset
  192.168.010.001.00025-192.168.010.002.41403: 250 2.0.0 Ok
  192.168.010.002.41403-192.168.010.001.00025: helo prueba.example.com
  192.168.010.001.00025-192.168.010.002.41403: 250 smtp.example.com
  192.168.010.002.41403-192.168.010.001.00025: mail from: prueba@example.com
  192.168.010.001.00025-192.168.010.002.41403: 250 2.1.0 Ok
  192.168.010.002.41403-192.168.010.001.00025: rcpt to: prueba1@example.com
  192.168.010.001.00025-192.168.010.002.41403: 250 2.1.5 Ok
  192.168.010.002.41403-192.168.010.001.00025: data
  192.168.010.001.00025-192.168.010.002.41403: 354 End data with .
  192.168.010.002.41403-192.168.010.001.00025: Subject: Titulo del correo
  192.168.010.002.41403-192.168.010.001.00025: Este texto se ve en la captura
  192.168.010.002.41403-192.168.010.001.00025: .
  192.168.010.001.00025-192.168.010.002.41403: 250 2.0.0 Ok: queued as 1F7426C420
  192.168.010.002.41403-192.168.010.001.00025: quit
  192.168.010.001.00025-192.168.010.002.41403: 221 2.0.0 Bye

Sorpresa, tcpflow ha generado, en esta caso por salida estándar (-c), todo lo que ha sido capturado en el puerto 25.

Segunda prueba.

Bien, vamos con algo un poco diferente, pero igual de fácil (recordad que esto no son más que ideas)

Ahora vamos a suponer que he programado un rootkit que se llama exploit, y que lo voy a subir por ftp a la máquina que estamos monitorizando.

  ftp 192.168.10.1
  Connected to 192.168.10.1.
  220 Este es un servidor privado. Por favor cierre la sesion inmediatamente.
  Name (192.168.10.1:prueba):
  331 Please specify the password.
  Password:
  230 Login successful.
  Remote system type is UNIX.
  Using binary mode to transfer files.
  ftp> put exploit
  local: exploit remote: exploit
  200 PORT command successful. Consider using PASV.
  150 Ok to send data.
  226 File receive OK.
  101992 bytes sent in 0.00 secs (29433.1 kB/s)
  ftp> quit
  221 Goodbye.

Muy bien, ahora veamos lo que tenemos, empezando por el puerto 21, y después por el 20.

  # tcpflow -r captura.pcap -c port 21
  192.168.010.001.00021-192.168.010.002.50427: 220 Este es un servidor privado. Por favor cierre la sesion inmediatamente.
  192.168.010.002.50427-192.168.010.001.00021: USER prueba
  192.168.010.001.00021-192.168.010.002.50427: 331 Please specify the password.
  192.168.010.002.50427-192.168.010.001.00021: PASS secreto
  192.168.010.001.00021-192.168.010.002.50427: 230 Login successful.
  192.168.010.002.50427-192.168.010.001.00021: SYST
  192.168.010.001.00021-192.168.010.002.50427: 215 UNIX Type: L8
  192.168.010.002.50427-192.168.010.001.00021: TYPE I
  192.168.010.001.00021-192.168.010.002.50427: 200 Switching to Binary mode.
  192.168.010.002.50427-192.168.010.001.00021: PORT 192,168,10,2,205,32
  192.168.010.001.00021-192.168.010.002.50427: 200 PORT command successful. Consider using PASV.
  192.168.010.002.50427-192.168.010.001.00021: STOR exploit
  192.168.010.001.00021-192.168.010.002.50427: 150 Ok to send data.
  192.168.010.001.00021-192.168.010.002.50427: 226 File receive OK.
  192.168.010.002.50427-192.168.010.001.00021: QUIT
  192.168.010.001.00021-192.168.010.002.50427: 221 Goodbye.

Vamos a hacer ahora que tcpflow genere un fichero con el tráfico del puerto 20. Para esto quitamos el parámetro -c.

  # tcpflow -r captura.pcap  port 20
  # file 192.168.010.002.52512-192.168.010.001.00020
  192.168.010.002.52512-192.168.010.001.00020: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, stripped

Sorpresa, tenemos un fichero binario ..... con el exploit. Bueno, en realidad en una copia de /bin/ls, pero vale para el ejemplo

  # strings 192.168.010.002.52512-192.168.010.001.00020
  .......
  Usage: %s [OPTION]... [FILE]...
  List information about the FILEs (the current directory by default).
  Sort entries alphabetically if none of -cftuvSUX nor --sort.
  Mandatory arguments to long options are mandatory for short options too.
    -a, --all                  do not ignore entries starting with .
    -A, --almost-all           do not list implied . and ..
        --author               with -l, print the author of each file
    -b, --escape               print octal escapes for nongraphic characters
        --block-size=SIZE      use SIZE-byte blocks
  .......

¿Qué pasa en la realidad, cuando tenemos cientos o miles de sesiones de correo o ftp y queremos ver una concreta? Por un lado debemos guardar el tráfico que queremos investigar, claro, pero luego debemos saber qué sesiones se han establecido, a qué hora, cuánto tráfico ha pasado por ellas, entre que puertos, .... Para esto hay mucho software, pero un buen ejemplo es argus. A partir de aquí, podemos generar expresiones más elaboradas para usar en tcpflow (algo más que "port 20")