jueves, 22 de noviembre de 2012

VMware ESXi, máquinas virtuales y obtención de evidencias

Debido al auge de la virtualización es altamente probable que tarde o temprano una investigación forense tenga como sujeto objeto de análisis un sistema virtualizado. Y dado que actualmente VMware se lleva la palma en cuanto a implantación en el mercado empresarial es más que posible que el sistema virtualizado se ejecute sobre un hipervisor de dicha compañía. Pues bién, lo que viene a continuación son mis experiencias ante una situación hipotética como la que planteo: la adquisición de evidencias procedentes de máquinas virtuales ejecutándose en servidores ESXi. A lo largo de las siguientes líneas desarrollaré la configuración del escenario y todas las pruebas/aciertos/errores por los que he pasado hasta que, a mi juicio como lego en la materia, he dado con una metodología personal que considero bastante aceptable.

Sobra decir que no me hago responsable de los problemas que pueda ocasionar aceptar todo lo que detallo sin probar siquiera antes en un laboratorio las características concretas de cada escenario. Nótese, por otra parte, que el artículo no contempla la utilización de mapeo de discos físicos para ser utilizados por las máquinas virtuales como espacio de almacenamiento. Una vez establecida mi exención de responsabilidades y antes de continuar, al cesar lo que es del cesar, y por ello incluyo aquí las dos principales fuentes que he utilizado como referencia:

Ghost in the Machine - Forensic Evidence Collection in the Virtual Environment
How To - Digital Forensics Copying A VMware VMDK

Puedes simplemente leerlas y descartar el resto del artículo, o seguir leyendo y entretenerte tanto como me he divertido yo con la preparación del mismo, además de encontrar algunas alternativas que no se incluyen en ninguno de los enlaces anteriores y que creo pueden facilitarnos mucho la vida. Voy a intentar describir paso a paso todo el proceso, aunque en ocasiones esta descripción no sea muy exhaustiva; no obstante si tienes alguna duda y te interesa reproducirlo no tienes más que indicármelo y trataré de echarte una mano. Ahora, sin más preámbulos, vamos al lío :-)

VMware vSphere

Seguro que todos conocemos y/o hemos utilizado en alguna ocasión los hipervisores de nivel 2 o de "andar por casa". Estos no son más, ni tampoco menos, que aplicaciones que se ejecutan sobre el sistema operativo permitiendo correr diferentes maquinas virtuales. Algunos ejemplos: VMware Player, VMware Workstation, Oracle VM VirtualBox, qemu, etc.

Luego están los hipervisores "más serios", los de nivel 1, que son aquellos que se ejecutan directamente "sobre el metal", compuesto por el hardware del equipo, y que ofrecen mayores prestaciones como para ser tenidos en cuenta en entornos empresariales. El buque insignia de VMware es vSphere, cuyo hipervisor en versión free es totalmente funcional, solo que no ofrece muchas de las características más avanzadas. Pues bién, esta última es la versión que he utilizado para las pruebas, montado sobre un equipo con una única tarjeta de red debido a las restricciones en cuanto a compatibilidad de hardware de la criatura.

Una vez instalado ESXi 5.1.0 (vídeo detallado del proceso), configurados los parámetros de red (dirección IP estática 192.168.1.3) e introducida la licencia gratuita con la correspondiente merma de características respecto de la versión trial viene la configuración básica, entendiendo por tal:

  1. Instalación del cliente vSphere en el equipo del analista (o sea, mi equipo).
  2. Configuración de la sincronización horaria en el ESXi mediante el cliente vSphere (detalle del proceso).
  3. Habilitar el acceso remoto mediante SSH (detalle del proceso).

Ahora llegaría el momento de instalar la máquina virtual (en mi caso un Windows XP SP3) que supuestamente habría sido comprometida y por tanto sería objeto de análisis. No detallaré el proceso, tampoco he encontrado ningún enlace adecuado, pero básicamente bastaría con seleccionar el servidor ESXi en el cliente vSphere y seguir el asistente iniciado mediante la opción "Create a new virtual machine".

