domingo, 6 de marzo de 2011

Análisis de protocolos en TCP/IP (nivel aplicación)

El propósito de este artículo es aclarar unas ideas básicas sobre la manera de obtener información acerca del funcionamiento de un protocolo determinado en el nivel de aplicación. Para la mayoría de los protocolos standard que están en funcionamiento es obligada una lectura previa de los RFCs (requests for comments) que le correspondan, ya que en ellos se definen las bases y especificaciones de este. Dicho método no siempre será posible, ya que hay protocolos cerrados y a veces la única manera de saber algo más es mediante ingeniería inversa.

Además de la documentación que podamos encontrar, nos valdremos de la ayuda de un sniffer. Los sniffers son programas de análisis de la red, permiten capturar la información que pasa a través de un interface de red. En nuestro caso, hemos escogido el ethereal, ya que está disponible en varias plataformas y además tiene una GUI que facilita mucho el análisis de los datos.




















Conceptos preliminares.

Para poder establecer comunicaciones en una red, se requieren una serie de procesos que transforman los datos y los envían entre un remitente a un destinatario. Así mismo, son necesarias ó deseables una serie de características que permitan controlar factores como establecimiento de conexiones, sincronización, corrección de errores, etc... para todo esto, lo más práctico es separar estas tareas en capas o niveles, de manera que en cada capa se realiza una función. El modelo standard OSI define las siguientes capas:

  • Aplicación.  
  • Presentación.  
  • Sesión.  
  • Transporte.  
  • Red.  
  • Enlace.  
  • Física.
TCP/IP asume la capa física en la de enlace, la de sesión la incluye en la de transporte y la de presentación se realiza a nivel aplicación. De esta manera, engloba todo el proceso en 4 niveles: aplicación, transporte, red y enlace.

En cada nivel podemos encontrar a su vez varios protocolos:

  • Aplicación: telnet, ftp, dns, http, irc...  
  • Transporte: TCP, UDP.  
  • Red: IP, ICMP, IGMP.  
  • Enlace: ARP, RARP.
Nuestro propósito, es analizar los protocolos que residen en la capa de aplicación. Para ello, sería recomendable tener unos conceptos previos sobre las restantes capas, el establecimiento de conexiones, las direcciones IP / MAC y alguna que otra cosa. Se pueden obtener muy buenas referencias sobre esto en el primer volumen de el libro TCP/IP Illustrated.
























Primer contacto con el sniffer.

Al cargar el ethereal, lo primero con lo que nos encontramos es una ventana similar a la siguiente:

En dicha ventana, podemos distinguir claramente las siguientes partes (de arriba hacia abajo):

  • Barra de menús - desde ella, podemos acceder a todas las opciones
    del programa.

    • FILE: operaciones genéricas (cargar, grabar, imprimir, salir).
    • EDIT: localización de datos, filtros, y configuración del
      programa.
    • CAPTURE: inicia o detiene una captura.
    • DISPLAY: visualización de los datos.
    • TOOLS: procesado de los datos.
    • HELP: diálogos de ayuda e información general.
  • Ventana superior - será nuestra área principal de trabajo, ya que
    es donde se muestran de una manera clara los paquetes. Además cuenta con una
    serie de pestañas en la parte de arriba:
    • Número: orden numérico de los paquetes.
    • Tiempo: tiempo transcurrido.
    • Origen: quién es el remitente del paquete.
    • Destino: a quién va dirigido el paquete.
    • Protocolo: protocolo del paquete.
    • Información: muestra información adicional.

      NOTA:
      En cualquier momento, podemos pulsar cualquiera de estas pestañas para poder
      ordenar los paquetes con un determinado criterio.
  • Ventana central - muestra un esquema en arbol con información del
    paquete. Podemos desglosarla en tramas, datagramas y segmentos pulsando los
    [+] correspondientes.
  • Ventana inferior - muestra el volcado real del paquete
    seleccionado. Si pulsamos alguna parte del arbol en la ventana anterior
    (central) podremos ver marcada en esta, la sección correspondiente a la rama
    del arbol seleccionada..
  • Barra de status - Permite filtrar segun un criterio, mediante el
    boton RESET se puede restaurar la captura inicial completa sin ningun
    tipo de filtro.
NOTA: Es posible que alguna o varias de las ventanas anteriores (superior, central e inferior) no coincidan con la descripción anterior, ya que pueden reducirse en tamaño hasta llegar a ocultarse.



















