Gentoo Logo

Utilidades Pax para Gentoo

Contenido:

1.  ¿De qué trata esta guía?

Introducción

La seguridad de un sistema es más que configurar decentemente un cortafuegos y los servicios del mismo. Los binarios que se ejecutan y las librerías que se cargan pueden ser también vulnerables a los ataques. Aunque las vulnerabilidades exactas no se conocen hasta que son descubiertas, hay algunas formas de evitar que ocurran.

Un vector posible de ataque es escribir y ejecutar segmentos en un programa o librería, permitiendo a usuarios maliciosos ejecutar su código a través de un aplicación o librería vulnerable.

Esta guía le informará acerca de cómo usar el paquete pax-utils para encontrar e identificar binarios problemáticos. También hablaremos del uso de pspax (una herramienta para ver las capacidades específicas de PaX) y de dumpelf (una herramienta que muestra una estructura C conteniendo una copia funcional de un objeto dado).

Pero antes de empezar con esto, daremos alguna información sobre objetos. Los usuarios familiarizados con los segmentos y el enlazado dinámico no aprenderán nada en la siguiente sección y pueden continuar con la sección Extraer información ELF de los binarios.

Objetos ELF

Todos los binarios ejecutables de su sistema están estructurados de una forma determinada, permitiendo al núcleo Linux cargar y ejecutar el fichero. Realmente esto se aplica a más objetos que los binarios ejecutables planos: esto también sirve para los objetos compartidos, hablaremos de esto más adelante.

La estructura de estos binarios se define en el estándar ELF. El acrónimo ELF significa Formato Ejecutable y Enlazable. Si está interesado en los detalles internos, eche un vistazo a la Especificación Genérica de ELF o a la página del manual elf(5).

Un ejecutable ELF consta de las siguientes partes:

  • La cabecera ELF contiene información del tipo de fichero (si es un ejecutable, una librería compartida,...), la arquitectura destino, la localización en el fichero de la Cabecera del Programa, Cabecera de Sección y de la Cabecera de las Cadenas de Texto así como la localización de la primera instrucción ejecutable.
  • La Cabecera del Programa informa al sistema acerca de cómo debe crear un proceso desde el fichero binario. Realmente se trata de una tabla que contiene entradas para cada segmento del programa. Cada entrada contiene el tipo, direcciones (físicas y virtuales), tamaño, derechos de acceso,...
  • La Cabecera de Sección es una tabla que contiene una entrada para cada sección en el programa. Cada una de estas entradas contiene el nombre, tipo, tamaño,... así como la información que contiene la sección.
  • Datos, conteniendo las secciones y segmentos mencionados arriba.

Una sección es una pequeña unidad que contiene datos específicos: instrucciones, datos variables, tabla de símbolos, información de relocalización y demás. Un segmento es una colección de secciones. Los segmentos son unidades que son transferidas a la memoria.

Objetos compartidos

Antiguamente, las aplicaciones binarias contenían todo lo que necesitaban para operar de forma correcta. Estos binarios se denominaban binarios enlazados estáticamente. Éstos consumían mucho espacio debido a que las aplicaciones utilizaban las mismas funciones una y otra vez.

Un objeto compartido contiene la definición e instrucciones para esas funciones. Cada aplicación que las necesita puede enlazar dinámicamente este objeto compartido de forma que puede beneficiarse de la funcionalidad ya existente.

Una aplicación que está enlazada dinámicamente con un objeto compartido contiene símbolos, referencias a la funcionalidad real. Cuando se carga esta aplicación en memoria, en primer lugar pedirá la enlazador dinámico que resuelva todos y cada uno de los símbolos que tiene definidos. El enlazador dinámico cargará el objeto compartido apropiado en memoria y resolverá las referencias simbólicas entre ellos.

Segmentos y secciones

