viernes, 2 de noviembre de 2012

De los bloqueos por MAC y demas hierbas

Primer post desde la tierra Kiwi (aaah cierto, me fui a New Zealand de paseo un tiempo :D). Las primeras impresiones del país son muy positivas, limpio, ordenado, las cosas funcionan, PERO... Internet es prácticamente inexistente. Suena muy loco en un país tan desarrollado, pero aparentemente se puede vivir sin estar conectado 24x7 (APARENTEMENTE!!!).

Este va a ser un post sencillo, para evadir una restricción de igual naturaleza. Cuando uno se encuentra en una red LAN básicamente (redes tipo ethernet, 802.11 wi-fi y otras mas) se encuentra identificado por una dirección MAC (sisi, también por una dirección IP, pero en primera instacia solo por la dirección MAC, :D, don't panic!). Se dice que una dirección MAC (http://es.wikipedia.org/wiki/MAC_address) identifica unívocamente a un adaptador de red físico, consiste en 48 bits formados por 6 bloques de 8 bits. Por ejemplo: 00:16:1b:5f:57:c3. Se supone que esta dirección es propia del adaptador de red y NO se puede cambiar, por este motivo muchas veces es utilizada para restringir el acceso a los servicios en una LAN.
Bien, resulta ser de que esta dirección SI se puede cambiar. Cambiándola se pueden conseguir cosas muy interesante, como el famosos ataque de MIM (man in the middle, hombre en el medio), pero eso no viene al caso ahora :D. Cambiando esta dirección en una LAN sobre la que no tenemos control nos permite básicamente cambiar nuestra identidad y por ejemplo permitiría cambiar la dirección IP en caso de que el DHCP las asigne estáticamente o hacernos pasar por otro miembro de la red.

Las pruebas se hicieron sobre mi laptop y en particular sobre la interfaz wlan0 (el adaptador de red wifi).

Ver la dirección MAC actual:

juan@moon:~$ ifconfig wlan0
wlan0     Link encap:Ethernet  direcciónHW 00:16:1b:5f:57:c3 
          Direc. inet:172.31.62.24  Difus.:172.31.255.255  Másc:255.255.0.0
          Dirección inet6: fe80::216:1bff:fe5f:57c3/64 Alcance:Enlace
          ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST  MTU:1500  Métrica:1
          Paquetes RX:17814 errores:0 perdidos:0 overruns:0 frame:0
          Paquetes TX:10555 errores:0 perdidos:0 overruns:0 carrier:0
          colisiones:0 long.colaTX:1000
          Bytes RX:12942393 (12.9 MB)  TX bytes:2236128 (2.2 MB)

juan@moon:~$


En este caso la MAC de mi adaptador wlan0 es 00:16:1b:5f:57:c3.

Posiblemente en alguna distribución se requiera permisos de root para utilizar ifconfig o utilizar el path completo /sbin/ifconfig. En ubuntu no es necesario :D.
Para facilitar la tarea del cambio de mac utilicé una aplicación llamada (extrañamente xD) macchanger (se puede obtener mediante: apt-get install macchanger).

Primero detenemos el servicio network-manager para que el adaptador de red no esté en uso:

root@moon:/home/juan# /etc/init.d/network-manager stop
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service network-manager stop

Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the stop(8) utility, e.g. stop network-manager
network-manager stop/waiting


Cambiamos la dirección MAC por una aleatoria utilizando macchanger. El parámetro -a indica que la MAC a asignar será aleatoria y de cualquier fabricante, y luego se indica sobre qué adaptador de red debe hacer el cambio (wlan0 en este caso):

root@moon:/home/juan# macchanger -a wlan0
Permanent MAC: 00:25:e2:24:24:1a (Azurewave Technologies, Inc)
Current   MAC: 00:16:1b:5f:57:c3 (Micronet Corporation)
New       MAC: 00:14:7b:74:b2:95 (Iteris, Inc.)


Iniciamos nuevamente el network-manager:

root@moon:/home/juan# /etc/init.d/network-manager start
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service network-manager start

Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the start(8) utility, e.g. start network-manager
network-manager start/running, process 3171


Y ahora comprobamos la nueva configuración del adaptador wlan0:

juan@moon:~$ ifconfig wlan0
wlan0     Link encap:Ethernet  direcciónHW 00:14:7b:74:b2:95 
          Direc. inet:172.31.65.63  Difus.:172.31.255.255  Másc:255.255.0.0
          Dirección inet6: fe80::214:7bff:fe74:b295/64 Alcance:Enlace
          ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST  MTU:1500  Métrica:1
          Paquetes RX:25972 errores:0 perdidos:0 overruns:0 frame:0
          Paquetes TX:14249 errores:0 perdidos:0 overruns:0 carrier:0
          colisiones:0 long.colaTX:1000
          Bytes RX:14604765 (14.6 MB)  TX bytes:3433891 (3.4 MB)

juan@moon:~$


Vemos que cambió la dirección MAC y también la dirección IP, dado que el servidor DHCP identificó a la dirección MAC como un nuevo dispositivo y le asignó una IP diferente a la anterior. Con esto nos alcanza para evadir ciertas restricciones como cuando nos limitan a por ejemplo una X cantidad de MB diarios gratis, generalmente este tipo de controles se realizan por MAC.

Otra posibilidad que nos brinda macchanger es elegir qué MAC ponerle al adaptador de red, ya se imaginarán para que puede servir eso jajaja.

miércoles, 4 de julio de 2012

mails de phishing news-story24.com

Buenos días!!! hoy va una entrada medio express porque tengo que ponerme a avanzar un poco con la tesis así que ahí vamos.

Resulta que esta mañana viendo los correos, me encuentro con que alguien que jamás me escribió, me mandó un link (http://moneyathomestor e.com/wp-admin/ultrup.html?rwz=bhhqeu). El mail no llama para nada la atención, no tiene asunto ni texto mas allá del propio enlace.

A simple vista se ve que se trata de un sitio hecho en wordpress (por el wp-admin). Como bien saben hay un dicho que dice "La curiosidad mató al gato", así que allá fue: copie la el link y lo pegué en el browser.

El link no nos lleva a al home del sitio principal, sino a algo similar a esto:


 Cuyo código (precario) es:


<h1>
You are here because one of your friends <br> have invited you.<br>
Page loading, please wait....
h1>
<meta http-equiv="refresh" content="3; url=http://news-story24.com/">


nos redirije a news-story24.com. Simpático!!! Analizando ese sitio con virustotal.com (https://www.virustotal.com/url/a7bb4e464122a7917a0b1fad660287c2ba7ec6e1fa80c423e69f7fb117888785/analysis/1341407178/) nos dice que es un sitio fraudulento y que se dedica al phishing, que raro xD.

Bien, veamos de qué se trata don news-story24!!! 

A simple vista el sitio se ve muy bonito:


Pero si empezamos a leerla y a pasear el mouse sobre ella nos encontramos con algo muy particular:

-Todos los links internos llevan a http://news-story24.com/hcg.php?s= , raro no?

Podemos ver todos los links disponibles en el sitio con:

$ curl news-story24.com 2>/dev/null| perl -n -e '/href=\"(.*?)\"/ && print "$1\n"'
Encontramos con 26 links a hcg.php?s=, y el resto son links de perfiles de facebook.

El link en cuestión nos redirije (por 301, moved permanently) a http://www984.hcg-diet-ultra.com/order.php?s= (también sospechoso https://www.virustotal.com/url/16574b392a4d0e682574573da7b073e7b297051a5b21ddc62a3884fef15cb374/analysis/1341411688/). Donde vemos todas las ofertas disponibles. 

Como nos morimos de ganas de comprar un producto para combatir nuestro exceso de peso (cuak!), procedemos a llenar el formulario. Notamos:

-Que en la parte baja del sitio tenemos imágenes como


Por las cuales uno podría pensar que se trata de un sitio seguro y confiable, pero no existe conexión https, y de hecho el formulario es procesador por el script http://www420.hcg-diet-ultra.com/success.php . 

A ver... puede que se trate de un sitio de ventas genuino, pero:

-Están utilizando spam entre otras cosas para promocionarse.
-No utilizan conexiones seguras para que el usuario pueda ingresar sus datos privados de manera confiable.

jueves, 14 de junio de 2012

Usando schemaspy

Buenas! Hoy en un rapto de inspiración y por cortesía de Gabriel (un compañero del trabajo) les voy a presentar una herramienta muuuy interesante para quienes les toque lidiar (en algún momento) con alguna base de datos de la cuál no tiene el Diagrama de Entidad Relación (DER de ahora y hasta el fin de los tiempos :P ). En mi caso en particular se trata de la BD de una aplicación llamada DTC.

Necesitamos un par de cosas para proceder:
  1. Schemaspy, que lo pueden descargar de: http://schemaspy.sourceforge.net/
  2. El driver jdbc para mysql (en este caso, porque la aplicación usa ese motor), que lo pueden obtener de: http://dev.mysql.com/downloads/connector/j/
  3. Y hay que tener también el paquete graphviz, necesario para la generación de las imágenes que describen las tablas de la BD.
Entoncessss, en el directorio de trabajo tenemos:

juan@moon:~/dtc$ ls
schemaSpy_5.0.0.jar  mysql-connector-java-5.1.20.tar.gz
juan@moon:~/dtc$

Descomprimimos el connector,

tar -xvf mysql-connector-java-5.1.20.tar.gz

Hacemos un backup de la base (Just In Case):

mysqldump -u root -p -h 127.0.0.1 --databases dtc > dtc.sql

Ahora tenemos:

juan@moon:~/dtc$ ls
mysql-connector-java-5.1.20         schemaSpy_5.0.0.jar
dtc.sql  mysql-connector-java-5.1.20.tar.gz
juan@moon:~/dtc$

Una vez tomadas las precauciones necesarias, lanzamos schemaspy:

juan@moon:~/dtc$ java -jar schemaSpy_5.0.0.jar -t mysql -db dtc -host 127.0.0.1 -u root -p ElPassword -dp mysql-connector-java-5.1.20/mysql-connector-java-5.1.20-bin.jar -o der_dtc

Como schemaspy se trata de una aplicación java la lanzamos con "java -jar schemaSpy_5.0.0.jar", el resto son parámetros de schemaspy, que significan:

-t mysql: indicamos que se trata de un motor MySQL.
-db dtc: indicamos que vamos a trabajar sobre la base de datos llamada dtc.
-host 127.0.0.1: indicamos el host donde escucha la BD.
-u root: indicamos el usuario con cuál vamos a conectarnos.
-p ElPassword: indicamos el password para autenticarnos (por lo que vi, esta es la única manera de pasar el password).
-dp mysql.../mysql....jar: indicamos el path al driver jdbc a utilizar.
-o det_dtc: el directorio donde queremos que schemaspy nos escriba toda la salida.

NOTA: existe una opción "-port puerto", que se supone se usa para especificar el puerto donde se encuentra la BD, en caso de que no sea el standard. Hago la nota, porque a mi no me funcionó :P.

Ahora abrimos el resultado:

juan@moon:~/dtc$ firefox der_dtc/index.html &

Y nos encontramos con toda la información que schemaspy pudo recolectar de nuestra BD.



La información que mas me interesaba debería estar en la tab de "Relationships", pero lamentablemente las tablas no tienen integridad referencial, por lo tanto schemaspy no es capaz de detectar las dependencias entre tablas, y por eso no dibuja el DER. Pero me sirve la tab "Utility tables", donde se listan todas las tablas, y uno puede darse una idea de las relaciones por el nombre de los campos y armar consultas para obtener lo que hace falta :D.


domingo, 10 de junio de 2012

Contando mis logs

Tanto tiempo ciertoo??? Esta vez vengo con un problema mas operativo que otra cosa! El problema es el siguiente: me tocó implementar un servidor de logs centralizado donde escriben logs unos mmm, 150-200 hosts, entre servidores, equipos de red, ups etc.

Hay momentos en el día en que la cantidad de logs se puede poner un pooco densa, y por las noches extrañamente el rsyslog colapsa. En principio activé el monitoreo propio de rsyslog, pero este solamente me dice la cantidad de logs en la cola actual, la cantidad encolados desde que inició el servidor, y el máximo de logs que hubo en algún momento en la cola.

##Estadisticas de rsyslog
$ModLoad impstats.so
$PStatInterval 20
$PStatSeverity 7


Aca una salida del monitoreo con impstats.so

Jun 10 20:50:25 bb rsyslogd-pstats: imuxsock: submitted=141 ratelimit.discarded=0 ratelimit.numratelimiters=72
Jun 10 20:50:25 bb rsyslogd-pstats: action 30 queue: size=0 enqueued=213694 full=0 maxqsize=159
Jun 10 20:50:25 bb rsyslogd-pstats: action 31 queue: size=0 enqueued=76427 full=0 maxqsize=18
Jun 10 20:50:25 bb rsyslogd-pstats: main Q: size=3 enqueued=636410 full=0 maxqsize=238

Tengo 3 colas, la principal y dos mas, una para escribir en un rsyslog secundario remoto y otra para escribir en una BD en otro servidor remoto.

Por las noches sucedía que la mainQ colapsaba y perdía logs. Un par de veces el servidor colapsó.

El tamaño default de la cola de mensajes principal es de 10k mensajes, por lo tanto como me sobraba memoria agrandé la cola considerablemente a unos 100k mensajes. Y por las dudas implementé unas mediciones extras para ver qué cantidad de logs están llegando y de qué dispositivos en particular.

Asumciones:
-Que los logs vienen por UDP (recuerdo que algunos servidores están configurador con TCP, pero son minoría).
-Que cada paquete UDP representa un mensaje, es lo mas probable.

La solución fue el siguiente script en perl:

#!/usr/bin/perl -w

open STDIN,"tcpdump -n -s 1024 -tt dst host HOST_IP and dst port 514 2>/dev/null |" or die "Oops";
open STDOUT,">>/dev/null";
open STDERR,">>/dev/null";

$t1=time();
$t2=$t1+300;

#Imprime en "valores" un historico con el siguiente formato
#fecha y hora
#mensajes -> host
#mensajes -> host
#...
#Ademas escribe en total_logs, el valor logs.value mensajes
#este archivo es levantado por munin para graficar la cantidad
#de mensajes recibidos en los ultimos 5 minutos
sub ver_valores
{
        my $i;
        my $s="";
        my $x=0;
        foreach $i (sort (keys %LOGS))
        {
                $x=$x+$LOGS{$i};
                $s=$s."$LOGS{$i} -> $i\n";
        }
        open(F,">>valores");
        print F localtime()."\n$s\n\n";
        close(F);
        open(F,">total_logs");
        print F "logs.value $x";
        close(F);
}


#Pone en 0 todos los valores del hash
sub reiniciar
{
        foreach $i (keys %LOGS)
        {
                $LOGS{$i}=0;
        }
}

while()
{
        my @a=split(' ',$_);
        my @b=split('\.',$a[2]);
        my $c="$b[0].$b[1].$b[2].$b[3]";
        if(defined $LOGS{$c})
        {
                $LOGS{$c}=$LOGS{$c}+1;
        }
        else
        {
                $LOGS{$c}=1;
        }
        $t1=time();
        if($t1 > $t2)#pasaron al menos 300 segundos
        {
                $t2=$t1+300;
                ver_valores();
                reiniciar();
        }
}


El script es bastante sencillo, toma la salida de tcpdump (un tanto filtrada para reducir la carga al script), y por cada linea (mensaje syslog) carga un nuevo valor en el hash o incrementa en 1 el valor si el host ya fue ingresado. Pasados los 300 segundos se llama a la función ver_valores(), que imprime datos en dos archivos diferentes. Luego la función reiniciar, que pone a cero la cantidad de mensajes de todos los hosts de hash, era mas sencillo reiniciar el hash completamente? SI, pero me interesa que el hash crezca a medida que un nuevo host comienza a mandar logs, y si deja de enviar que marque cero.

Filtrado del tcpdump:

-n: sin resolución de nombres.
-s 1024: reducir el tamaño máximo de captura por paquete, para no sobrecargar en vano, con 1024 bytes sobra para reconocer el tipo de paquete (UDP o TCP).
-tt: para que la hora se imprima como timestamp.
dst host HOST_IP and dst port 514: solamente captura los paquetes destinados a a la IP HOST_IP y al puerto 514 (UDP o TCP).

Si bien falta un pequeño detalle (a tratar en otro post, que es hacer de este script un demonio, de momento lo lanzo con screen), con esto logré saber el número de mensajes recibidos en los últimos 5 minutos y tener un historial que muestra la cantidad de logs que envió cada host.



En la imagen podemos ver como si bien hay una tendencia a los 2k mensajes cada 5 minutos, hubo unos picos muy interesantes que pasaron los 20k mensajes!!!

UPDATE: hice un cambio en la función ver_valores(), básicamente simplifiqué la obtención de la hora, ahora es mas simple la función.

sábado, 25 de febrero de 2012

Buscando una IP libre en mi red

Buenas, tanto tiempo!!! Definitivamente me cuesta alcanzar una frecuencia aceptable de entradas al blog, ya no cabe duda.

En fin, hoy les traigo un pequeño aporte que para algunas podría ser muy útil y para otros unas líneas de código casi inútiles xD.

El problema que intenta resolver es el siguiente: cuando uno administra una cantidad considerable de direcciones IP, digamos como mínimo una clase C fragmentada por ejemplo en 4 redes, resulta complicado saber qué direcciones están disponibles para asignar y cuáles están en uso.

Para existen las siguientes soluciones:
  • Tener una memoria perfecta y recordar precisamente todas las IPs libres y las asignadas.
  • Llevar registro con alguna herramienta.
  • Recorrer el rango de direcciones en busca de ellas.
Debo admitir que carezco de memoria perfecta, y no conozco una herramienta sencilla que resuelva el problema, por lo tanto opté por la tercera solución.


#!/usr/bin/perl -w
use Sys::Hostname;
use Socket;

####functions
#turns a number to an IP (dot-decimal notation)
sub pickAddress
{
    my $A = $_[0];
    my $aux;
    my $S="";
   
    $aux=$A & 4278190080;#first byte
    $aux=$aux>>24;
    $S=int($aux).".";#127.
   
    $aux=$A & 16711680;#second byte
    $aux=$aux>>16;
    $S=$S.int($aux).".";#127.0.

    $aux=$A & 65280;#third byte
    $aux=$aux>>8;
    $S=$S.int($aux).".";#127.0.0.
   
    $aux=$A & 255;
    $S=$S.int($aux);#127.0.0.1

    return $S;
}

#returns up if the host answer echo requests
sub state
{
    my $IP = $_[0];
    my $line;
    my $rtt;
    @SALIDA=`ping -nfq -w 1 -c 2 $IP`;
    while ($line=pop(@SALIDA))
    {
        if($line=~/0 received/)
        {
            return extraTest($IP);
        }
    }
    $rtt="UP";
    return $rtt;
}

#a running host might not answer echo requests, so lets try some common open ports.
sub extraTest
{
    my $IP=$_[0];
    @SALIDA=`nmap $IP -p T:25,22,21,53,80,110,443,U:53 2>/dev/null`;
    while ($line=pop(@SALIDA))
    {
        if($line=~/0 hosts up/)
        {
            $rtt="DOWN";
            return $rtt;#so it seems to be down... any other test?
        }
    }
    $rtt="UP";
    return $rtt;
}
####end of functions

####main code
if($< != 0)
{
    print STDERR "You must be root!\n";
    exit(-3);
}

$NET_ADDR="";
$NET_MASK="";
$HOSTS="";
$FIRST="";
$LAST="";

$argc=@ARGV;
if($argc < 1 or $argc > 2)
{
    print STDERR "USE: script [mask_bits]\n";
    exit(-1);
}

$NET_ADDR=$ARGV[0];
$NET_MASK=$ARGV[1];

#is it a real IP address?
if($NET_ADDR!~/^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/)
{
    print STDERR "Invalid network address. Example: 192.168.0.1\n";
    exit(-4);
}

#valid mask?
if($argc == 2 and ($NET_MASK > 30 || $NET_MASK < 1))
{
    print STDERR "Invalid mask. Mask [1 .. 30]\n";
    exit(-2);
}


#from 127.0.0.1 to 01111111 0000000 00000000 00000001
@L=split('\.',$NET_ADDR);
$NET_ADDR=$L[0]<<24;
$NET_ADDR=$NET_ADDR | $L[1]<<16;
$NET_ADDR=$NET_ADDR | $L[2]<<8;
$NET_ADDR=$NET_ADDR | $L[3];

if($argc == 2)
{#subnet check
    $HOSTS=2**(32-$NET_MASK) - 2;
   
    $aux=$NET_MASK;
    $NET_MASK=1;
    for($i=0;$i<32;$i++)
    {
        if($aux>0)
        {
            $NET_MASK=$NET_MASK<<1;
            $NET_MASK=$NET_MASK | 1;   
            $aux-=1;
        }
        else
        {
            $NET_MASK=$NET_MASK<<1;
        }
    }
    #now the real mask is ready, so i get the real net addr just in case
    $NET_ADDR=$NET_MASK & $NET_ADDR;
    $FIRST=$NET_ADDR+1;
    $LAST=$NET_ADDR+$HOSTS;
    print "NET ADDRESS: ".pickAddress($NET_ADDR).". NET MASK: ".pickAddress($NET_MASK).". HOSTS: $HOSTS. FIRST: ".pickAddress($FIRST).". LAST: ".pickAddress($LAST).".\n";

    $counter=1;

    while($counter<=$HOSTS)
    {
        $next_addr=pickAddress($NET_ADDR+$counter);
   
        $name=gethostbyaddr(inet_aton($next_addr),AF_INET);
   
        if(!$name)
        {
            $name="NONAME";
        }
   
        print $next_addr." is ".state($next_addr)." name $name\n";   
   
        $counter+=1;
    }
}
else
{#single host check
    $next_addr=pickAddress($NET_ADDR);
    $name=gethostbyaddr(inet_aton($next_addr),AF_INET);
    if(!$name)
    {
        $name="NONAME";
    }
    print $next_addr." is ".state($next_addr)." name $name\n";   
}


El script es bastante sencillo, recibe como parámetros una dirección IP y opcionalmente, el número de bits de la máscara de red. Debe ser ejecutado como root. Consiste básicamente en 2 pruebas, la primera es ver si el host responde mensajes ICMP, si los responde se concluye con que esa IP está en uso, si no responde se realiza una prueba mas en busca de puertos abiertos si la prueba devuelve algún puerto abierto, asume que la IP está en uso, de lo contrario asume que la IP está libre.

Aca les dejo una pequeña prueba. En busca de hosts en un fragmento de la red:

root@moon:/home/juan/Escritorio/stuff/Dropbox/TFG/scripts# ./chekIPs.pl 192.168.1.1 28
NET ADDRESS: 192.168.1.0. NET MASK: 255.255.255.240. HOSTS: 14. FIRST: 192.168.1.1. LAST: 192.168.1.14.
192.168.1.1 is DOWN name NONAME
192.168.1.2 is DOWN name NONAME
192.168.1.3 is DOWN name NONAME
192.168.1.4 is DOWN name NONAME
192.168.1.5 is DOWN name NONAME
192.168.1.6 is DOWN name NONAME
192.168.1.7 is DOWN name NONAME
192.168.1.8 is DOWN name NONAME
192.168.1.9 is DOWN name NONAME
192.168.1.10 is UP name NONAME
192.168.1.11 is DOWN name NONAME
192.168.1.12 is DOWN name NONAME
192.168.1.13 is DOWN name NONAME
192.168.1.14 is DOWN name NONAME


El script resulta mucho mas explícito cuando se ejecuta en una red que tiene resolución reversa de nombres.

La idea del script es meter el menor tráfico posible en la red, por eso las pruebas se separan en dos, siendo la primera muy sencilla y la segunda ya un poco mas exigente.

Yo lo uso para encontrar fácilmente direcciones IP que no están siendo utilizadas y así poder reasignarlas a nuevos hosts.

PD: si se preguntan porque está comentado en inglés (mi jefe me lo preguntó xD), no lo recuerdo jajaja.