Congelando el estado del sistema

Una vez preparado el entorno de pruebas llega el momento de obtener las evidencias del sistema comprometido. El escenario más simple sería como el de mi laboratorio, donde sólo tenemos una máquina virtual ejecutándose sobre un servidor ESXi con un storage local. Pero desde luego ésto dista mucho de la realidad, donde lo normal sería encontrarnos decenas e incluso cientos de sistemas ejecutándose sobre el mismo hipervisor o un cluster de hipervisores con un almacenamiento gigantesco en una o varias SANs y con unas necesidades de alta disponibilidad críticas. ¿Qué hacer en estos casos?

Si nos olvidamos de que se trata de máquinas virtuales sabemos que tendremos que obtener al menos una copia del disco duro y otra de la memoria RAM del sistema comprometido, y para incidir lo menos posible en la ejecución del sistema objetivo y recordando nuevamente que se trata de máquinas virtuales, tenemos la opción de generar un snapshot. Un snapshot es básicamente una imagen estática del sistema objetivo en el momento de su generación. Ésto implica que el fichero que compone el disco duro del sistema virtual deja de recibir modificaciones, las cuales a partir de ese momento comenzarán a almacenarse en un fichero delta, permititiendo de esa forma en cualquier momento posterior revertir el estado del sistema al momento del snapshot. Nótese que el contenido de la memoria RAM también se congela, generándose un nuevo fichero inmutable mediante un dump de la misma para contener su estado. Más información sobre snapshots:

Understanding virtual machine snapshots in VMware ESXi and ESX
VMware Knowledge Base 1009402: Working with snapshots
How VMware snapshots work

Habitualmente antes de lanzar un snapshot tendríamos el fichero asociado al disco virtual nombremaquina-flat.vmdk con sus características definidas en nombremaquina.vmdk, siendo este último un fichero de texto. El nombre y ubicación del fichero correspondiente al disco se incluirían en el fichero de configuración de la máquina virtual. Para confirmar esta afirmación y desde una shell en el servidor ESXi obtenida mediante SSH primero obtendremos la ubicación de las máquinas virtuales:
# esxcfg-info -s | grep -i "volume name"
|----Volume Name...........................................datastore1

Otro comando para obtener el nombre del datastore bajo el cual se ejecutaría cada máquina virtual:
# vim-cmd vmsvc/getallvms

Ahora que conocemos la ubicación ya podemos consultar los ficheros de configuración:
# grep -i "filename.*vmdk" "/vmfs/volumes/datastore1/Windows XP/Windows XP.vmx"
ide0:0.fileName = "Windows XP.vmdk"
# grep "vmdk" "/vmfs/volumes/datastore1/Windows XP/Windows XP.vmdk"
RW 41943040 VMFS "Windows XP-flat.vmdk"

Una vez lanzado un snapshot seguiríamos teniendo los dos anteriores. Además, y para evitar su modificación, se crearán dos nuevos ficheros: nombremaquina-000001-delta.vmdk como nuevo disco virtual para almacenar los cambios desde el snapshot y nombremaquina-000001.vmdk, y se modificará el fichero de configuración de la máquina virtual para reflejar la nueva situación:
# grep -i "fileName.*vmdk" "/vmfs/volumes/datastore1/Windows XP/Windows XP.vmx"
ide0:0.fileName = "Windows XP-000001.vmdk"
# grep "vmdk" "/vmfs/volumes/datastore1/Windows XP/Windows XP-000001.vmdk"
parentFileNameHint="Windows XP.vmdk"
RW 41943040 VMFSSPARSE "Windows XP-000001-delta.vmdk"

Por último, y en cuanto a lo que nos atañe, también se volcará el espacio de direcciones de la memoria RAM asignado a la máquina virtual en el fichero nombremaquina-Snapshot1.vmsn

