sábado, 26 de abril de 2014

A brief and real malware story

Esta historia (real por sobre todas las cosas), sucedió hace ya algo mas de un año e involucro a un webserver productivo de una ONG Argentina a la cual en la empresa en la que trabajo, le hacemos mantenimiento de sistemas e infraestructura. El desencadenante del siguiente procedimiento, fue un llamado telefónico por parte del cliente, manifestando que el webserver eventualmente andaba lento, y había que determinar cual era el origen de este problema. Luego de atender los tickets previamente asignados me puse a trabajar en el caso, logueandome de manera remota al equipo (que se encontraba en un conocido datacenter de Argentina), y tras ejecutar las herramientas típicas de detección de problemas de performance y/o observación (vmstat para inspeccionar la memoria virtual, iostat para inspeccionar el IO y mpstat para inspeccionar CPU) comienzo a revisar los logs del sistema operativo, un CentOS 6.2 x86_64, en este caso. Y tras ejecutar el comando dmesg (encargado de loguear los mensajes del booteo, como así también del kernel) me encuentro con lo siguiente:

sábado, 27 de octubre de 2012

VMWare Server: Adding a VNC server without web console.



Una de las plataformas de virtualización con mayor aceptación en el mercado actualmente es VMWare, en sus versiones enterprise tales como ESX/ESXi o en su versión gratuita (apta para PoC, o uso hogareño), VMWare Server. Quienes me conocen, saben que no tengo demasiada simpatía con este producto, lo cual hace que mi interés en el mismo no sea mas allá que instalarlo en algún server, crear máquinas virtuales y hacer alguna que otra tarea administrativa con el, pero no más.

Esta terrorífica historia que hoy les traigo, me sucedió hace algunos meses en un servidor productivo, que utilizaba VMWare Server. El equipo se había caído, y por algún motivo extraño la interfaz web no levantaba. Siguiendo la Ley de Murphy: "Si algo puede salir mal, lo hará..."
Una de las VM's no había levantado correctamente y no tenía forma alguna de conectarme a ella para ver por qué no booteaba el sistema operativo, así que buscando en Google, encontré esto:

lunes, 22 de octubre de 2012

Linux x86: Adjacent Memory Overflows

Durante los días 18 y 19 de Octubre de 2012, tuve el placer de viajar y presentarme como disertante a la 8.8 Security Conference en la hermosa ciudad de Santiago de Chile.

Durante mi conferencia sobre "Buffer Overflow for fun and pr0fit", luego de la larga y aburrida introducción teórica hice algunas demostraciones prácticas de explotación de binarios, bypasseo de protecciones y "adjacent memory corruption explotation" en la cual esta última falló, quizá por la presión de hacerlo en vivo, nervios o lo que sea, falló. Entonces me gustaría a través de este post hacer un repaso de este último tópico que me hubiera encantado haberlo compartido en vivo durante mi charla.

sábado, 30 de junio de 2012

Linux/KVM: Growing filesystem on a LVM based virtual disk.

Cuando se utiliza virtualización, las capacidades de flexibilización del storage son enormes, es por ello existen diferentes formas de manejar el almacenamiento utilizando KVM como hypervisor.
Una de ellas es utilizar filedisks, con los cuales, cada uno de ellos emula un disco físico en la VM y los filesystems son armados ahí mismo.
Otra forma es mediante LVM dedicando uno o varios LV a uso exclusivo de la VM.
Esta última forma, optimiza el I/O debido a que se evita pasar por una capa intermedia de abstracción: "un archivo", a fin de escribir los bloques de datos a disco. De esta manera las operaciones de I/O son manejadas directamente por el Device Mapper (LVM), y se evita caer en capas de abstracción intermediarias.
Este caso era sencillo, un servidor de correos en CentOS 5.6, bajo "Zimbra", el cual tiene un disco basado en un LV (vdb1), que monta en /opt, directorio utilizado por Zimbra para mantener todos sus datos, el cual se había quedado sin espacio.

sábado, 23 de junio de 2012

Solaris: SVM deployment and ZFS migration with minimun downtime

Hace muy pocos días, compré un viejo, pero en excelente estado, servidor Sun Fire 280R. El equipo cuenta con algunos features más que interesantes, equipado con dos procesadores UltraSPARC64 III, 2 Gb. de RAM, RSC card, fuentes de alimentación redundantes, lector de DVD-R y dos discos SCSI de 36 Gb cada uno.
Al momento de bootearlo por primera vez, me encontré con Solaris 10 5/08 instalado, y prácticamente sin uso. Por lo cual no hacía reinstalar el sistema operativo. Había un solo tema negativo en esta configuración por default, el layout de particionamiento de los discos y asignación filesystems no me gustaba. En uno de los discos estaba el sistema operativo, el /export/home, en otro utilizando ZFS cree un zpool donde instalé una zona que no quería volver a reinstalar.

sábado, 16 de junio de 2012

P2V migration: from Solaris 9 server to Solaris 10 branded zone.



Hace poco tiempo atrás, participe en un proyecto en el cual se me asigno la tarea de migrar un obsoleto equipo en Solaris 9, junto a sus aplicaciones, a un nuevo Sun Enterprise M3000 con Solaris 10.
El proceso es en si sencillo y brinda una flexibilidad enorme al hacer este tipo de migraciones que cada vez se vuelven mas frecuentes en datacenters del mundo.
La idea principal es disminuir la cantidad de hardware necesario y el espacio ocupado por este en los datacenters, como así también aprovechar las ventajas que provee la posibilidad de utilizar zonas para disminuir costos, como así también reducir el punto de falla de equipos, debido a que tarde o temprano, esto debería ser migrado ya que en estos tiempos Solaris 9 a quedado obsoleto en el mercado.

