lunes, 26 de septiembre de 2011

Ver actualizaciones Ubuntu + CentOS + OpenSuSE

Justamente en la entrada anterior veíamos una de las posibles consecuencias de no actualizar el software que utilizamos.  Si bien es cierto que actualizar indiscriminadamente puede ser un tanto riesgoso en entornos de producción, (podríamos romper alguna dependencia y dejar inútil una aplicación) actualizar ES NECESARIO!!!

Actualizar puede ser una tarea simple y hasta divertida cuando se tratan de unos pocos servidores, pero ya no tanto cuando el número comienza a ascender! Por lo tanto la idea de esta entrada es definir un mecanismo que nos permita:

-Identificar entre actualizaciones de seguridad y el resto.
-Automatizar los avisos de actualizaciones.

El modelo es el siguiente:

-Utilizamos nagios para recolectar y presentar la información.
-No buscaremos actualizaciones cada 5 minutos, las actualizaciones no salen con tanta frecuencia por lo tanto estaríamos consumiendo ancho de banda de manera innecesaria. En el esquema planteado los servidores buscaran sus actualizaciones una vez en el día, y el resto del día mostraran los datos de esa recolección hasta que sean actualizados.
-Tendremos 2 scripts:
  1. updateNombreDelSO.pl que dependerá del sistema operativo y será el que se ejecute automáticamente una vez al día para recolectar las actualizaciones disponibles. Este script generará el segundo.
  2. check_actualizaciones.sh que será el script que ejecuté nrpe en los servidores, bajo la demanda del servidor corriendo nagios. Este script es la salida del primero, solo imprime la cantidad de actualizaciones pendientes de seguridad y extra, y un código de salida acorde a la situación.
-Definimos como CRITICAL la situación en la que existen actualizaciones de seguridad sin aplicar, y como WARNING cuando solamente existen actualizaciones extras (no de seguridad) por aplicar.

updateUbuntu.pl

#!/usr/bin/perl
$STATUS_OK=0;
$STATUS_WARNING=1;
$STATUS_CRITICAL=2;
$STATUS_UNKNOWN=3;
$PATCHS=`/usr/lib/update-notifier/apt-check 2>&1`;
@A=split(';',$PATCHS);
$SALIDA="#!/bin/bash\n";
$EXIT=$STATUS_UNKNOWN;
$FILE="/usr/lib/nagios/plugins/check_actualizaciones.sh";
if($A[0] eq "0" and $A[1] eq "0")
{
    open(F,">$FILE");
    print F "$SALIDA"."echo \"Existen ".$A[0]." actualizaciones.\"\n";
    print F "exit $STATUS_OK";
    close(F);
    chmod (0777,$FILE);
    exit;
}
if($A[0] > 0)
{
    $SALIDA = $SALIDA . "echo \"ERROR - Existen ".$A[0]." actualizaciones de seguridad y ".$A[1]." extras\"\n";
    $EXIT = $STATUS_CRITICAL;
}
else
{
    $SALIDA = $SALIDA . "echo \"WARNING - Existen ".$A[1]." actualizaciones extras.\"\n";
    $EXIT = $STATUS_WARNING;
}
open(F,">$FILE");
print F $SALIDA;
print F "exit $EXIT";
close(F);
chmod (0777,$FILE);

El script es bastante, sencillo,  "/usr/lib/update-notifier/apt-check" nos devuelve una linea de la forma act_seguridad;act_extras, que separamos con split y guardamos así el número de actualizaciones de seguridad en $A[0] y el número de actualizaciones extras en $A[1]. Luego de eso simplemente definimos la salida según las actualizaciones que haya para hacer. La salida de este script es un archivo bash con el formato:

#!/bin/bash
echo "ERROR -  Existen 3 actualizaciones de seguridad y 2 extras"
exit 2

 Este archivo es el que ejecutará nrpe cada vez que nagios consulte por el plugin, por lo tanto debemos agregarlo al archivo de configuracion de nrpe:

#echo "command[check_actualizaciones]=/usr/lib/nagios/plugins/check_actualizaciones.sh">> /etc/nagios/nrpe.cfg

Ahora nos encargamos de que ĺa recolección de actualizaciones se haga una vez al día:

#echo "@daily root /path/to/script/updateUbuntu.pl" >> /etc/crontab

No olvidarse de reiniciar nrpe una vez que se agregue la linea y se ejecute manuelmente por primera vez "/path/to/script/updateUbuntu.pl".

updateCentOS.pl

Para este script necesitamos instalar un agregado de yum, ejecutar como root:  "yum -y install yum-security" .

#!/usr/bin/perl

$STATUS_OK=0;
$STATUS_WARNING=1;
$STATUS_CRITICAL=2;
$STATUS_UNKNOWN=3;

$SALIDA="#!/bin/bash\n";
$EXIT=$STATUS_UNKNOWN;
$FILE="/usr/lib/nagios/plugins/check_actualizaciones.sh";
@PATCHS=`yum -q --security check-update 2>/dev/null`;