Así que como primer paso tendríamos que generar un snapshot y la forma más fácil de hacerlo es a través del cliente vSphere seleccionando la máquina virtual adecuada y pulsando el botón derecho del ratón Snapshot, Take snapshot. Es importante recalcar que para seguir el proceso desarrollado en este artículo es imprescindible no disponer previamente de ningún snapshot; en el caso de existir uno o varios tendríamos que eliminarlos o consolidarlos.

Como queremos incidir lo menos posible en el estado del sistema para obtener una evidencia lo más fidedigna posible deberemos asegurarnos de dejar las opciones por defecto, además de lanzarlo en un momento en que no haya mucha carga sobre la máquina virtual.


ESXi y los tipos de discos virtuales

Llega el momento de obtener una copia de las evidencias previamente generadas mediante el snapshot, pero antes nos detendremos en el concepto de discos thin y thick provisioned.

Cuando generamos una máquina virtual en un servidor ESXi tenemos la posibilidad de elegir entre discos thin o thick. La diferencia entre ambos es que el primero se crea sólo con el tamaño inicial estrictamente necesario y va creciendo conforme se van almacenando datos en él hasta alcanzar, como máximo, el espacio establecido al crearlo. Esta característica permite sobreutilizar el espacio de almacenamiento disponible en lugar de tener que reservarlo de antemano y constituye una de las principales ventajas de trabajar con máquinas virtuales. Cuando se hace una petición de lectura para un bloque no utilizado el sistema de ficheros VMFS se encarga de devolver ceros.

Por el contrario los discos thick precisan disponer del total del espacio cuando son creados, de forma que éste queda reservado. A su vez dentro de los discos thick tenemos dos subtipos más:
  • LazyZeroedThick: este es el tipo por defecto y, a pesar de precisar del espacio total disponible en el dispositivo de almacenamiento dicho espacio no queda ocupado hasta que no resulta necesario.

  • EagerZeroedThick: en este tipo de discos el espacio total queda reservado y sobreescrito con ceros, de forma que el proceso de creación es más lento pero la velocidad de escritura de datos es mayor.

Nótese que el disco virtual siempre se creará como EagerZeroedThick independientemente de las opciones especificadas durante su creación si no se elige el formateo rápido del sistema de ficheros durante el particionado del disco al instalar una máquina virtual con un sistema operativo Microsoft.

Using thin provisioned disks with virtual machines
Thin Provisioning – What’s the scoop?

El disco de la máquina virtual generado para el ejemplo es thin provisioned. Nótese la diferencia entre el resultado de la ejecución de los siguientes comandos:
# ls -l "Windows XP-flat.vmdk"
-rw------- 1 root root 21474836480 Nov 8 11:21 Windows XP-flat.vmdk


# du "Windows XP-flat.vmdk"
1873920 Windows XP-flat.vmdk

Y para los servidores ESXi disponemos del comando stat:
# stat "Windows XP-flat.vmdk"
File: Windows XP-flat.vmdk
Size: 21474836480 Blocks: 3747840 IO Block: 131072 regular file
Device: f7b4079747314280h/17848899569491985024d Inode: 16796484 Links: 1
Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2012-11-08 11:13:25.000000000
Modify: 2012-11-08 11:21:15.000000000
Change: 2012-11-08 11:07:43.000000000

El campo size nos indica el tamaño máximo del disco en bytes; el campo blocks nos indica el número de bloques utilizados hasta el momento. De esta forma, y suponiendo que habitualmente el tamaño de bloque es igual a 512 habríamos ocupado 3747840 * 512 = 1918894080 bytes de los 21474836480 disponibles:
# echo "Max: $((`stat -c "%s"  "Windows XP-flat.vmdk"` / 1024))K \
- Size: $((`stat -c "%b * %B" "Windows XP-flat.vmdk"` / 1024))K"
Max: 20971520K - Size: 1873920K

Esta distinción en cuanto a los tipos de discos existentes es muy importante a la hora de adquirir las evidencias, dado que puede ser una ventaja si el disco se ha creado como thin permitiéndonos ahorrar espacio en el destino así como acelerar el proceso de copia al tener que trabajar con muchos menos datos. Pero para poder aprovecharnos de dicha característica, y esto es imprescindible, el sistema de ficheros del dispositivo de destino debe ser VMFS. En caso contrario obtendremos un disco con el tamaño total cuyos bloques no ocupados contendrán ceros.