El modo en que se revisa el fichero ELF, depende de la vista que tengamos del mismo: cuando estamos tratando con un fichero binario en Vista de Ejecución, el fichero ELF contiene segmentos. Cuando el fichero está en Vista de Enlazado, el fichero contiene secciones. Un segmento se extiende una o más secciones (continuas).

2.  Extraer información ELF de los binarios

La aplicación scanelf

La aplicación scanelf es parte del paquete app-misc/pax-utils. Con esta aplicación se puede mostrar información específica de la estructura del binario ELF. La siguiente tabla resume las distintas opciones.

Opción Opción larga Descripción
-p --path Escanea todos los directorios en el entorno PATH
-l --ldpath Escanea todos los directorios en /etc/ld.so.conf
-R --recursive Escanea los directorios de forma recursiva
-m --mount No salirse de los puntos de montaje cuando se escanee de forma recursiva
-y --symlink No escanear enlaces simbólicos
-A --archives Escanear archivos (ficheros .a)
-L --ldcache Utiliza la información de ld.so.cache (usar con -r/-n)
-X --fix Intentar corregir aquello que vaya 'mal' (usar con -r/-e)
-z [arg] --setpax [arg] Ajustar EI_PAX/PT_PAX_FLAGS a [arg] (usar con -Xx)
Opción Opción larga Descripción
-x --pax Imprimir marcas PaX
-e --header Imprimir marcas GNU_STACK/PT_LOAD
-t --textrel Imprimir información TEXTREL
-r --rpath Imprimir información RPATH
-n --needed Imprimir la información NEEDED
-i --interp Imprimir información INTERP
-b --bind Imprimir información BIND
-S --soname Imprimir información SONAME
-s [arg] --symbol [arg] Buscar el símbolo especificado
-k [arg] --section [arg] Encontrar la sección especificada
-N [arg] --lib [arg] Encontrar la librería especificada
-g --gmatch Usar strncmp para cotejar librerías (usar con -N)
-T --textrels Localizar la causa de TEXTREL
-E [arg] --etype [arg] Imprimir solo aquéllos ficheros ELF que coinciden con ET_DYN, ET_EXEC ...
-M [arg] --bits [arg] Imprimir solo los ficheros que coinciden con los bits numéricos indicados
-a --all Imprime toda la información escaneada (-x -e -t -r -b)
Opción Opción larga Descripción
-q --quiet Solo muestra aquello que va 'mal'
-v --verbose Salida ampliada (se puede especificar más de una vez)
-F [arg] --format [arg] Usar un formato específico para la salida
-f [arg] --from [arg] Leer la entrada desde un fichero
-o [arg] --file [arg] Escribir la salida a un fichero
-B --nobanner No mostrar la cabecera
-h --help Imprimir esta ayuda y salir
-V --version Imprimir la versión y salir

Los especificadores de formato para la opción -F se muestran en la siguiente tabla. Anteponga un carácter % (salida ampliada) o # (salida silenciosa) a cada especificador a su antojo.

Especificador Nombre completo Especificador Nombre completo
F Nombre de fichero x Ajustes PaX
e STACK/RELRO t TEXTREL
r RPATH n NEEDED
i INTERP b BIND
s Símbolo N Librería
o Tipo p Nombre del fichero
f Base del nombre del fichero k Sección
a ARCH/e_machine    

Usar scanelf para relocalizaciones de texto

Como ejemplo, usaremos scanelf para encontrar binarios que contienen relocalizaciones de texto.

Una relocalización es una operación que sobreescribe una dirección en un segmento que se ha cargado. Esta sobreescritura de la dirección puede ocurrir cuando un segmento referencia a un objeto compartido y ese objeto compartido está cargado en memoria. En este caso, las referencias se substituyen con los valores reales de la dirección. Pueden ocurrir eventos similares dentro del propio objeto compartido.

Una relocalización de texto es una relocalización en el segmento de texto. Ya que estos segmentos contienen código ejecutable, los administradores del sistema puede que deseen que no se pueda escribir en estos segmentos. Esto es perfectamente posible, sin embargo, ya que estas relocalizaciones de texto realmente escriben el segmento de texto, esto no es siempre viable.