$A[0]=0;
$A[1]=0;
foreach $i (@PATCHS)
{
    $A[0]=$A[0]+1;  
}

@PATCHS=`yum -q check-update 2>/dev/null`;
foreach $i (@PATCHS)
{
    $A[1]=$A[1]+1;  
}
if($A[0] eq "0" and $A[1] eq "0")
{
        open(F,">$FILE");
        print F "$SALIDA"."echo \"Existen ".$A[0]." actualizaciones.\"\n";
        print F "exit $STATUS_OK";
        close(F);
        chmod (0777,$FILE);
        exit;
}
if($A[0] > 0)
{
       $SALIDA = $SALIDA . "echo \"ERROR - Existen ".$A[0]." actualizaciones se seguridad y ".$A[1]." extras\"\n";
       $EXIT = $STATUS_CRITICAL;
}
else
{
        $SALIDA = $SALIDA . "echo \"WARNING - Existen ".$A[1]." actualizaciones extras.\"\n";
        $EXIT = $STATUS_WARNING;
}
open(F,">$FILE");
print F $SALIDA;
print F "exit $EXIT";
close(F);
chmod (0777,$FILE);

Este script mantiene el mismo concepto, salvo que en lugar de ejecutar un solo programa ejecuta dos, el primero obtiene las actualizaciones de seguridad disponibles y el segundo las extras.

También debemos agregar la linea en el archivo de configuración de nrpe como se explicó antes, así como también la línea en crontab para la ejecución. Reiniciar nrpe y ejecutarlo manualmente la primera vez.

updateOpenSuSE.pl

#!/usr/bin/perl

$STATUS_OK=0;
$STATUS_WARNING=1;
$STATUS_CRITICAL=2;
$STATUS_UNKNOWN=3;

@PATCHS=`zypper -q lp 2>/dev/null | grep -i needed`;
$FLAG=0;
$c=0;

$SALIDA="#!/bin/bash\n";
$EXIT=$STATUS_UNKNOWN;
$FILE="/usr/lib/nagios/plugins/check_actualizaciones.sh";

foreach $i (@PATCHS)
{
    $c=$c+1;
    @aux=split('\|',$i);
    #solo uso los campos 1, 2 y 3
    if($i =~ /security/)
    {
        push(@SEGURIDAD,$aux[1]);
    }
    else
    {
        push(@OTROS,$aux[1]);
    }
    $FLAG=1;
}

if(@SEGURIDAD == 0 and @OTROS == 0)
{
        open(F,">$FILE");
        print F "$SALIDA"."echo \"Existen ".@SEGURIDAD." actualizaciones.\"\n";
        print F "exit $STATUS_OK";
        close(F);
        chmod (0777,$FILE);
        exit;
}

if(@SEGURIDAD > 0)
{
        $SALIDA = $SALIDA . "echo \"ERROR - Existen ".@SEGURIDAD." actualizaciones de seguridad y ".@OTROS." extras\"\n";
        $EXIT = $STATUS_CRITICAL;
}
else
{
        $SALIDA = $SALIDA . "echo \"WARNING - Existen ".@OTROS." actualizaciones extras.\"\n";
        $EXIT = $STATUS_WARNING;
}

open(F,">$FILE");
print F $SALIDA;
print F "exit $EXIT";
close(F);
chmod (0777,$FILE);


Nuevamente pero esta vez para openSuSE, también se deben aplicar los puntos de los otros dos casos.

No voy a incluir la configuración de nagios (por tiempo, ya me dio sueño :P, si alguien la precisa la tengo), pero básicamente consiste en definir un servicio y utilizar nrpe para ejecutar remotamente "check_actualizaciones.sh", de esta forma nagios nos estaría avisando cuántas actualizaciones pendientes tenemos y de qué tipo son.

Cabe aclarar que si actualizamos un servidor, las alertas no se irán hasta que no se vuelva a hacer la recolección, pero como esto pasa una vez al día estaríamos viendo alertas el resto del día. Por lo tanto recomiendo que una vez actualizado el servidor se ejecute manualmente el archivo de recolección para que las alarmas se vayan :D.

Concejos, dudas y demás serán bien recibidos!


lunes, 12 de septiembre de 2011

Prueba de concepto CVE-2011-3200 rsyslog