Podemos comprobarlo utilizando Veeam FastSCP (actualmente integrado dentro de Veeam Backup) o directamente mediante la interfaz de exploración del datastore del cliente vSphere: seleccionado el servidor ESXi, pestaña Configuration, Storage, seleccionar datastore adecuado, botón derecho Browse Datastore y allí seleccionar fichero correspondiente al disco virtual, botón derecho Download. Una vez descargado el fichero utilizado para el ejemplo comprobaremos como su suma md5 coincidirá con la calculada en el servidor tras crear el snapshot pero su tamaño será el espacio total indicado durante la creación de la máquina virtual.

Por lo tanto en nuestro caso, para realizar el proceso de adquisición, crearemos un ISCSi target que conectaremos al ESXi para generar un nuevo datastore y poder copiar allí la evidencias, incluyendo el disco virtual thin provisioned.

Instalando y configurando un ISCSI target en Ubuntu

En lugar de exponer un disco fisico como almacenamiento voy a utilizar un fichero generado utilizando dd cuyo tamaño voy a preubicar, algo así como EagerZeroedThick :-)
# dd if=/dev/zero of=/mnt/casos/vmfs.img bs=1024k count=8000
8000+0 registros leídos
8000+0 registros escritos
8388608000 bytes (8,4 GB) copiados, 217,871 s, 38,5 MB/s

La instalación del ISCSi target en Ubuntu 12.04 me ha dado algún que otro problema de dependencias, pero al final los he resuelto realizando los siguientes pasos en el orden exacto en que los indico:
# apt-get update
# apt-get install -y linux-source build-essential
# cd /usr/src/
# ln -s linux-source-3.2.0 linux
# apt-get install -y linux-headers-`uname -r`
# apt-get -y install iscsitarget-dkms
# apt-get -y install iscsitarget

Ahora llega el momento de configurar los paquetes. Para el ejemplo no se ha configurado autentificación usuario/contraseña para la conexión del iscsitarget aunque sería lo más recomendable.

Lo primero habilitar el iscsitarget:
# sed -i "s/false/true/" /etc/default/iscsitarget

y definir la LUN compartida, en mi caso el fichero creado previamente con dd, tras lo que reiniciaremos el servicio para aplicar la nueva configuración:
# echo "Target iqn.2012-11.local.collector:storage.lun1" >> /etc/iet/ietd.conf
# echo " Lun 0 Path=/mnt/casos/vmfs.img,Type=fileio" >> /etc/iet/ietd.conf
# echo " Alias LUN1" >> /etc/iet/ietd.conf
# service iscsitarget restart

Tambien podemos modificar las opciones del fichero /etc/iet/initiators.allow para indicar exáctamente qué equipos/redes tienen permitido el acceso al iscsitarget; por defecto se permite la conexión a todos (ALL : ALL).

Para comprobar que funciona correctamente:
# apt-get install open-iscsi
# iscsiadm -m discovery -t st -p 192.168.1.9
192.168.1.9:3260,1 iqn.2012-11.local.collector:storage.lun1

Ahora llega el momento de establecer la conexión desde el servidor ESXi al iscsitarget. La configuración de red para las pruebas que he realizado es la más sencilla de las posibles:


En este escenario dentro del ESXi sólo hay definido un vSwitch sobre una única tarjeta de red que se utiliza tanto para dotar de conectividad a las máquinas virtuales como para permitir las administración del servidor y, a partir de este momento, conectar mediante ISCSI con el nuevo storage para almacenar las evidencias. Para configuraciones más complejas o simplemente con el fín de aprender más recomiendo consultar la guía "vSphere Networking".

Para no alargar innecesariamente el artículo he generado un PDF con capturas de pantalla de los pasos a dar para agregar un nuevo adaptador iSCSI, conectarlo al target configurado en la máquina Ubuntu y generar un datastore para poder almacenar allí los ficheros necesarios.