Si quiere eliminar las relocalizaciones de texto, necesitará asegurarse de que la aplicación y el objeto compartido se han construido con Código Independiente de la Posición (PIC), haciendo obsoletas las referencias. Ésto no solo incrementa la seguridad, también incrementa el rendimiento para el caso de objetos compartidos (para permitir la escritura en el segmento de texto, se requiere reservar un espacio de intercambio y una copia privada del objeto compartido para cada aplicación que lo utilice).

El siguiente ejemplo busca binarios ELF que contengan una relocalización de texto en sus rutas de librería de forma recursiva, y siempre en el sistema de ficheros montado, ignorando los enlaces simbólicos.

Listado de Código 2.1: Escanea el sistema para buscar binarios con relocalizaciones de texto

# scanelf -lqtmyR

Si quiere escanear su sistema completo para buscar cualquier fichero que contenga relocalizaciones de texto:

Listado de Código 2.2: Escanea el sistema completo para buscar ficheros con relocalizaciones de texto

# scanelf -qtmyR /

Usar scanelf para cabeceras específicas

La utilidad scanelf se puede usar para identificar rápidamente ficheros que contienen una cabecera de sección dada usando la opción -k .section.

En este ejemplo buscamos recursivamente todos los ficheros en /usr/lib/debug que han sido recortados usando un modificador de formato con el modo silencioso habilitado. Un fichero elf recortado no posee la entrada .symtab, por lo que usamos el carácter '!' para invertir la lógica.

Listado de Código 2.3: Escanea en busca de ejecutables recortados o no

# scanelf -k '!.symtab' /usr/lib/debug -Rq -F%F#k

Usando scanelf para buscar marcas de segmento específicas