Es una tendencia y una muy buena práctica la centralización de los logs de los equipos. Existen varias opciones, siendo las mas difundidas rsyslog, syslog-ng y syslogd.
En esta entrada vamos a comprobar una vulnerabilidad (debilidad o falta de un control) que fue encontrada hace un par de semanas en el servidor de logs rsyslog.
La vulnerabilidad es básicamente un desbordamiento de pila, provocado por un excesivo tamaño del campo TAG. Este, es uno de los campos que compone un mensaje tipo syslog (RFC3164 http://www.ietf.org/rfc/rfc3164.txt).

El contexto de pruebas es el siguiente:

-Servidor rsyslog remoto en la dirección 192.168.206.160 (OpenSuSE 11.3)
-Cliente rsyslog en la dirección 192.168.206.1 (Ubuntu 9.10)

Software utilizado:

-rsyslog 5.4.0 en el servidor
-rsyslog 4.2.0 en el cliente
-logger en el cliente
-hping3 en el cliente

Configurar el servidor rsyslog:

Primeramente configuramos nuestro servidor rsyslog para que reciba mensajes remotos, esto se hace editando el archivos /etc/rsyslog.d/remote.conf y descomentando las siguientes líneas:

$ModLoad imudp.so
$UDPServerRun 514

Luego reiniciamos rsyslog, y abrimos el puerto 514 UDP en el firewall para poder recibir los mensajes.

Configurar el cliente rsyslog:

En este ejemplo vamos a indicar al rsyslog que corre en la pc cliente, que envíe al servidor remoto los logs que tengan facility local7 y severity warn (o mayor a warn); agregamos la siguiente linea a /etc/rsyslog.d/50-default.conf

local7.warn    @192.168.206.160

Probando la configuración con logger:

Logger es una interface de comandos que nos comunica con el sistema de loggin del equipo local. Es decir, logger NO enviará los mensajes al servidor remoto, sino al rsyslog local y este los enviará a donde correspondan.

logger -p local7.err -d -t Prueba "esto es una prueba"

Y en la red vemos:


Y del lado del servidor, con tail -f /var/log/messages veremos como llega nuestro mensaje:



Entonces ya tenemos andando nuestro servidor de logs centralizado (.... por decirlo de una manera :P).

Ahora veamos qué pasa si rompemos la barrera de los  32 caracteres en el campo TAG del mensaje, utilizando logger.

# logger -p local7.err -d -t PruebaPruebaPruebaPruebaPruebaTTX "esto es una prueba"

Captura de wireshark:


CARAMBA! Podemos apreciar que la X que excede el límite de los 32 caracteres nunca salió de nuestro sistema, es decir que nuestro rsyslog local cortó la cadena para solamente enviar lo permitido.

Bien, de momento podemos asegurar que un rsyslog no tiraría abajo otro rsyslog porque jamás enviaría un TAG que superase el límite que dicta el RFC.

Qué pasa si... creamos a mano un mensaje syslog y violamos esta restricción?

Para simular el mensaje copiamos de wireshark la parte de datos del paquete UDP y lo pegamos abriendo un archivo en modo binario (vi -b crafted_packet), de la siguiente forma:


Ahora el TAG tiene "PruebaPruebaPruebaPruebaPruebaTTX" que son 33 caracteres, es decir la misma prueba que hicimos con logger, pero esta vez será de manera manual, salteandonos el rsyslog local.

Pero cómo metemos este mensaje en un paquete UDP y lo enviamos al servidor???

hping3 es la respuesta a esa pregunta!!! hping3 es una aplicación esencialmente diseñada para hacer ataques de flooding xD, pero en este caso la usaremos con fines menos escabrosos. Entre otras cosas nos permite crear paquetes ICMP, IP, TCP, UDP de forma muy flexible y enviarlos a tasas dañinas o no.

Lo que haremos es generar paquetes UDP al puerto 514 del servidor de logs remoto en la IP 192.168.206.160.

La forma de generar el paquete es la siguiente:


-2 : indica que queremos generar paquetes UDP
-i 1: cantidad de paquetes por segundo
-d 78: tamaño del PDU UDP, es decir de los datos del paquete UDP
-E crafted_packet: es el archivo de 78 bytes que creamos anteriormente
-p 514: indica el puerto de destino de los paquetes
192.168.206.160: es la IP del servidor remoto

En la parte inferior de la imagen vemos los dos paquetes que recibió el servidor remoto, y se puede apreciar la X extra que excede los 32 caracteres. Por lo tanto queda claro que el buffer donde se guarda esta variable tiene mas de 32 bytes de espacio.

Bueno, ahora a reventarlo de una vez por todas.

Ahora generemos un ultra_crafted_packet (muajaja muajaja), básicamente es el crafted_packet, pero con 1024 X en lugar de una. Al archivo lo generé con un MUY feo script en perl.

#!/usr/bin/perl -w
open(F,">ultra_crafted_packet");
$inicio="<187>Sep 11 15:25:32 moon PruebaPruebaPruebaPruebaPruebaTT";
$fin=" esto es una prueba";
$mid="";
foreach $i (1 .. 1024)
{
    $mid="X".$mid;
}
print F $inicio.$mid.$fin;
close(F);

Ejecutamos el script y ya tenemos nuestro super ultra_crafted_packet, con un total de 1101 bytes. Entonces lanzamos hping3, cambiando los parámetros que corresponden (-d 1101 y -E ultra_crafted_packet).


Y en el servidor nos encontramos con una grata sorpresa :D :


La muerte súbita de rsyslogd y el backtrace correspondiente.

Entonces nos encontramos ante un sencillo caso de denegación al servicio de login centralizado. Solo basta con 1 paquete que exceda los límites del buffer donde se almacena el campo TAG del mensaje syslog, para que el servicio muera.

POR SUERTE la mayoría (sino todas) de las distribuciones ya han publicado el parche correspondiente. Por lo tanto actualizar el servidor es crucial.

#zypper lu -t patch | grep rsyslog


Nos muestra disponible el parche de seguridad 5099, que corresponde a esta vulnerabilidad. Lo aplicamos y volvemos a probar.

#zypper in patch rsyslog

#rcsyslog restart

Y volvemos a lanzar hping3 con los parámetros que mataron el servidor, pero esta vez vemos:


Esta vez el servidor no hice overflow y sigue funcionando perfectamente. Por lo tanto el parche funciona.

Bueno, esto ya se extendió demasiado, posiblemente esta vulnerabilidad pueda ser explotada para hacer cosas mas peligrosas, pero a mi gusto es suficiente con poder denegar un servicio que podría ser crucial para una organización.

El parche creo que se tomó 1 semana en salir, y en ese tiempo todos los rsyslog que vagaban por el mundo eran vulnerables a algo tan secillo como esto... me gustaría creer que no queda ninguno sin actualiazr... ME GUSTARÍA!!!

miércoles, 31 de agosto de 2011

Usando tmpfs

Bien, entrada corta si las hay!!! Esto va a ser una PEQUEÑA demostración del uso de tmpfs. Qué es tmpfs??? Wiki knows (http://es.wikipedia.org/wiki/Tmpfs#Linux). Es una suerte de sistema de archivos en memoria volátil (RAM y swap si es necesario, ojo!!!).

Ventajas:
-Las operaciones de lectura y escritura son MUCHO mas rápidas que en otros medios de IO como los discos rígidos (IDEAL para montar directorios de CACHEs).
-Es sencillo de utilizar.
 Desventajas:
-Es volátil!!! no se mantiene luego de un reinicio del equipo por ejemplo.
-Su espacio está limitado por la cantidad de memoria RAM disponible y la swap del sistema.

Demostración simple de uso y rendimiento en escritura:

Creamos un directorio llamado prueba_tmpfs

root@moon:~# mkdir prueba_tmpfs

Antes de montar veamos cómo se el consumo de memoria con free -m.

root@moon:~# free -m
                     total       used       free     shared    buffers     cached
Mem:          1975       1167        807          0         25        538
-/+ buffers/cache:        603       1371
Swap:         5789          0       5789

Montamos un sistema de archivos tipo tmpfs (-t tmpfs) de 1GigaByte en el directorio que acabamos de crear.

root@moon:~# mount -t tmpfs -o size=1G tmpfs prueba_tmpfs/
Vemos los puntos de montaje existentes y nos encontramos con nuestro tmpfs recien montado.

root@moon:~# mount 
...
 tmpfs on /root/prueba_tmpfs type tmpfs (rw,size=1G)


Pegamos una mirada con free para ver qué pasó y vemos que si bien el directorio se montó, no se ocupó memoria del sistema aún.

root@moon:~# free -m
                     total       used       free     shared    buffers     cached
Mem:          1975       1167        807          0         25        538
-/+ buffers/cache:        603       1371
Swap:         5789          0       5789

Veamos qué beneficios nos trae tmpfs, escribamos algo!!! Para probar utilizamos un simple dd.

root@moon:~# dd if=/dev/zero of=prueba_tmpfs/prueba bs=1M count=768
768+0 registros de entrada
768+0 registros de salida
805306368 bytes (805 MB) copiados, 1,58104 s, 509 MB/s

Nos encontramos con una velocidad de escritura de 509 Mbytes por segundo!!! (509MBytes*8 = 4072Mbits por seg aprox 4Gbits por segundo!!! lo cual es consistente con el ancho de banda teórico de las memorias DDR2 de 667 Mhz que tiene mi laptop :D). Una velocidad MAS que interesante.

Podemos ver un cambio significativo en free -m. Pasamos de 807 a 37 Mbytes libres, es decir consumimos 807-37=770 (consistente con los 768 que escribimos con el dd).

root@moon:~# free -m
                     total       used       free     shared    buffers     cached
Mem:          1975       1937         37          0         25       1306
-/+ buffers/cache:        605       1369
Swap:         5789          0       5789

mmm ahora le toca al sata de la laptop hacer su mejor esfuerzo xD (competencia un tanto injusta jajaja). Escribimos de la misma manera que antes, pero a un archivo fuera del directorio donde montamos el tmpfs, en este caso el archivo se llama simplemente prueba.

root@moon:~# dd if=/dev/zero of=prueba bs=1M count=768
768+0 registros de entrada
768+0 registros de salida
805306368 bytes (805 MB) copiados, 12,3028 s, 65,5 MB/s

La velocidad fue de 65,5 Mbytes por segundo (65,5Mbytes * 8 = 524 Mbits por segundo, bastante por debajo del máximo teórico de los SATA II, por debajo inclusive del SATA I). Con esto queda claro que la diferencia es IMPORTANTE, la escritura sobre tmpfs fue casi 8 veces mas rápida (509/65,5=7,7).

Demostración simple de uso y rendimiento en lectura:

Todo muy lindo en la escritura, pero en la lectura qué será? :O.

Primero leemos del tmpfs y vemos una velocidad bastante mayor a la que obtuvimos en escritura. Pasando los 7Gbits por segundo!!!, esto seguramente se debe a algún manejo extraño de caches por parte del kernel, porque esta velocidad excede el límite teórico de las memorias de la laptop.

root@moon:~# dd if=prueba_tmpfs/prueba of=/dev/null bs=1M
768+0 registros de entrada
768+0 registros de salida
805306368 bytes (805 MB) copiados, 0,873211 s, 922 MB/s

Con respecto a la lectura en disco... Obtuve una velocidad muy similar a la de escritura, lo cual NO es muy común en este tipo de dispositivos.

root@moon:~# dd if=prueba of=/dev/null bs=1M
768+0 registros de entrada
768+0 registros de salida
805306368 bytes (805 MB) copiados, 13,5713 s, 59,3 MB/s

Por lo general los discos rígidos leen a mayor velocidad de la que escriben, por lo tanto podríamos suponer que la velocidad de escritura obtenida anteriormente es producto de algún manejo eficiente de cache o una suerte de inteligencia en la escritura de datos repetidos (solamente ceros, obtenidos de /dev/zero).

Qué pasa si...?:

Intentamos escribir mas bytes de los que tiene asignado nuestro directorio en tmpfs:

root@moon:~# dd if=/dev/zero of=prueba_tmpfs/prueba bs=1M count=1024
dd: escribiendo «prueba_tmpfs/prueba»: No hay espacio libre en el dispositivo
1022+0 registros de entrada
1021+0 registros de salida
1071640576 bytes (1,1 GB) copiados, 2,47776 s, 433 MB/s
root@moon:~#

Como era de esperarse no pudimos escribir mas de lo que definimos como tamaño del tmpfs :D.

Creamos un tmpfs mayor que nuestra RAM (mi laptop tiene 2Gbytes de RAM):

Es absolutamente posible hacerlo, PERO...

root@moon:~# mount -t tmpfs -o size=3G tmpfs prueba_tmpfs
root@moon:~# mount | grep prueba_tmpfs
tmpfs on /root/prueba_tmpfs type tmpfs (rw,size=3G)
a medida que comencemos a ocupar el espacio del tmpfs, nos comeremos (si, casi literalmente) la memoria ram del equipo, este comenzará a intercambiar páginas con poco uso a la memoria de intercambio (swap) y eventualmente el sistema podría quedar inutilizable. Moraleja? no es recomendable hacerlo (cosas que pasan xD).


Conclusión:

Definitivamente es una opción muy interesante principalmente para utilizar como directorio para caches.

En mi caso en particular utilicé tmpfs para el directorio donde munin crea/actualiza los archivos rrd, en un servidor que monitorea mas de 100 servidores, y el cambio fue notable. Antes de esto los gráficos se cortaban porque el proceso de graficar no terminaba antes de que llegaran las nuevas mediciones.

jueves, 25 de agosto de 2011

Como quitar Windows 7, instalar CentOS 6 desde un pendrive y todo esto sin que se muera Ubuntu 9.10 oO


Windows en las particiones sda3 y sda4, CRAP!!! ¿sda2 es booteable? qué pasa si la borro?

root@moon:/home/juan# fdisk -lu /dev/sda

Disco /dev/sda: 250.1 GB, 250059350016 bytes
255 cabezas, 63 sectores/pista, 30401 cilindros, 488397168 sectores en total
Unidades = sectores de 1 * 512 = 512 bytes
Identificador de disco: 0xbab21f87

Dispositivo Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sda1              63   454623434   227311686   83  Linux
/dev/sda2   *   454625280   454830079      102400    7  HPFS/NTFS
/dev/sda3       454830080   476534783    10852352    7  HPFS/NTFS
/dev/sda4       476536095   488392064     5927985    5  Extendida
/dev/sda5       476536158   488392064     5927953+  82  Linux swap / Solaris


Para ver en qué consiste mi grub actualmente ejecuté

root@moon:/home/juan# grub-mkconfig -o grub.conf.bak
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.31-22-generic
Found initrd image: /boot/initrd.img-2.6.31-22-generic
Found linux image: /boot/vmlinuz-2.6.31-21-generic
Found initrd image: /boot/initrd.img-2.6.31-21-generic
Found linux image: /boot/vmlinuz-2.6.31-20-generic
Found initrd image: /boot/initrd.img-2.6.31-20-generic
Found linux image: /boot/vmlinuz-2.6.31-19-generic
Found initrd image: /boot/initrd.img-2.6.31-19-generic
Found linux image: /boot/vmlinuz-2.6.31-17-generic
Found initrd image: /boot/initrd.img-2.6.31-17-generic
Found linux image: /boot/vmlinuz-2.6.31-16-generic
Found initrd image: /boot/initrd.img-2.6.31-16-generic
Found linux image: /boot/vmlinuz-2.6.31-15-generic
Found initrd image: /boot/initrd.img-2.6.31-15-generic
Found linux image: /boot/vmlinuz-2.6.31-14-generic
Found initrd image: /boot/initrd.img-2.6.31-14-generic
Found memtest86+ image: /boot/memtest86+.bin
Found Windows 7 (loader) on /dev/sda2
done

De esta manera me hice con una copia de la configuración actual, por si las moscas!!!
mmmm... viendo un poco la configuración actual de grub encontré la parte donde se define el arranque del win7

menuentry "Windows 7 (loader) (on /dev/sda2)" {
        insmod ntfs
        set root=(hd0,2)
        search --no-floppy --fs-uuid --set 2860188560185c3e
        chainloader +1
}


Entonces decidí actuar! :P
Eliminé ambas particiones de windows!

root@moon:/etc/grub.d# fdisk -lu /dev/sda

Disco /dev/sda: 250.1 GB, 250059350016 bytes
255 cabezas, 63 sectores/pista, 30401 cilindros, 488397168 sectores en total
Unidades = sectores de 1 * 512 = 512 bytes
Identificador de disco: 0xbab21f87

Dispositivo Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sda1              63   454623434   227311686   83  Linux
/dev/sda4       476536095   488392064     5927985    5  Extendida
/dev/sda5       476536158   488392064     5927953+  82  Linux swap / Solaris
Por lo tanto me quedó un gran vacío xD, unos 11Gb perdidos entre sda1 y sda4, ese vacío debería ser llenado por CentOS :D.
Volví a lanzar grub-mkconfig -o grub.conf.bak.2, y esta vez ya no aparecieron las líneas del arranque de windows 7 :D.

root@moon:/etc/grub.d# grub-mkconfig -o grub.conf.bak.2
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.31-22-generic
Found initrd image: /boot/initrd.img-2.6.31-22-generic
Found linux image: /boot/vmlinuz-2.6.31-21-generic
Found initrd image: /boot/initrd.img-2.6.31-21-generic
Found linux image: /boot/vmlinuz-2.6.31-20-generic
Found initrd image: /boot/initrd.img-2.6.31-20-generic
Found linux image: /boot/vmlinuz-2.6.31-19-generic
Found initrd image: /boot/initrd.img-2.6.31-19-generic
Found linux image: /boot/vmlinuz-2.6.31-17-generic
Found initrd image: /boot/initrd.img-2.6.31-17-generic
Found linux image: /boot/vmlinuz-2.6.31-16-generic
Found initrd image: /boot/initrd.img-2.6.31-16-generic
Found linux image: /boot/vmlinuz-2.6.31-15-generic
Found initrd image: /boot/initrd.img-2.6.31-15-generic
Found linux image: /boot/vmlinuz-2.6.31-14-generic
Found initrd image: /boot/initrd.img-2.6.31-14-generic
Found memtest86+ image: /boot/memtest86+.bin
done


Por último una actualizada del grub para que los cambios se reflejen en el archivo de configuración real:

root@moon:/etc/grub.d# update-grub
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.31-22-generic
Found initrd image: /boot/initrd.img-2.6.31-22-generic
Found linux image: /boot/vmlinuz-2.6.31-21-generic
Found initrd image: /boot/initrd.img-2.6.31-21-generic
Found linux image: /boot/vmlinuz-2.6.31-20-generic
Found initrd image: /boot/initrd.img-2.6.31-20-generic
Found linux image: /boot/vmlinuz-2.6.31-19-generic
Found initrd image: /boot/initrd.img-2.6.31-19-generic
Found linux image: /boot/vmlinuz-2.6.31-17-generic
Found initrd image: /boot/initrd.img-2.6.31-17-generic
Found linux image: /boot/vmlinuz-2.6.31-16-generic
Found initrd image: /boot/initrd.img-2.6.31-16-generic
Found linux image: /boot/vmlinuz-2.6.31-15-generic
Found initrd image: /boot/initrd.img-2.6.31-15-generic
Found linux image: /boot/vmlinuz-2.6.31-14-generic
Found initrd image: /boot/initrd.img-2.6.31-14-generic
Found memtest86+ image: /boot/memtest86+.bin
done


Y ahora le pegamos un reboot a ver qué pasa!!! (no hacer bungee jumping con los cordones!!!, por las dudas tengan un live-cd de alguna distro para arreglar grub :P, yo tengo en un pendrive un ubuntu 9.04 por si las moscas).

NOTA: luego de reiniciar noté que ya no me aparecía la lista de entradas para elegir, sino que directamente me cargó la primer entrada sin decir nada. Me queda averiguar porque...

Bien ahora, a preparar el pendrive desde donde bootear para instalar CentOS, claramente no pienso quemar un CD para usarlo una sola vez ajajaja. Rata? no!, económico! Lo mas complicado de todo esto fue encontrar el pendrive xD, los hacen tan pequeñosss.

NOTA: Backup del pendrive!!!!

Para hacer booteable nuestro pendrive con una iso de CentOS , primero descargamos la iso (wget http://centos-mirror.hostdime.com.br/centos/6.0/isos/x86_64/CentOS-6.0-x86_64-minimal.iso) :P, y luego instalamos "UNetbootin" (a buscar los paquetes gente, aptitude search unetbootin y ver :P).
Elegimos la iso y la partición del pendrive que correspondan, aceptamos y esperamos un raaaato.



Ahora reiniciamos y vemos qué pasa!

Una vez booteado del pendrive elegimos la primer opción que dice con video básico y cargará el instalador de CentOS.

NOTA1: no encontraba el archivo /images/install.img, cuando aparece la opción para ingresar el path del archivo hay que poner ./images/install.img y elegir el dispositivo que corresponda al pendrive!

NOTA2: también es necesario copiar la iso del CD dentro del pendrive!

Durante la instalación en ningún momento hay que dejar que particione el disco ni que instale un bootloade!!!! sino no va a salir caro :P

Terminada la instalación, inicié ubuntu y corrí nuevamente un grub-mkconfig pero la configuración ni se enteró de la instalación de CentOS...

A meterle mano a Grub: la versión de grub que tengo ¿1.97? oO, se configura a partir de unas plantillas que se encuentran en el directorio /etc/grub.d y también el archivo /etc/default/grub.

Primero modificamos /etc/default/grub para que vuelva a aparecer el menu de sistemas operativos durante el booteo de grub, esto se logra comentando la línea que dice GRUB_HIDDEN_TIMEOUT=0.

Ahora agregamos las lineas necesarias para el arranque de CentOS en el archivo /etc/grub.d/40_custom (en este archivo deberiamos incluir todas las entradas que pongamos manualmente):

menuentry "CentOS 6" {
    set root=(hd0,2)
    linux /boot/vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/sda2 rhgb quiet
    initrd /boot/initramfs-2.6.32-71.el6.x86_64.img
}


NOTA: estas líneas deben ser agregadas al final del archivo y sin modificar el resto de las lineas anteriores.

Vemos que las lineas indican la partición de root, la imagen del kernel y el initrd.
Ahora debemos actualizar grub para que aplique estos cambios a la configuración actual (update-grub) y vemos que la entrada fue agregada correctamente al final del archivo de configuración:

root@moon:/home/juan# tail /boot/grub/grub.cfg
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry "CentOS 6" {
    set root=(hd0,2)
    linux /boot/vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/sda2 rhgb quiet
    initrd /boot/initramfs-2.6.32-71.el6.x86_64.img
}

### END /etc/grub.d/40_custom ###


Reiniciamos y.... :D un lujo, probado y re contra probado, levantó CentOS sin ningún inconveniente.

miércoles, 9 de febrero de 2011

Bicho de messenger Nº: n+1

Estoy en pleno estudio así que esta entrada será breve y posiblemente inconclusa, pero me parece que vale la pena hacerla.
Mientras estudiaba, un contacto de messenger me envió el siguiente mensaje:


Anterior a esta hubo otros, pero que involucraban dominios que no valía la pena analizar, pero este... este dice apps.facebok.com!!!

Como siempre en estas cosas hay que ser cauto, y la verdad que quería hacer clic en ese link :P. En fin, limpié las cookies de mi browser, inicié sesión en una cuenta de facebook que tengo para estas ocasiones especiales e hice clic :D.


NICE!, una vez mas salvado por "non script", en la aplicación en cuestión lograron insertar un iframe, el siguiente:

ZOOM IN:
Podemos ver claramente el dominio al que hace referencia, no me queda claro, almenos aún que está enviando mediante "?signed_request=VALOR", eso me queda por ver cuando tenga mas tiempo.

Hace unos minutos la applicación directamente nos invitaba a descargar "http://christybonham.com/img/facebook-pic0009345919.exe", ahora solamente nos muestra el listado del sitio "http://christybonham.com/img/"

Efecto anterior:


A juzgar por como fueron cambiando las fechas/hora de última actualización de los archivos, se puede decir que están en pleno desarrollo.

Denuncié adecuadamente la aplicación, pero facebook aún no la deshabilitó.

Link del reporte a virus total: http://www.virustotal.com/file-scan/report.html?id=e34cca1509d1ead0f2131049389c42c157ec83b848e6bb8bca4f4fc7a89e0429-1297287029

No tengo tiempo para probar los efectos del .exe, si alguien se anima y me cuenta será muy apreciado!


UPDATE 1:

Pensando un poquito se me ocurrió procesar el parámetro signed_request, con base64 y obtuve esto:

cadena_que_no_pude_descifrar.{"algorithm":"HMAC-SHA256","issued_at":1297282079,"user":{"country":"ar","locale":"es_LA","age":{"min":21}}}

Mis conocimientos de javascript son MUY básicos, pero eso parece ser un HASH, posiblemente la cadena_que_no_pude_descifrar no sea mas que el nombre del hash, un nombre posiblemente asignado por facebook, porque es bastante largo y feo (posiblemente aleatorio). No veo que se estén llevando datos realmente sensibles, al menos no con ese parámetro. Alguien con mas info???

UPDATE 2:

Aparentemente la app de facebook ya fue dada de baja, pero el servidor sigue infectando hosts.

viernes, 28 de enero de 2011

El retorno: "Reto ncn_2010 Parte1"

Como verán hace un par o dos pares de meses que no ando por aquí. Básicamente es por mi PÉSIMA administración del tiempo, no soy lo que se dice la persona mas ocupada del mundo, pero siempre me las arreglo para que el tiempo no me sea suficiente xD.

Llevo alrededor de 6 meses ya en mi pasantía en el centro de redes de la Universidad Nacional de Córdoba, y debo decir que es increíble todo lo que se aprende en el campo de batalla. Definitivamente era lo que me hacía falta, práctica.

Pero como esto NO es un diario, o por lo menos ahora no lo es, les traigo la primera parte de mi interpretación del reto http://noconname.org/concursos/NcN_2010_Reto_Forense.pdf , aquí la imagen del dispositivo a analizar http://noconname.org/concursos/okin.dd.bz2 .

En primera instancia cabe aclarar que este no es un reto como los demás, aquí no hay mas consigna que: Todo lo que encuentres y puedas justificar vale.

""Obras a la Mano":
Una vez descargado el archivo lo descomprimimos y utilizamos el famoso file para ver de qué se trata okin.dd.

root@moon:/home/juan/ForensicTests/NcNForense# file okin.dd
okin.dd: Linux rev 1.0 ext2 filesystem data (mounted or unclean), UUID=42006dd3-3ea3-42dd-aa42-e86c3376ea31
root@moon:/home/juan/ForensicTests/NcNForense#

Como nos comenta el pdf se trata del dd (copia cruda, hablando mal y pronto) de una partición de tipo ext2.
Para asegurarnos de que tenemos el archivo correcto procesamos okin.dd con md5sum y lo comparamos con el valor que dice el pdf:

root@moon:/home/juan/ForensicTests/NcNForense# md5sum -b okin.dd
9c9a5e0d25dd57db10c99e84d9b03d48 *okin.dd
root@moon:/home/juan/ForensicTests/NcNForense#

Si no coincidiera estamos en problemas, habría que volver a descargar el archivo o probar descomprimiendo nuevamente okin.dd.bz2.

Entonces tenemos una partición en un archivo, en principio no podemos ver su contenido (archivos y directorios) porque se trata simplemente de un archivo mas en nuestro disco.
Pero al tener la certeza de que se trata de una partición, solo necesitamos decirle al sistema operativo que la trate como un dispositivo de bloques como cualquier otro. Para lograr esto usamos losetup, que nos permite asociar a un dispositivo de loop un archivo o un dispositivo de bloque, que en nuestro caso significa: nos permite emular un dispositivo de bloque a partir de nuestro archivo okin.dd.

juan@moon:~/ForensicTests/NcNForense$ losetup --all

Antes de crear un dispositivo hay que ver cuál de los loop devices no está en uso, e mi caso losetup --all no devuelve nada y por lo tanto puedo utilizar cualquiera de los loop.

juan@moon:~/ForensicTests/NcNForense$ ls /dev/loo*
loop0  loop1  loop2  loop3  loop4  loop5  loop6  loop7

Entonces utilzio loop1, y como se trata de evidencia forense, le indicamos a losetup que configure el loop device como SOLO lectura.

root@moon:/home/juan/ForensicTests/NcNForense# losetup -r /dev/loop1 okin.dd

Listamos nuevamente los dispositivos loop en uso y vemos ahora que loop1 está en uso con nuestro archivo.

root@moon:/home/juan/ForensicTests/NcNForense# losetup -a
/dev/loop1: [0801]:692806 (/home/juan/ForensicTests/NcNForense/okin.dd)

Podemos ver nuestro dispositivo con fdisk:

root@moon:/home/juan/ForensicTests/NcNForense# fdisk -l /dev/loop1

Disco /dev/loop1: 123 MB, 123379200 bytes
255 cabezas, 63 sectores/pista, 15 cilindros
Unidades = cilindros de 16065 * 512 = 8225280 bytes
Identificador de disco: 0x00000000

El disco /dev/loop1 no contiene una tabla de particiones válida

No tiene particiones válidas porque no se trata de un disco particionado, sino simplemente de una partición.
Ahora creamos un directorio donde montaremos nuestra partición para por fin poder ver qué contiene.

root@moon:/home/juan/ForensicTests/NcNForense# mkdir analisis

root@moon:/home/juan/ForensicTests/NcNForense# mount -o ro /dev/loop1 analisis/

Lo montamos como cualquier otro dispositivo de bloques, expecificando la opción de solo lectura, no es necesario especificar el tipo de partición ya que lo detecta automáticamente (aunque no estaría mal hacerlo).
Podemos ver que se montó correctamente mediante:

root@moon:/home/juan/ForensicTests/NcNForense# mount | grep loop1
/dev/loop1 on /home/juan/ForensicTests/NcNForense/analisis type ext2 (ro)
root@moon:/home/juan/ForensicTests/NcNForense#

Eso es todo por ahora, de aca en mas ya se puede recorrer la partición como lo hacemos normalmente. Para la próxima veremos el contenido, los archivos, sus fechas, etc, y ver cuánta información se puede obtener.