Copiando las evidencias

Clonaremos ahora el disco thin provisioned obtenido como resultado del snapshot del sistema comprometido en el nuevo datastore desde una sesión SSH en el servidor ESXi:
# vmkfstools -i "/vmfs/volumes/datastore1/Windows XP/Windows XP.vmdk" \
-d thin "/vmfs/volumes/evidencias/Windows XP.vmdk"
Destination disk format: VMFS thin-provisioned
Cloning disk '/vmfs/volumes/datastore1/Windows XP/Windows XP.vmdk'...
Clone: 100% done.

Una vez finalizado el proceso comprobaremos que ambos ficheros tienen el mismo tamaño y generaremos la suma MD5 para confirmar que son idénticos:
# du "/vmfs/volumes/datastore1/Windows XP/Windows XP-flat.vmdk"
1873920 /vmfs/volumes/datastore1/Windows XP/Windows XP-flat.vmdk
# du "/vmfs/volumes/evidencias/Windows XP-flat.vmdk"
1873920 /vmfs/volumes/evidencias/Windows XP-flat.vmdk

# openssl dgst -md5 "/vmfs/volumes/datastore1/Windows XP/Windows XP-flat.vmdk"
MD5(/vmfs/volumes/datastore1/Windows XP/Windows XP-flat.vmdk)= 72af25242d8abf5ae8183d8fbab22925
# openssl dgst -md5 "/vmfs/volumes/evidencias/Windows XP-flat.vmdk"
MD5(/vmfs/volumes/evidencias/Windows XP-flat.vmdk)= 72af25242d8abf5ae8183d8fbab22925

En este caso he utilizado md5, lo cual no es lo más recomendable a día de hoy. Para conocer los algoritmos de resumen soportados por openssl así como todas las opciones puede consultarse la manpage del comando.

Sólo restaría hacer una copia del estado de la memoria en el momento del snapshot y generar las sumas de comprobación:
# cp "/vmfs/volumes/datastore1/Windows XP/Windows\ XP-Snapshot1.vmsn" /vmfs/volumes/evidencias/
# openssl dgst -md5 "/vmfs/volumes/datastore1/Windows XP/Windows XP-Snapshot1.vmsn"
MD5(/vmfs/volumes/datastore1/Windows XP/Windows XP-Snapshot1.vmsn)= bc91023b458d5103aa97bf3b265572cc
# openssl dgst -md5 "/vmfs/volumes/evidencias/Windows XP-Snapshot1.vmsn"
MD5(/vmfs/volumes/evidencias/Windows XP-Snapshot1.vmsn)= bc91023b458d5103aa97bf3b265572cc

En último lugar habría que desmontar el datastore y desconectar el iscsitarget para dejarlo todo como estaba. Incluyo aquí un PDF con el proceso detallado mediante capturas de pantalla. También detendremos y deshabilitaremos el servicio iscsitarget en Ubuntu:
# service iscsitarget stop
# sed -i "s/true/false/" /etc/default/iscsitarget

Ahora ya tenemos los ficheros en nuestra máquina pero, ¿como accedemos a un sistema de ficheros VMFS para analizar el contenido?

Accediendo a vmfs desde Ubuntu

La respuesta viene de la mano de Mike Hommey y las vmfs-tools, un set de herramientas que permite el acceso al sistema de ficheros VMFS apoyándose en el módulo de FUSE. El paquete está disponible desde los repositorios de Ubuntu, pero para garantizar la disponibilidad de las últimas funcionalidades, entre las que se encuentra el soporte de VMFS-5, descargaremos las fuentes desde el repositorio git:
# apt-get -y install git
# cd /usr/local
# git clone https://github.com/glandium/vmfs-tools.git

Ahora compilamos e instalamos, satisfaciendo en primer lugar todas las dependencias:
# cd vmfs-tools/
# apt-get -y install uuid-dev pkg-config libfuse-dev asciidoc xsltproc docbook
# ./configure
# make
# make install

Una vez correctamente finalizado el proceso anterior llega el momento de acceder a las evidencias montando el "disco" en formato vmfs. Para ello he seguido los pasos indicados en el comentario final del siguiente enlace, Announcing vmfs-tools version 0.1.0. Básicamente los pasos serían:
# apt-get -y install kpartx
# losetup -r /dev/loop0 /mnt/casos/vmfs.img
# kpartx -a -v /dev/loop0
add map loop0p1 (252:0): 0 16368187 linear /dev/loop0 2048
# mkdir /mnt/temp
# vmfs-fuse /dev/mapper/loop0p1 /mnt/temp
VMFS: Warning: Lun ID mismatch on /dev/mapper/loop0p1
ioctl: Invalid argument
ioctl: Invalid argument
# mount | grep temp
/dev/fuse on /mnt/temp type fuse (rw,nosuid,nodev,default_permissions)
# ls -l /mnt/temp/
total 2404544
-rw------- 1 root root 21474836480 nov 10 14:26 Windows XP-flat.vmdk
-rw------- 1 root root 542290920 nov 10 15:01 Windows XP-Snapshot1.vmsn
# du -h /mnt/temp/*
1,8G /mnt/temp/Windows XP-flat.vmdk
518M /mnt/temp/Windows XP-Snapshot1.vmsn

Y podemos volver a comprobar las sumas md5 para confirmar que no han sido modificadas durante el proceso:
# md5sum /mnt/temp/*-flat.vmdk /mnt/temp/*.vmsn
72af25242d8abf5ae8183d8fbab22925 /mnt/temp/Windows XP-flat.vmdk
bc91023b458d5103aa97bf3b265572cc /mnt/temp/Windows XP-Snapshot1.vmsn

Cuando terminemos de trabajar con el sistema de ficheros VMFS y para dejarlo todo como estaba:
# umount /mnt/temp
# kpartx -d -v /dev/loop0
del devmap : loop0p1
# losetup -d /dev/loop0

Para analizar el disco vmdk podemos utilizar las herramientas del sleuthkit directamente sobre el sistema de ficheros montado. Importante recalcar que éstas deben haberse compilado con soporte para ficheros en formato afflib, pero esto lo dejaremos para otra ocasión :-)

Recalcar de nuevo que si copiamos el disco vmdk thin provisioned a cualquier sistema de ficheros distinto de vmfs nos ocupará el tamaño máximo establecido.

Despedida y cierre

Seguro que por desconocimiento he cometido algún error. Si éste fuera el caso agradecería vuestros comentarios o sugerencias para subsanarlos. Por último, y si habéis llegado hasta aquí, os agradezco la deferencia y espero os hayáis entretenido tanto como lo he hecho yo durante la configuración del escenario y todas las pruebas necesarias para escribir estas líneas.

Enlaces de interés

VMware vSphere 5.1 Documentation Center
A handful of ESXi tips and tricks
Configuring advanced options for ESX/ESXi
VMDK virtual disk type
vSphere Command-Line Interface Reference
VMware ESXi SSH CLI commands
Linux / UNIX: Create Large 1GB Binary Image File With dd Command
Ubuntu 12.04 with iSCSI target for VMware ESXi 4.1
iSCSI target on Ubuntu
Regular vmdks
Snapshots or Redologs
vmfs
Virtual Machine Files Essential to Forensic Investigations
Howto read VMFS 3 with a Linux LiveCD

En breve más, y mejor, espero ;-)

3 comentarios:

Anónimo dijo...

Excelente Neo, el tiempo que llevo leyendo tu blog he aprendido mucho, muchisimas gracias por tus articulos donde nos muestras paso a paso todo.

Saludos y exitos!!

neofito dijo...

¡Gracias a ti, me alegra saber que lo que escribo pueda servirle a alguien!

Saludos

Trojan Solutions dijo...

Gracias por la explicación tan buena que has hecho. Trabajo en una empresa de mantenimiento informatico y este post me ha resultado muy util.