Comenzando a capturar.

Para comenzar una nueva sesión lo único que debemos hacer es seleccionar en la pestaña de CAPTURE (en la barra de menús) la opción de START. También podríamos haber usado el atajo de teclado: CRTL+K. Acto seguido, nos aparecerá una ventana en la que seleccionaremos una serie de opciones para capturar los datos. En esta parte hay que destacar lo siguiente:

  • Capture
    • Interface: eth0 (es el interface en el que deseamos
      capturar los datos, en caso de que existan varios, es aquí donde
      podemos seleccionar cual de ellos usar, o incluso todos con
      any).
    • Limit each packet to xx bytes: establece un límite para los
      paquetes. Para nuestro propósito no nos interesa, por lo que dejamos
      esta opción desmarcada.
    • Capture packets in promiscuos mode: activa el modo
      promiscuo en la tarjeta, es decir, se capturará todo lo que se escuche
      en el interface de red seleccionado. Podemos desactivarla, ya que solo
      nos interesa capturar lo que enviamos/recibimos nosotros.
      NOTA: en una switched-lan esta opción no tiene mucho efecto; si deseamos
      capturar paquetes en una red de este tipo debemos usar otro tipo de
      sniffer como el ettercap.
    • Filter: nos permite aplicar un filtro a lo que estamos
      capturando.
  • Capture file(s)
    • File: captura directamente a un fichero.
    • User ring buffer
  • Display options
    • Update list of packets in realtime: actualiza los paquetes
      capturados en tiempo real. Esto consume bastante CPU, con lo que no lo
      seleccionaremos.
    • Automatic scrolling in live capture: hace un scroll
      automatico de la informacion segun la va capturando. Para esta opción
      es necesario tener la casilla anterior activada.
  • Capture limits
    • Stop capture after xx packets captured: establece un límite
      en el número de paquetes.
    • Stop capture after xx kilobytes captured: establece un
      límite de Kb en la captura.
    • Stop capture after xx seconds captured: establece un límite
      de segundos de captura.
  • Name resolution
    • Enable MAC name resolution: activa la resolución de
      direcciones físicas.
    • Enable network name resolution: activa la resolución de
      nombres dns.
    • Enable transport name resolution: activa la resolución de
      servicios.




Al pulsar OK, nos debe aparecer otra ventana, en la que empieza a dar unas estadísticas con los datos que se capturan y la posibilidad de parar el proceso.
Vamos a efectuar un proceso simple, abriremos una sesión ftp, listaremos los contenidos del directorio y cerraremos la sesión. Si nos fijamos en la ventana anterior (la de estadísticas) veremos que ha cambiado y refleja el número y tipo de paquetes capturados. Pulsaremos STOP en dicha ventana para finalizar la captura.













Análisis de datos.

Una vez que hemos parado la captura, la ventana principal debería semejarse a esto (a veces para refrescar la información hay que pulsar la pestaña de RESET situada en la parte inferior de la ventana).

Analizaremos con un poco de detenimiento la información que hemos capturado. En primer lugar nos fijaremos en el orden de los primeros paquetes recibidos.
No.TimeSourceDestinationProtocolInfo
10.00000000:02:44:62:b2:4eff:ff:ff:ff:ff:ffARPWho has 192.168.1.1 ? Tell 192.168.1.2
20.00034800:02:44:62:b2:6200:02:44:62:b2:4eARP192.168.1.1 is at 00:02:44:62:b2:4e
1. ARP request: nuestro equipo quiere conectar con la
IP 192.168.1.1, pero no conoce su dirección física (MAC), por ello hace
una solicitud preguntando por broadcast.
2. ARP reply: el dueño
de la IP 192.168.1.1 escucha nuestra petición y nos contesta diciendonos
su direccion IP.
No.TimeSourceDestinationProtocolInfo
30.000406192.168.1.2192.168.1.1TCP1024 > 21 [SYN]
40.001455192.168.1.1192.168.1.2TCP21 > 1024 [SYN, ACK]
50.001617192.168.1.2192.168.1.1TCP1024 > 21 [ACK]
Una vez que hemos averiguado la dirección física mediante el
protocolo ARP y que también conocemos la dirección IP del destino, podemos
saltar unos niveles más arriba en la capa de protocolos y establecer una
conexión TCP con el host remoto. Esto se hace entre los paquetes numero 3
y 5, mediante una conexión conocida como three-way handshake.

3. SYN: nuestro host envía una petición de conexión (FLAG SYN)
al host remoto.
4. SYN/ACK: el host remoto nos envía una
petición de conexión (SYN) confirmando la nuestra (FLAG ACK).
5.
ACK: nuestro host envía la confirmación (FLAG ACK).
No.TimeSourceDestinationProtocolInfo
60.015938192.168.1.1192.168.1.2TCP1024 > 113 [SYN]
70.016024192.168.1.2192.168.1.1TCP113 > 1024 [RST, ACK]
6. SYN: el host remoto intenta acceder a nuestro
puerto local 113 (identd) para autentificarnos.
7. RST/ACK: no
tenemos el servicio identd disponible en nuestro host, cerramos la
conexión (FLAG RST/ACK).

Llegados a este punto, la conexión con el host remoto está establecida. En nuestro ejemplo de estudio, estábamos interesados en listar el contenido del directorio raiz del ftp. Si nos fijamos en la parte derecha (Info) de la ventana superior, veremos que hay unas líneas que ponen Respose: ..., esto es una pequeña parte de la información transferida, como deseamos verla toda, nos situaremos en el paquete donde la transferencia comienza (el número 8), pulsándolo en la ventana principal (superior) y a continuación haremos un filtrado de los datos para mostrar lo que realmente esta pasando en el nivel aplicación. Para ello usaremos la opción FOLLOW TCP STREAM, del menú TOOLS, también podríamos habernos situado con el raton en el paquete inicial y pulsar el boton derecho, para abrir una ventana de diálogo de menús, donde también aparecería dicha opción.

Este proceso de filtrado, extrae la información correspondiente a la capa de aplicación, que es la que en nuestro caso nos interesa analizar. Queremos saber cual es la estructura de los comandos del protocolo FTP y como se transmite la información (ASCII puro, binario...). Al pulsar la opción de FOLLOW TCP STREAM se nos abrirá otra ventana similar a esta:

Hay 2 partes diferenciadas:
  1. Datos: abarca la mayor parte, lo que recibimos sale en color azul y lo que enviamos en color rojo. En nuestro caso, el protocolo FTP usa
    comandos en ASCII osea que es un texto legible, del cual podemos sacar
    bastante información.
  2. Barra inferior.
    • Pestaña izquierda: en ella podemos seleccionar lo siguiente:
      - Entire conversation (por defecto) - muestra lo enviado y recibido en la
      ventana de datos.
      - 192.168.1.2:1024 ->; 192.168.1.1:21 : solo muestra
      lo que enviado.
      - 192.168.1.1:21 ->; 192.168.1.2:1024 : solo muestra
      lo que recibido.
    • Modo de visualización (ASCII / EBCDIC / Hex DUMP): son diferentes modos
      de visualizar la información. Por defecto sale en ASCII y es la que nos
      interesa.
    • Print / Save as / Close: permite imprimir o grabar los datos de esta
      ventana (ojo, solo estos).
Esta es la transcripción de paquetes que se suceden:

No.TimeSourceDestinationProtocolInfo
80.152402192.168.1.1192.168.1.2FTPResponse: 220 ProFTPD 1.2.5 Server (Debian)
[springfield.dns-local.net]
90.152522192.168.1.2192.168.1.1TCP113 > 1024 [RST, ACK]
100.153893192.168.1.2192.168.1.1FTPRequest: USER anonymous
110.154195192.168.1.1192.168.1.2TCP21 > 1024 [ACK]
120.158362192.168.1.1192.168.1.2FTPResponse: 331 Anonymous login ok, send your complete
email address as your password.
130.160653192.168.1.2192.168.1.1FTPRequest: PASS lftp@
14170701192.168.1.1192.168.1.2TCP21 > 1024 [ACK]
15328063192.168.1.1192.168.1.2FTPResponse: 230-Welcome, archive user
anonymous@192.168.1.2 !
160.328418192.168.1.1192.168.1.2FTPResponse: 230-
170.329057192.168.1.1192.168.1.2FTPResponse: 230-The local time is: Tue Sep 3 16:57:45
2002
180.329355192.168.1.1192.168.1.2FTPResponse: 230-
190.361780192.168.1.2192.168.1.1TCP1024 > 21 [ACK]
200.362268192.168.1.1192.168.1.2FTPResponse: 230-This is an experimental FTP server. If
have any unusual problems,
230-please report them via
e-mail...
210.362358192.168.1.2192.168.1.1TCP1024 > 21 [ACK]
220.363816192.168.1.2192.168.1.1FTPRequest: PWD
230.366798192.168.1.1192.168.1.2FTPResponse: 257 "/" is current directory.
240.369381192.168.1.2192.168.1.1FTPRequest: PORT 192,168,1,2,4,1
250.371912192.168.1.1192.168.1.2FTPResponse: 200 PORT command successful.
260.372797192.168.1.2192.168.1.1FTPRequest: LIST