Cada segmento tiene definiciones específicas en la cabecera del programa binario. Una de estas definiciones es el tipo de segmento. Algunos valores interesantes son: PT_LOAD (el segmento debe cargarse en memoria desde el fichero), PT_DYNAMIC (el segmento contiene información de enlace dinámico), PT_INTERP (el segmento contiene el nombre del intérprete de programa), PT_GNU_STACK (una extensión GNU para el formato ELF, usado por algunos mecanismos de protección de pila), y PT_PAX_FLAGS (una extensión PaX para el formato ELF, usado por el proyecto PaX pensando en la seguridad.

Si queremos escanear todos los ejecutables en el directorio de trabajo actual, en el entorno PATH y en las rutas de las librerías y queremos ser informados de aquéllos que tengan una marca de escritura y ejecución PT_LOAD o PT_GNU_STACK, puede usar el siguiente comando:

Listado de Código 2.4: Escanea en busca de definiciones de escritura/ejecución PT_LOAD y PT_GNU_STACK

# scanelf -lpqe .

Usar el manejador de modificación de formato de scanelf

Una característica útil de la utilidad scanelf es el manejador de modificación de formato. Con esta opción puede controlar la salida de scanelf, simplificando por tanto la salida mediante el uso de guiones.

Como ejemplo, usaremos scanelf para mostrar los nombres que contienen relocalizaciones de texto:

Listado de Código 2.5: Ejemplo del manejador de modificación de formato de scanelf

# scanelf -l -p -R -q -F "%F #t"

3.  Listando definiciones y capacidades de PaX

Acerca de PaX

PaX es un proyecto que a su vez está alojado en el proyecto grsecurity. Citando la documentación PaX, su principal objetivo es "investigar los distintos mecanismos de defensa contra la explotación de fallos en el software que dan a un atacante acceso de lectura y escritura al espacio de direcciones del proceso atacado. Esta clase de fallos contiene, entre otros, varias formas de desbordamiento de buffer (basados tanto en pila como en heap), fallos por cadenas de usuario especialmente formateadas, etc.".

Para beneficiarse de estos mecanismos de defensa, necesitará correr un núcleo Linux en el que se apliquen los parches de código de la última versión de PaX. El proyecto Gentoo Hardened ofrece soporte de PaX y su proyecto padre: grsecurity. El paquete del núcleo con estos cambios es sys-kernel/hardened-sources.

El proyecto Gentoo/Hardened incluye la Guía rápida de comienzo con PaX para su lectura.

Ajustes y capacidades

Si su cadena de herramientas lo soporta, sus binarios pueden tener ajustes PaX adicionales en sus cabeceras de programa. Se permiten los siguientes ajustes.

Ajuste Nombre Descripción
P PAGEEXEC Rechaza la ejecución de código, en páginas en las que se puede escribir, basándose en el bit NX (o el bit NX emulado).
S SEGMEXEC Rechaza la ejecución de código, en páginas en las que se puede escribir, basándose en la lógica de segmentación de la arquitectura IA-32.
E EMUTRAMP Permite la ejecución de secuencias de ejecución de código conocidas, en páginas en las que se puede escribir, que no deberían causar ningún daño.
M MPROTECT Evita la creación de nuevo código ejecutable en el espacio de direcciones del proceso.
R RANDMMAP Aleatoriza la base de la pila para evitar que algunos ataques de desbordamiento de pila tengan éxito.
X RANDEXEC Aleatoriza las direcciones a las que la aplicación mapea para evitar que algunos ataques sean practicables.

El núcleo por defecto de Linux también soporta algunas capacidades, agrupadas en las llamadas Capacidades POSIX.1e. Puede encontrar un listado de estas capacidades en nuestro documento Capacidades de POSIX.

Usar pspax

La aplicación pspax, parte del paquete pax-utils, muestra las capacidades en tiempo de ejecución de todos los programas para los que se tiene permiso. Estos atributos también se muestran en los núcleos Linux con soporte adicional para atributos extendidos (como SELinux).

Cuando se ejecuta, pspax muestra la siguiente información:

Columna Descripción
USER Propietario del proceso
PID Identificador del proceso
PAX Ajustes PaX en tiempo de ejecución (si se puede aplicar)
MAPS Marcas de escritura/ejecución para el mapa de proceso
ELF_TYPE Tipo de ejecutable del proceso: ET_DYN o ET_EXEC
NAME Nombre del proceso
CAPS Capacidades POSIX.1e (ver nota)
ATTR Atributos extendidos (si se puede aplicar)

Nota: La aplicación pspax únicamente muestra estas capacidades cuando está enlazada con la librería de capacidades externa. Esto requiere que se construya pax-utils con -DWANT_SYSCAP.

Por defecto, pspax no muestra ningún proceso del núcleo. Si quiere que estos procesos sean tratados también, deberá usar la opción -a.

4.  Programar con ficheros ELF

La utilidad dumpelf

Con la utilidad dumpelf puede convertir un fichero ELF en un fichero de código C legible por los humanos que define una estructura con la misma imagen que el fichero ELF original.

Listado de Código 4.1: Ejemplo de dumpelf

$ dumpelf /bin/hostname
#include <elf.h>

/*
 * ELF dump of '/bin/hostname'
 *     10276 (0x2824) bytes
 */

struct {
        Elf32_Ehdr ehdr;
        Elf32_Phdr phdrs[8];
        Elf32_Shdr shdrs[26];
} dumpedelf_0 = {

.ehdr = {
(... La salida ha sido recortada ...)


Imprimir

Página actualizada 29 de agosto, 2010

Sumario: Esta guía ofrece instrucciones acerca de cómo asegurar su sistema usando el paquete pax-utils para encontrar e identificar binarios problemáticos.

Sven Vermeulen
Autor

Ned Ludd
Editor

Joshua Saddler
Editor

José María Alonso
Traductor

Donate to support our development efforts.

Copyright 2001-2013 Gentoo Foundation, Inc. Questions, Comments? Contact us.