Wednesday, October 22, 2008

Tratamiento grafico de logs de Firewall

Estoy trabajando en el tratamiento grafico de los logs de firewall en base a un articulo que lei en la revista Sysadmin

Aclaro que no soy un experto en GNUPLOT ni en scripting, por lo cual seguramente encontraras errores, recordas la frase que dice, una imagen es mejor que mil palabras ?

From Deny All



En mi caso solamente los FW que administro, producen 15.000.000 de eventos diarios, por lo cual tener una herramienta para el analisis de los logs en forma grafica seria una buena manera de detectar patrones, o errores que nos alerten de eventuales amenazas que estemos sufriendo.

Si bien no es una herramienta proactiva, es mejor que nada.

Los scripts son similares a los de la pagina que mencione, con alguna pequeña modificacion que permite trabajar con el patron de los logs del Firewall.

Basicamente el flujo de trabajo consiste en :

Download del log --> Filtro campos interesantes ---> Tratamiento grafico.




Por el momento todo es muy artesanal, pero con un poco de tiempo se puede automatizar todo el proceso.

Una tipica linea de Firewall consiste en los siguientes campos :

"258" "11Mar2008" "23:57:53" "xxxxxxxxxxxxxxxx" "eth1c0" "172.16.5.2" "Log" "Accept" "80" "200.225.159.26" "20.111.10.18" "tcp" "65" "50174" "" ""
Los campos mas interesantes :

Fecha : "11Mar2008"
Hora : "23:57:53"
Status : "Accept"
Port Destino : "80"
IP Origen : "200.225.159.26"
IP Destino : "20.111.10.18"


Una vez bajado el archivo tenemos que quitar del las IP de origen todas aquellas que pertenezcan a nuestro rango, de otra manera el grafico se vuelve confuso.

Luego se ejecuta el siguiente script en perl ( Al cual tengo que agregarle la funcion de quitar las IP nuestras ) :

#
# prepare-for-gnuplot.pl: convert Firewall log files to gnuplot input
# Raju Varghese. 2007-02-03
#
# XXXXXXXXXXXXX. 2008-03-10
#
use strict;

my $tempFilename = "/tmp/temp.dat";
my $ipListFilename = "/tmp/iplist.dat";

my (%ipList, %urlList);

sub ip2int {
my ($ip) = @_;
my @ipOctet = split (/\./, $ip);
my $n = 0;
foreach (@ipOctet) {
$n = $n*256 + $_;
}
return $n;
}

# prepare temp file to store log lines temporarily
open (TEMP, ">$tempFilename");

# reads log lines from stdin or files specified on command line

while (<>) {
chomp;
my ($time,$sc,$port,$sip,$dip) = split;
# $time =~ s/\[//;
# next if ($url =~ /(gif|jpg|png|js|css)$/);
print TEMP "$time $sc $port $sip $dip\n";
$ipList{$sip}++;
$ipList{$dip}++;
}

# process IP addresses

my @sortedIpList = sort {ip2int($a) <=> ip2int($b)} keys %ipList;
my $n = 0;
open (IPLIST, ">$ipListFilename");
foreach (@sortedIpList) {
++$n;
print IPLIST "$n $ipList{$_} $_\n";
$ipList{$_} = $n;
}
close (IPLIST);

close (TEMP); open (TEMP, $tempFilename);
while () {
chomp;
my ($time, $sc, $port, $sip, $dip ) = split;
print "$time $sc $port $ipList{$sip} $ipList{$dip} \n";
}
close (TEMP);

Es script realiza lo siguiente , primero genera una lista ordenada de IP,s origen ( SIP ) y destino ( DIP ) con la cantidad de eventos por IP :

Por ejemplo :

48797 7 224.212.150.4
48798 7 224.212.151.10
48799 7 224.212.151.26
48800 3 239.255.255.250

En donde el primer campo es el ID asignado a la IP, luego vienen el numero de eventos y por ultimo la IP.

Luego de esto , el script genera el archivo de relacion, entre IP's de origen y destino, el cual sera tomado por GNUPLOT para hacer el ploting.

Por ejemplo :

11Mar2008 0 80 39893 28234
11Mar2008 1 80 41524 30483

Dado que gnuplot no puede trabajar con texto, modique el valor del campo status de "Accept" a 1 y "Drop" a 0.


Esto tambien tengo que agregarlo al script, por el momento lo hago con awk.

Volviendo al archivo generado, este tiene los campos Fecha,Status,Puerto,IP ORIGEN, IP DESTINO.

Una vez con el archivo generado, ejecutamos gnuplot

A gnuplot en mi caso le doy las siguientes instrucciones :