Pero nosotros, con el cliente de ftp habíamos hecho un listado del directorio raiz y sin embargo, no aparece reflejado en esta ventana, que ha pasado entonces ?. Si nos remitimos a la ventana principal del ethereal y pulsamos RESET de nuevo, veremos que despues de los datos que van a partir del paquete 8, se abre otro socket por parte del servidor de ftp, a nuestro host, esta vez el puerto origen es el 20 (ftp-data) y el destino 1025, un puerto por encima del 1024, no privilegiado, que nuestro cliente de ftp ha especificado previamente en el paquete 24 con el comando PORT (podemos encontrar informacion de la estructura del comando PORT en el RFC).


Quizás haber empezado analizando el ftp no haya sido muy comodo y resulte algo confuso, ya que se usa un puerto para los comandos y otro para los datos, pero ya que estamos en ello, continuaremos. Al haber enviado el comando LIST (paquete número 26) inmediatamente se abre el nuevo socket ftp-data (paquete 27) desde el puerto 20 del servidor al puerto que previamente habiamos definido 1025, de esta manera:
 
No.TimeSourceDestinationProtocolInfo
270.375016192.168.1.1192.168.1.2TCP20 > 1025 [SYN]
280.375153192.168.1.2192.168.1.1TCP1025 > 20 [SYN, ACK]
290.375456192.168.1.1192.168.1.2TCP20 > 1025 [ACK]
Se establece una nueva conexión mediante three-way
handshake
, esta vez para el protocolo ftp-data.
No.TimeSourceDestinationProtocolInfo
300.376568192.168.1.1192.168.1.2FTPResponse: 150 Opening ASCII mode...
310.411776192.168.1.2192.168.1.1TCP1024 > 21 [ACK]
La conexión se ha realizado con exito y nos lo confirma en
el puerto de ftp (21). Los siguientes paquetes deberían ser los
respectivos a los datos enviados por el puerto de ftp-data (el listado de
los contenidos del directorio que habíamos solicitado).
No.TimeSourceDestinationProtocolInfo
320.454864192.168.1.1192.168.1.2FTP-DATAFTP Data: 58 bytes
330.454999192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
340.455295192.168.1.1192.168.1.2FTP-DATAFTP Data: 2 bytes
350.455352192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
360.455947192.168.1.1192.168.1.2FTP-DATAFTP Data: 58 bytes
370.456017192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
380.456288192.168.1.1192.168.1.2FTP-DATAFTP Data: 2 bytes
390.456355192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
400.456966192.168.1.1192.168.1.2FTP-DATAFTP Data: 63 bytes
410.457042192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
420.457301192.168.1.1192.168.1.2FTP-DATAFTP Data: 2 bytes
430.458641192.168.1.1192.168.1.2FTP-DATAFTP Data: 188 bytes

Efectivamente se confirman nuestras sospechas, si nos fijamos en el protocolo del paquete 32 es FTP-DATA. Además, si desplegamos en la ventana central la rama del arbol correspondiente a FTP-DATA, veremos que aparece una parte del listado del directorio. Volvemos a filtrar la informacion a partir de este paquete de la misma manera que antes, con la opción FOLLOW TCP STREAM de la barra de menú TOOLS.

Se nos abrirá otra ventana y en ella deberín aparecer los datos referentes al listado del directorio del ftp. El resultado debe ser similar a este:
En los siguientes paquetes, se nos confirma en el puerto de FTP, que la transferencia (listado del directorio) se ha realizado con éxito.

No.TimeSourceDestinationProtocolInfo
440.460325192.168.1.1192.168.1.2FTPResponse: 226-Transfer complete.
450.460585192.168.1.1192.168.1.2FTPResponse: 226 Quoutas off
460.491803192.168.1.2192.168.1.1TCP1025 > 20 [ACK]
470.491878192.168.1.2192.168.1.1TCP1024 > 21 [ACK]
Llegados a este punto, ya hemos descubierto toda la parte de información que
buscábamos. A partir de aquí se cierran los sockets existentes, tanto el de
FTP, como el de ftp-data. La conexion finaliza.
No.TimeSourceDestinationProtocolInfo
480.4512769192.168.1.2192.168.1.1TCP1025 > 20 [FIN, ACK]
490.512769192.168.1.1192.168.1.2TCP20 > 1025 [ACK]
502.263758192.168.1.2192.168.1.1FTPRequest: QUIT
512.264362192.168.1.2192.168.1.1TCP1024 > 21 [FIN, ACK]
522.264674192.168.1.1192.168.1.2TCP21 > 1024 [ACK]
532.267945192.168.1.1192.168.1.2FTPResponse: 221 Goodbye.
542.266054192.168.1.2192.168.1.1TCP1024 > 21 [RST]





Conclusiones del análisis.


El ftp, es un protocolo para intercambio de archivos (file transfer
protocol), usa 2 puertos TCP, el 20 para los datos y el 21 para los comandos.
Los comandos son en ASCII. La respuesta del servidor a nuestros comandos es
siempre numérica con una descripción despues del número, cualquier cosa
diferente a esta, se considera un comentario.
En este ejemplo no hemos analizado mas que una simple conexión para ejecutar
un comando de listado, sin tener en cuenta todos los factores que pueden
aparecer, como modos de transferencia ASCII/BINARY, modo PASSIVE para
transferencias detrás de un router o firewall y muchos otros. Podemos encontrar
toda la información que necesitemos en el RFC0959.





Provecho del análisis.


Intentaremos realizar en Perl una
simulación de lo que hemos hecho previamente con nuestro cliente de FTP. He aquí
el listado de código que emula de un modo muy simple y mínimo la operación de
nuestro cliente de ftp:
#!/usr/bin/perl -w
#
#    ftp-test by z0mbie (thesumidero@yahoo.com)
#    example ftp-test code writted for the article 
#    "analyzing protocoles with ethereal"
#
#    Copyright (C) 2002 Alejandro Portela, thesumidero@yahoo.com
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
require 5.005;
use strict;
use IO::Socket;
 
my $FTP_SOCK = IO::Socket::INET->new(
    PeerAddr => "192.168.1.1",
    PeerPort => 21,
    Proto    => "tcp"
);
unless ($FTP_SOCK) {
    print "error, no se puede crear el socket\n";
    exit(-1);
}
 
my $FTPDATA_SOCK = IO::Socket::INET->new(
    LocalPort => 1025,
    Proto     => "tcp",
    Listen    => SOMAXCONN,
    Reuse     => 1
);
unless ($FTPDATA_SOCK) {
    print "error, no se puede crear el socket\n";
    exit(-1);
}
 
while (<$FTP_SOCK>) {
    print "RECV <= ";
    print;
    if (/^220 /) {
        print $FTP_SOCK "USER ftp\n";
        print "SEND => USER ftp\n";
    }
    elsif (/^331 /) {
        print $FTP_SOCK "PASS ftp\n";
        print "SEND => PASS ftp\n";
    }
    elsif (/^230 /) {
        print $FTP_SOCK "PWD\n";
        print "SEND => PWD\n";
    }
    elsif (/^257 /) {
        print $FTP_SOCK "PORT 192,168,1,2,4,1\n";
        print "SEND => PORT 192,168,1,2,4,1\n";
    }
    elsif (/^200 /) {
        print $FTP_SOCK "LIST\n";
        print "SEND => LIST\n";
    }
    elsif (/^150 /) {
        last;
    }
    elsif (/^425 /) {
        exit(-1);
    }
}
 
my $LIST = $FTPDATA_SOCK->accept();
while (<$LIST>) {
    print "RECV <= ";
    print;
}
 
close($LIST);
close($FTPDATA_SOCK);
print $FTP_SOCK "QUIT\n";
close($FTP_SOCK);
Puedes bajar una copia de este código fuente aquí

1 comentario:

  1. Howdy! This blog post could not be written much better! Going through this article reminds me of my previous roommate!
    He constantly kept talking about this. I'll forward this information to him. Pretty sure he'll have
    a good read. Many thanks for sharing!
    Feel free to surf my web blog :: boost your bust review

    ResponderEliminar