jueves, 17 de mayo de 2012

Solaris: Connecting to iSCSI targets



iSCSI es un protocolo que permite enviar comandos SCSI mediante tramas ethernet, el cual se utiliza en Storage Area Networks a fin de flexibilizar las soluciones de storage que existen hoy en día.

iSCSI, se compone básicamente de dos tipos de tecnologías, iniciadores (clientes), y targets, los cuales son aquellos equipos que están sirviendo unidades de disco (LUN's), para que los iniciadores las monten como si se trataran de discos físicamente conectados al equipo cliente.
iSCSI suele utilizarse por regla general en redes separadas a las de datos, por cuestiones de performance sobre todas las cosas, pero como bien sabemos, iSCSI hace uso del stack TCP/IP, y este tiene una limitación bastante común, el MTU que por default es 1500 bytes, a fin de sobrellevar este primer inconveniente, muchas redes iSCSI utilizan Jumbro frames, estos son paquetes especiales en los cuales el MTU a sido alterado, incrementando el tamaño de su payload, por ejemplo 9000 bytes, que es el tamaño más común para un Jumbo frame.
La utilización de Jumbo frames, requiere que las interfaces de red de ambos lados, tanto el iniciador, como el cliente, tengan con mismo valor de MTU configurados.

miércoles, 16 de mayo de 2012

Solaris: Adaptative Replacement Cache and ZFS memory leak



Hace unos días acudí a un cliente el cual decía que sus servidores con Solaris 10 08/11 estaban consumiendo memoria de una manera excesiva (un total de 8 GB. de RAM física). La situación se producía en un grupo de dos servidores que utilizaban ZFS para montar unos Containers, mientras que en aquellos que cumplían la misma función pero no utilizaban ZFS, esto no se producía. Así que comenzando a destripar el alien, hice uso de unas de las fantásticas herramientas que Solaris provee para esto, mdb.

sábado, 12 de mayo de 2012

POSIX: System-V Executable and Linkeable Format (ELF) and the Linux ABI

ELF son las siglas en inglés de Executable and Linkeable Format, y es el formato de archivo utilizado por los file objects (.o), binarios, librerías y coredumps en Linux y en Unix en general.
El principio de todo proceso, define al mismo como un archivo en un dispositivo de almacenamiento, que una vez compilado y al ser ejecutado, es cargado en memoria para que el scheduler (mediante el sistema operativo), le asigne tiempo de CPU y recursos a fin de poder ejecutar las rutinas definidas en el.
Este archivo, ya convertido en binario, se encuentra escrito en algunos de los cientos lenguajes de programación que existen actualmente, por ejemplo ANSI C o Fortran. Cuando fue compilado, el compilador en un momento determinado ejecuto el linker, y definió en un header todas aquellas librerías que el programa necesita para poder ejecutarse y que estás les provean aquellas funciones y procedimientos que utilice.
Un binario, puede ser compilado de dos formas, una es estática y la otra dinámica. Compilar un binario de manera estática (parámetro -Bstatic en gcc(2)), significa que se incluirán en el mismo binario todas aquellas librerías que el programa requiera. Por su parte, la principal idea de las librerías compartidas, es tener una sola copia de las mismas instaladas en el sistema operativo y que todo aquel programa que las necesite, haga uso de ellas, y las cargue en memoria para ejecución, en segmentos que pueden ser mapeados de manera privada para el proceso, o compartido entre varios procesos/threads.

Los procesos en Unix, nacen de alguna de las variantes de la syscall fork(2). fork(2), bifurca el proceso padre en una nueva imagen del proceso (una nueva entrada en la estructura proc_t), y mediante exec(2) desplaza esta imagen para crear el mapeo y la estructuras en memoria para el nuevo proceso ejecutado.
Una vez realizado el exec del proceso, y si este está compilado de manera dinámica, en invocado el runtime linker, en este caso ld.so.1,

sábado, 5 de mayo de 2012

POSIX: INT_MAX, INT_MIN and SIGFPE

En sistemas operativos modernos, los límites de direccionamiento de memoria y cantidad de procesos/threads está estipulada de dos formas: la primera acorde al hardware específico con que cuenta el equipo, y la segunda, mediante configuración específica del sistema operativo.

A modo de ejemplo, y para dejar las cosas más en claro, vamos a hablar un poco sobre los límites de los procesos: Cada proceso en el sistema operativo ocupa un slot en una estructura de datos denominada kernel process table. Esta tabla contiene toda la información necesaria que el kernel mantiene a fin de poder manejar los procesos, schedulear las distintas tareas (acorde a sus prioridades) y estados de los mismos. Cuando el OS bootea, el kernel inicializa una estructura de datos denominada process_cache, donde comenzará a direccionar la estructura de procesos que luego serán empleada por el kernel y el userspace. Esta tabla es una lista doblemente enlazada con dos punteros, uno a su elemento anterior y otro a su elemento posterior, la cual tiene una capacidad máxima que se define acorde a la cantidad de memoria física instalada en el equipo. El sistema operativo, para esto asigna la cantidad de memoria instalada a una variable MAX_MAXUSERS (que no tiene nada que ver con el número máximo de usuarios que el sistema soporta), que luego será utilizada por dos variables más del propio kernel max_nprocs y maxuprc. max_nprocs define el número máximo de procesos del sistema operativo, y maxuprc determina el número máximo de procesos que usuarios no privilegiados (que no sean root), puedan crear y ocupar slots en la kernel process table. Y basándose en el valor de MAX_MAXUSERS, poder definir el tamaño en memoria de cada segmento del proceso (región .text, .stack, .heap, .bss, etc.).