set style data dots
set ticslevel 0
set zlabel "Ports"
set xlabel "SIP address"
set ylabel "DIP address"
set yrange[30400:30600]
rgb(r) = (r==1)? (238): (r==0)? (16711680):(16711680)
splot "test.input" using 4:5:3:(rgb($2)) with dots lc rgb variable

Esto signfica lo siguiente :

* Que genere puntos por cada "evento" ingresado

* Que el grafico este a nivel del 0 de las coordenadas cartesianas.
Labels de los ejes

* En mi caso las IP's que tengo se encuentran en este rango, por lo tanto lo limito .

* Para un evento permitido (Accept) que lo pinte "azul" ,para un evento rechazado (Drop ) que lo pinte "rojo".

* Que genere un grafico tridimensional con X:Y:Z: y el status del evento como variable R .


Esto generara una grafico con todos los eventos entrantes ( en este caso son 1.2 millones ) :


From Deny All




De esta imagen podemos sacar varios datos interesantes :

Vemos lineas azules que corren paralelas en los puertos mas bajos, evidentemente son los puertos que van desde el ftp en el puerto 21 hasta el ssl en el puerto 443.

En este caso son dos lineas porque tengo dos rangos de ip separados.

Veamos esto desde mas cerca, restringiendo el rango de puertos a los primeros 450.
Ejecutamos el siguiente comando

set zrange[0:450]
plot "test.input" using 4:5:3:(rgb($2)) with dots lc rgb variable

From Deny All


Aca se notan muchos Drops en el rango tcp 135 como tambien varios rechazos en el rango que va del ftp ( tcp 21 ) ssh ( tcp 22 ) y smtp ( tcp 25 )

Ahora veamos en mas detalle una de las lineas rojas que estan en el rango cercano al 25000 y que evidentemente es un scanning de todas las IP de mi rango publico.

Para esto reducimos el rango de IP sources al campo que nos interesa :

set xrange[24000:24500]


Reducimos una vez mas para tener mas precision y vemos que la IP origen tiene un ID cercano al 24060:

From Deny All



Veamos que IP corresponden a este ID y que tipo de scan realizo.


Del archivo de Ip's :

24060 22 200.129.159.249
24061 29 200.129.161.8
24062 10 200.129.162.10
24063 2 200.129.163.9
24064 231 200.129.168.202
24065 32 200.129.178.85
24066 129 200.129.178.171


Del archivo correlacionado :


12Mar2008 0 22 24064 28267
12Mar2008 0 22 24064 28260
12Mar2008 0 22 24064 28275
12Mar2008 0 22 24064 28287
12Mar2008 0 22 24064 28206
12Mar2008 0 22 24064 28296
12Mar2008 0 22 24064 28280
12Mar2008 0 22 24064 28210
12Mar2008 0 22 24064 28215
12Mar2008 0 22 24064 28283
12Mar2008 0 22 24064 28293
12Mar2008 0 22 24064 28217
12Mar2008 0 22 24064 28227
12Mar2008 0 22 24064 28298
12Mar2008 0 22 24064 28301
12Mar2008 0 22 24064 28234
12Mar2008 0 22 24064 28300
12Mar2008 0 22 24064 28307
12Mar2008 0 22 24064 28313



Esto podemos llamarlo un scanning horizontal, en el cual todas las IP del rango son scaneadas en un solo puerto.

Veamos ahora un scanning vertical, en el cual una IP es scaneada en varios puertos.

From Deny All


Cambiando el tipo de representacion de dots a points y el angulo de la imagen, podemos encontrar las coordenadas de estos eventos

From Deny All



Veamos la IP de origen y que puertos trato de acceder :


$grep 10895 /tmp/iplist.dat
10895 977 230.22.20.160
$grep 10895 /tmp/test.input




12Mar2008 0 58779 10895 30475
12Mar2008 0 59066 10895 30475
12Mar2008 0 59084 10895 30475
12Mar2008 0 59089 10895 30475
12Mar2008 0 10103 10895 30475
12Mar2008 0 10110 10895 30475
12Mar2008 0 14157 10895 30475
12Mar2008 0 14161 10895 30475
12Mar2008 0 14162 10895 30475
12Mar2008 0 14259 10895 30475
12Mar2008 0 14263 10895 30475
12Mar2008 0 14266 10895 30475
12Mar2008 0 14268 10895 30475
12Mar2008 0 14269 10895 30475
12Mar2008 0 14270 10895 30475



Trabajando con awk y gnuplot se puede filtrar esto y encontrar cosas que uno no esperaba encontar, por ejemplo un firewall aceptando conexiones en un port alto.


From Deny All



TO-DO para esto es terminar los scripts, y embeber esto en una pagina web para poder hacer esto en forma dinamica, creo que las posibilidades son muy interesantes.

No comments: