Gentoo Logo

Guía de inicio rápido para usar PaX con Gentoo Hardened

Contenido:

1.  ¿Qué es Gentoo Hardened?

El proyecto Hardened de Gentoo trata de añadir características a un sistema Gentoo que ayuden a evitar compromisos de seguridad. Este enfoque no es siempre sistemático, y muchas de las características son añadidas. Algunos de éstas complementan otras (por ejemplo PIE de la cadena de herramientas reforzada y ASLR del núcleo PaX reforzado), en cambio otras son mutuamente excluyentes (como SELinux y el núcleo RSBAC de Grsecurity reforzado). Este documento se centra en PaX que añade una mejora en la seguridad a ese área entre el núcleo y la zona de usuario.

2.  ¿Qué es PaX?

PaX es un parche para el núcleo Linux que ofrece el reforzamiento del mismo de tres formas:

1. La primera protección que ofrece PaX es un reforzamiento juicioso de memoria no ejecutable. Esto evita un tipo común de ataque en el que el atacante introduce código ejecutable en el espacio de direcciones de un proceso y a continuación lo ejecuta, secuestrando el proceso y posiblemente escalando privilegios. El vector normal de inserción es a traves de datos ofrecidos por el usuario que encuentran su camino hasta la memoria ejecutable. Asegurándonos de que los "datos" viven únicamente en memoria que no es ejecutable y que el "texto" se encuentra en memoria que es ejecutable, PaX protege de forma preventiva contra esta clase de ataques.

Ejecute le siguiente código con MPROTECT de PaX reforzado y no reforzado para ver esta característica en acción:

Listado de Código 2.1: mmap-rwx.c: viola MPROTECT con RWX mmap

/*
 * Compare al compilarlo con:
 *   gcc -UBAD -o mmap-rw mmap-rwx.c
 *   gcc -DBAD -o mmap-rwx mmap-rwx.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

int main()
{
       size_t *m;

#ifdef BAD
       m = mmap( NULL, 1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
#else
       m = mmap( NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
#endif

       if( m == MAP_FAILED )
               printf("mmap failed: %s\n", strerror(errno));
       else
               printf("mmap succeeded: %p\n", m);

        return 0;
}

De forma similar, ejecute el siguiente código con EMULTRAMP habilitado y deshabilitado. Este complicado código fuerza a gcc a preparar un trampolín para la función anidada f2(). El trampolín es código ejecutable que vive en la pila y podría permitir que el usuario inyectara su propio código a través de la variable i.

Listado de Código 2.2: trampoline.c: forzar a gcc a que genere un trampolín

/*
 * Comparar al compilarlo con:
 *   gcc -DTRAMPOLINE -o trampoline trampoline.c
 *   gcc -UTRAMPOLINE -o trampoline trampoline.c
 *
 */

#include <stdio.h>

typedef void (*fptr)(void) ;

void f0(fptr f)
{
        (*f)();
}

void f1()
{
       int i ;
       printf("Enter an integer: ");
       scanf("%d", &i);

        void f2()
       {
               printf("%d: Bouncey bouncey bounce!\n", i);
        }

#ifdef TRAMPOLINE
       f0(f2);
#endif
}

int main ()
{
       f1() ;
       return 0;
}

2. La segunda protección es la Aleatorización del Esquema del Espacio de Direcciones (ASLR o Address Space Layout Randomization). Esta protección ofrece una aleatorización del mapa de memoria de un proceso (tal y como informa, por ejemplo, pmap) y así, hace que sea más difícil para un atacante encontrar código que pueda constituir una amenaza en ese espacio. Cada vez que un proceso se creado desde un ejecutable ELF en particular, su mapa de memoria es diferente. Así el código peligroso que podría vivir en 0x00007fff5f281000 para una instancia del ejecutable, podría encontrarse en 0x00007f4246b5b000 para otra. A pesar que el los fuentes del núcleo Linux ofrecen alguna forma de ASLR, un núcleo parcheado con PaX incremente este efecto. Aún más, cuando una aplicación se construye como un Ejecutable Independiente de la Posición (PIE o Position Independent Executable), incluso la dirección base se aleatoriza. Intente ejecutar de forma repetida el siguiente código tanto en un núcleo Linux sin modificaciones como en uno preparado con PaX, con y sin PIE:

Listado de Código 2.3: aslr-test.c: aleatorizar la dirección base para PIE

/*
 * Comparar al compilarlo con:
 *   gcc -o aslr-test-withpie -fPIC -pie aslr-test.c
 *   gcc -o aslr-test-without -fno-PIC -nopie aslr-test.c
 *
 */

#include <stdio.h>

void doit()
{
        ;
        return ;
}

int main()
{
        printf("main @ %p\n", main);
        printf("doit @ %p\n", doit);
        return 0;
}

Para obtener más información sobre PIE, lea nuestra documentación sobre Cadena de Herramientas de Gentoo Hardened.

3. Por último, los parches de PaX ofrecen algún reforzamiento extra: borrado de la pila cuando se retorna de una llamada al sistema, rechazo a la hora de dereferenciar los punteros a la zona de usuario en algunos contextos, detectando el desbordamiento de ciertos contadores de referencia, corrigiendo los desbordamientos de algunos de los contadores de enteros, forzado del tamaño de las copias entre el núcleo y la zona de usuarios y oferta de entropía extra.

Se puede obtener más información sobre PaX en su página oficial, http://pax.grsecurity.net.

3.  Comprender PaX

El primer paso para trabajar con PaX es configurar y arrancar un núcleo parcheado con PaX. Dependiendo de si se ha configurado PaX para SOFTMODE o no SOFTMODE, el núcleo arrancará automáticamente el forzado de restricciones de memoria y una aleatorización del espacio de direcciones de todos los procesos. Idealmente, no debería de hacer nada más, sin embargo, para ejecutables problemáticos en no SOFTMODE, se requiere un segundo paso: deberá relajar algunas restricciones PaX para cada objeto ELF. Esto se hace modificando los ajustes PaX que lee el núcleo cuando el fichero ELF se carga en memoria y comienza su ejecución. Este segundo paso normalmente es directo excepto cuando el objeto ELF que requiere esta relajación es una librería. En este caso, los ajustes de la librería tienen que portarse al ejecutable que enlaza a la librería debido a que cuando PaX fuerza o relaja sus características, lo hace basándose en los ajustes del ejecutable, no en los de la librería a la cual enlaza. Discutiremos ambos pasos en detalle más abajo, pero en primer lugar necesitamos echar un vistazo rápido a las características de PaX. Las enumeraremos aquí, y para más detalles, remitiremos al lector a la documentación oficial de PaX.

SOFTMODE: Si se selecciona esta opción, la protección de PaX no se forzará por defecto para aquéllas características que se pueden habilitar o deshabilitar en tiempo de ejecución, por lo que este el el modo "permitir por defecto" contrario al "prohibir por defecto" que se obtiene cuando no se selecciona esta opción. En SOFTMODE, el usuario debe explícitamente marcar los ejecutables para forzar las protecciones PaX, mientras que en no SOFTMODE, el usuario debe marcar explícitamente para relajar las protecciones PaX.

Forzar páginas no ejecutables:

PAX_NOEXEC - Esta opción habilita la protección de las páginas de memoria reservadas como no ejecutables si no so parte del segmento de texto del proceso que se está ejecutando actualmente. Es necesario para PAGEEXEC, SEGMEXEC and KERNEXEC.
PAGEEXEC - El núcleo protegerá las páginas no ejecutables basándose en la característica que posee la CPU. Esto a veces se denomina "marcar la página con el bit NX" en otros sistemas operativos. Esta característica se pueden controlar en cada objeto ELF object basis mediante los ajustes PaX P y p.
SEGMEXEC - Esta opción es como PAGEEXEC, pero se basa en la característica de segmentación que ofrece la CPU y se controla mediante los ajustes PaX S y s. Observe que SEGMEXEC únicamente está disponible en CPUs que ofrecen segmentación de memoria, principalmente x86.
EMUTRAMP - El núcleo emulará trampolines (fragmentos de código escritos sobre la marcha) para los procesos que los necesiten, por ejemplo, funciones anidadas en C y en algunos compiladores JIT. Ya que los trampolines tratan de ejecutar el código escrito por el propio proceso a la memoria marcada como no ejecutable por PAGEEXEC o SEGMEXEC, el núcleo PaX podría matar cualquier proceso que intente hacer uso de alguna. EMUTRAMP permite a estos procesos correr sin tener que deshabilitar completamente el forzado de memoria no ejecutable. Esta característica se puede controlar para cada objeto ELF mediante el ajuste de PaX E y e.
MPROTECT - El núcleo evitará la introducción de nuevas páginas ejecutables en el proceso que se está ejecutando mediante distintas técnicas: Prohibirá cambiar el estado de ejecución de las páginas o la creación de mapeos RWX anónimos, o hacer que las páginas de datos RELRO sean escribibles. Esto se puede controlar para cada objeto ELF mediante el ajuste PaX M y m.
KERNEXEC - Este el ajuste equivalente a PAGEEXEC y MPROTECT en la zona del núcleo. No se puede deshabilitar mientras el núcleo está corriendo.

Aleatorización del Esquema del Espacio de Direcciones Mejorado (ASLR):

PAX_ASLR - El núcleo expandirá el número de bits aleatorizados para las distintas secciones del espacio de direcciones. Esta opción es necesaria para RANDMMAP, RANDKSTACK y RANDUSTACK.
RANDMMAP - El núcleo utilizará una base de direcciones aleatorizada para las peticiones mmap() que no especifiquen una a través del ajuste MAP_FIXED. Esto se controla mediante los ajustes PaX R y r.
RANDKSTACK - El núcleo aleatorizará cada pila de de tareas del núcleo en todas las llamadas al sistema. No se puede deshabilitar mientras el núcleo se está ejecutando.
RANDUSTACK - El núcleo aleatorizará cada pila de tarea de la zona de usuario. Esta característica se puede controlar para cada binario ELF mediante los ajustes PaX R y r.

Métodos de protección de memoria misceláneos:

Ninguna de las siguientes características se pueden deshabilitar mientras el núcleo se está ejecutando:
STACKLEAK - El núcleo borrará su pila antes de retornar desde una llamada al sistema. Esta característica no se puede deshabilitar mientras el núcleo se está ejecutando.
UDEREF - El núcleo no dereferenciará punteros en zona de usuario en contextos en los que se esperan únicamente punteros del propio núcleo. Esta característica no se puede deshabilitar mientras el núcleo se está ejecutando.
REFCOUNT - El núcleo detectará y evitará el desbordamientos de varios (pero no todos) los tipos de contadores de referencias a objetos.
USERCOPY - El núcleo forzará el tamaño de los objetos del montículo cuando se copian en cualquier dirección entre el núcleo y la zona de usuario.
SIZE_OVERFLOW - El núcleo recalculará expresiones de argumentos de función marcados por un atributo size_overflow con una precisión de entero doble.
LATENT_ENTROPY - El núcleo utilizará el código de arranque cuanto antes para generar entropía extra, lo cual es especialmente útil en sistemas empotrados.

Tal y como se describe más arriba, algunas de las características de PaX se pueden forzar (en el caso de SOFTMODE) o relajar (en el caso de no SOFTMODE) para cada objeto ELF. Éstos son PAGEEXEC, EMULTRAP, MPROTECT, RANDMMAP y SEGMEXEC y éstos se controlan respectivamente mediante los siguientes ajustes: P, E, M, R, S y p, e, m, r, s. Los ajustes en mayúsculas indican "reforzar" en SOFTMODE y aquéllos en minúsculas indican "relajar" en no SOFTMODE. Una tercera posibilidad es que ni los ajustes para reforzar ni para relajar están habilitados, en cuyo caso el núcleo simplemente utiliza el valor por defecto para esa protección en particular. Por ejemplo, is ni P ni p están habilitados para un objeto, entonces el núcleo no forzará PAGEEXEC en SOFTMODE y lo forzará en no SOFTMODE.

Actualmente, los parches PaX ofrecen tres formas de realizar marcados PaX: EI_PAX, PT_PAX y XATTR_PAX. EI_PAX coloca los ajustes PaX en los bytes 14 y 15 del campo e_ident de la cabecera de un objeto ELF. Sin embargo, esto no funciona así en las versiones recientes de glibc y ya no se ofrece soporte. Mire la incidencia #365825. PT_PAX coloca los ajustes en una cabecera de programa del objeto ELF llamada PAX_FLAGS. Esto tiene como ventaja que los ajustes están en el cuerpo del objeto y siempre se conservarán cuando se copie el mismo. Sin embargo, tiene la desventaja de que el objeto deberá tener la cabecera de programa PAX_FLAGS para que funcione. La mayoría de distribuciones Linux no construyen los ejecutables y librerías con esta cabecera de y el hecho de añadirlo da problemas: no hay suficiente espacio en el objeto ELF para añadirlo o, si se convierte a una cabecera de programa GNU_STACK, que no es utilizada por el núcleo PaX, puede causar problemas posteriormente bajo otros núcleos si el objeto se exporta. En el peor de los casos, cambiar el binario ELF romperá los ejecutables que se autocomprueban ya que comprobarán que han sido "modificados". Mire la incidencia #100507.

Aunque todavía se ofrece soporte para PT_PAX, la forma preferida es utilizar XATTR_PAX que localiza los ajustes PaX en los atributos extendidos del sistema de ficheros. Esto tiene la ventaja de que no modifica el objeto ELF de ninguna forma, sin embargo, tiene la desventaja de que el sistema de ficheros que aloje estos objetos, y las utilidades que se empleen para copiarlos, moverlos y archivarlos, deben ofrecer soporte para atributos extendidos (xattrs). En el caso de Gentoo y portage, esto significa que tmpfs debe dar soporte al espacio de nombres xattr de usuario user.pax.* en el cual se localizan los ajustes PaX, no solo los espacios de nombres security.* y trusted.* (Nota: user.pax.* es el subespacio de user.* que se utilizará para la información xattr relacionada con PaX. No habilitamos completamente el espacio de usuario user.* en tmpfs para reducir el riesgo de vectores de ataque enfocados a esa ruta).

Un apunte final sobre los dos métodos soportados para realizar marcados PaX: el núcleo PaX le permite habilitar tanto PT_PAX como XATTR_PAX, pero si lo hace, no impondrá los marcados a menos que los mismos ajustes se hallen en ambas localizaciones. Por esta razón, no recomendamos habilitar ambos, incluso para la migración que se describe más abajo.

4.  Construir un núcleo PaX

El equipo Gentoo Hardened mantiene y ofrece soporte para el paquete hardened-sources, que comentaremos aquí. Otros paquetes del árbol del núcleo pueden ofrecer PaX, y mucho de lo que se comente aquí se podrá aplicar a ellos. Sin embargo, tendrá que estudiar esas diferencias, nosotros no las comentaremos. El paquete hardened-sources incluye los parches Grsecurity (http://grsecurity.net/), que incluyen a su vez a los parches PaX. Si únicamente quiere los parches PaX, los puede obtener de forma aislada desde http://www.grsecurity.net/~paxguy1/. Si está interesado en aprender más sobre el reforzado con Grsecurity en general, lo cubriremos en nuestro Guía rápida de Grsecurity.

Al hacer emerge del núcleo hardened-sources, el árbol de los fuentes se localiza en /usr/src, pero no están configurados. Será entonces el momento de asegurarse de que PaX está configurado de modo que refuerce o relaje lo que desee. Abajo no concentraremos en las configuraciones recomendadas, pero si lo desea modifíquelas. La sección anterior debería haberle dado alguna idea de cada una de las opciones que se ofrecen para que así pueda elegir las opciones acertadas. Le recomendamos comenzar con una configuración muy reforzada y relajar solo cuando no se puede encontrar otra salida.

Como ya se ha comentado, los parches PaX están incluidos en Grsecurity, por lo que las opciones de configuración de PaX se encuentran bajo Security Options -> Grsecurity -> Customize Configuration -> PaX. Tiene también la opción de seleccionar uno de los perfiles preconfigurados de Grsecurity en Security Options -> Grsecurity -> Configuration Method. Éstos le ofrecerán un punto de partida con sentido para la configuración de PaX.

Si está realizando la configuración únicamente para PT_PAX, lo que sigue debería ser suficiente. Observe que debido a que estamos intentando mostrar las opciones de configuración tanto para x86 como para amd64, hemos marcado estas diferencias con un símbolo > en la columna que está más a la izquierda.

Listado de Código 4.1: Configuración del núcleo para PT_PAX

[*] Enable various PaX features

PaX Control ->

 [ ] Support soft mode
 [ ] Use legacy ELF header marking
 [*] Use ELF program header marking
 [ ] Use filesystem extended attributes marking
     MAC system integration (none)  --->

Non-executable page ->

 [*] Enforce non-executable pages
 [*]   Paging based non-executable pages
 [*]   Segmentation based non-executable pages                       <--- No está disponible para amd64.
 [*] Emulate trampolines
 [*] Restrict mprotect()
 [ ]   Use legacy/compat protection demoting (read help)
 [ ]   Allow ELF text relocations (read help)
 [*] Enforce non-executable kernel pages
     Return Address Instrumentation Method (or)  --->                <--- No está disponible para x86.
     (4) Minimum amount of memory reserved for module code           <--- No está disponible para amd64.

Address Space Layout Randomization ->

 [*] Address Space Layout Randomization
 [*] Randomize kernel stack base
 [*] Randomize user stack base
 [*] Randomize mmap() base

Miscellaneous hardening features  --->

 [*] Sanitize all freed memory
 [*] Sanitize kernel stack
 [*] Prevent invalid userland pointer dereference
 [*] Prevent various kernel object reference counter overflows
 [*] Harden heap object copies between kernel and userland
 [*] Prevent various integer overflows in function size parameters
 [*] Generate some entropy during boot

Preferentemente, deberíamos optar por los ajustes XATTR_PAX. En este caso, toda la información de arriba podría incluirse tal y como está, sin embargo, podríamos también cambiar la configuración de control de PaX:

Listado de Código 4.2: Configuración del núcleo con ajustes XATTR_PAX

PaX Control ->

 [ ] Support soft mode
 [ ] Use legacy ELF header marking
 [ ] Use ELF program header marking
 [*] Use filesystem extended attributes marking
     MAC system integration (none)  --->

Debido a que los ajustes PaX residen ahora en los atributos extendidos de su sistema de ficheros, deberemos habilitar xattr en esos sistemas de ficheros. El equipo de PaX ya ha definido una dependencia. Por ejemplo, para Ext4 tenemos:

Listado de Código 4.3: Selección automática de EXT4_FS_XATTR mediante XATTR_PAX_FLAGS

File systems  --->
 <*> The Extended 4 (ext4) filesystem
 -*-   Ext4 extended attributes
 [ ]     Ext4 POSIX Access Control Lists
 [ ]     Ext4 Security Labels
 [ ]   EXT4 debugging support

Aquí los atributos extendidos de Ext4 se han seleccionado automáticamente por PAX_XATTR_PAX_FLAGS [=y] && GRKERNSEC [=y] && PAX [=y] && EXT4_FS [=y]. Ni que decir tiene que, en caso de que esté utilizando un sistema de ficheros que no tiene esta dependencia en la selección, deberá comprobar que la selección se realiza, y si no es así, abrir un informe de incidencia para que su sistema de ficheros tenga mejor soporte en lo que se refiere a PaX.

5.  Control de PaX

Como hemos mencionado más arriba, existen cinco protecciones PaX que pueden ser activada (en SOFTMODE) or relajadas (en no SOFTMODE) para cada objeto ELF: PAGEEXEC, EMULTRAP, MPROTECT, RANDMMAP y SEGMEXEC. La última, SEGMEXEC, está disponible únicamente en las CPUs x86 que ofrecen soporte para segmentación, al contrario que la paginación que está soportada por todas las CPUs, incluso las x86. Debido a que algunos programas se rompen por alguna u otra razón bajo un reforzado PaX completo, tenemos que enfrentarnos con las alternativas: bien corregir el código para que funcione con PaX, bien relajar una o más de estas protecciones. En la praćtica, "corregir el código" puede resultar muy difícil y por tanto nos decantaremos por la segunda alternativa. El enfoque general debería consistir en intentar el reforzado completo y, en caso de que algo se rompa, utilizar dmesg para obtener un informe del núcleo indicando el porqué y a continuación relajar esa protección en particular. Esto puede no ser necesario en un sistema Gentoo debido a que los ebuilds deberían definir correctamente los ajustes a través de pax-util.eclass. Si necesita definir sus propios ajustes, le pedimos que informe de una incidencia.

En general, la definición de los ajustes PaX es sencilla, sin embargo, el usuario debería tener en cuenta algunas cosas:

1) Uno puede definir los ajustes PT_PAX o XATTR_PAX en un objeto ELF independientemente de otro objeto. De forma similar, el núcleo se puede configurar para leer uno, los dos o ninguno de estos campos. Es su decisión asegurarse de que define los ajustes en el campo que está utilizando el núcleo para obtener los resultados deseados. Por ejemplo, si tiene PT_PAX="Pe---" y XATTR_PAX no está presente en el objeto, pero el núcleo está configurado para utilizar únicamente XATTR_PAX, ¡podría obtener un resultado no deseado!

2) El enfoque recomendado es marcar los campos PT_PAX y XATTR_PAX de forma idéntica en los objetos siempre que sea posible y ajustar el núcleo para que lea únicamente XATTR_PAX. El paso "siempre que sea posible" es el paso en el que las cosas se ponen complicadas y los dos campos puede que no contengan los mismos ajustes. Si el objeto ELF no contiene una cabecera de programa PAX_FLAGS, el marcado PT_PAX fallará. Sin embargo, la ausencia de esta cabecera de programa no afectará a las marcas XATTR_PAX. Si el ELF está ocupado (esto es, hay un proceso corriendo que utilizar el texto del ELF), entonces se puede leer los ajustes PT_PAX pero no definirlos. De nuevo, esto no afectar definir u obtener los ajustes XATTR_PAX. Por el contrario, si está utilizando sistemas de ficheros que no ofrecen soporte para atributos extendidos, entonces el marcado XATTR_PAX fallará en los sistemas de ficheros mientras que el marcado PT_PAX no se verá afectado, excepto en la situación ya comentada. Esto puede ser muy sutil ya que, copiar un fichero desde un sistema de ficheros con xattrs a otro que no los tiene y volver a copiarlos a su origen hará que se pierdan los ajustes XATTR_PAX. O empaquetar con una versión antigua de tar que no conserva los xattrs hará que también perdamos nuestros ajustes.

3) Los ajustes PaX únicamente son reforzados cuando un proceso se carga desde un ejecutable ELF. Este ejecutable normalmente enlaza dinámicamente contra objetos compartidos en memoria. El uso de `cat /proc/<pid>/status | grep PaX` le ofrece el reforzamiento resultante del proceso que está corriendo con PID=<pid>. Pero, ya que el ejecutable y los objetos compartidos tienen ajustes diferentes, la pregunta surge, ¿Cuáles de ellos se utilizan para determinar los reforzamientos finales de PaX?. La respuesta es que se utiliza el ejecutable por razones de control y seguridad. Si las librerías fueran a definir el reforzado de PaX en tiempo de ejecución, entonces ¿Cuál de las librerías "ganarían" si un ejecutable está enlazado con todas ellas?. Además una librería demasiado relajada podría hacer que los privilegios sobre los muchos ejecutables que enlazan a ella también se relajaran. Por ejemplo, relajar todas las protecciones sobre glibc implicaría que PaX se desactivara en el sistema. Por supuesto, es el código de la propia librería el que necesita la relajación de algún reforzamiento PaX. En este caso uno tiene que "portar hacia atrás" los ajustes de la librería al ejecutable que los utiliza.

Abajo, describimos las utilidades ofrecidas en un sistema Gentoo para trabajar con marcados PaX. Existen varios ya que mientras PaX evolucionaba, se necesitaban nuevas características. Cada una hace hincapié en una necesidad diferente con respecto a las cuestiones planteadas arriba.

1. paxctl

Este es el paquete tradicional para la definición de ajustes PaX. Está limitado únicamente en el hecho en que solo define PT_PAX, no XATTR_PAX. Se ofrece mediante el paquete sys-apps/paxctl. Tiene una funcionalidad que ninguna otra utilidad posee: puede crear una cabecera de programa PAX_FLAGS o convertir una GNU_STACK a PAX_FLAGS. Ambos no se recomiendan ya que pueden romper ELF bajo ciertas circunstancias. Sin embargo, en el caso extremo en que no pueda utilizar XATTR_PAX (por ejemplo, no puede utilizar el sistema de ficheros que soporta los atributos extendidos) y esté tratando con un objeto ELF que no se construyó con una cabecera de programa PAX_FLAGS, entonces estas opciones están disponibles a través de esta utilidad.

A continuación se muestra una sinopsis del su utilización:

Listado de Código 5.1: paxctl -h

PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>

usage: paxctl <options> <files>

options:
        -p: disable PAGEEXEC            -P: enable PAGEEXEC
        -e: disable EMUTRAMP            -E: enable EMUTRAMP
        -m: disable MPROTECT            -M: enable MPROTECT
        -r: disable RANDMMAP            -R: enable RANDMMAP
        -x: disable RANDEXEC            -X: enable RANDEXEC
        -s: disable SEGMEXEC            -S: enable SEGMEXEC

        -v: view flags                  -z: restore default flags
        -q: suppress error messages     -Q: report flags in short format
        -c: convert PT_GNU_STACK into PT_PAX_FLAGS (see manpage!)
        -C: create PT_PAX_FLAGS (see manpage!)

Observe que paxctl también informa de la antigua protección PaX llamada RANDEXEC. Esta opción ya no se utiliza. La aleatorización de la dirección base de un proceso ahora es parte de ASLR en todos los ejecutables que se construyen con ET_DYN en lugar de EX_EXEC. Aquí se muestra a paxctl en acción:

Listado de Código 5.2: paxctl en acción

# paxctl -v /usr/bin/python3.2
PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>

- PaX flags: -----m-x-e-- [/usr/bin/python3.2]
        MPROTECT is disabled
        RANDEXEC is disabled
        EMUTRAMP is disabled

# paxctl -P /usr/bin/python3.2
# paxctl -v /usr/bin/python3.2
PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>

- PaX flags: P----m-x-e-- [/usr/bin/python3.2]
        PAGEEXEC is enabled                             <--- Nota: Esto se añade a ajustes anteriores, no los sobreescribe.
        MPROTECT is disabled
        RANDEXEC is disabled
        EMUTRAMP is disabled

2. getfattr setfattr

No hay utilidades específicas PaX sino utilidades generales para definir los atributos extendidos de un fichero. En Gentoo se ofrecen haciendo emerge de sys-apps/attr. Ya que XATTR_PAX utiliza el espacio de nombres user.* namespace (específicamente "user.pax.flags"), puede utilizar set/getfattr para trabajar con este campo. Sin embargo, tenga en cuenta que setfattr y getfattr no saben nada acerca de PaX, por lo que no realizarán ninguna comprobación de seguridad sobre lo que ponga en ese campo. Únicamente si define user.pax.flags a alguna combinación con sentido de los caracteres PpEeMmRr, el núcleo respetará su elección, en caso contrario, volverá a los valores por defecto. El siguiente listado ofrece algunos ejemplos.

Lo que sigue es un ejemplo de su uso para XATTR_PAX:

Listado de Código 5.3: setfattr y getfattr en acción

# getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="em"

# setfattr -n user.pax.flags -v P /usr/bin/python3.2
# getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="P"                                              <--- Nota: Esto sobreescribe los ajustes anteriores, no los añade.

# setfattr -n user.pax.flags -v "Hola Mamá."  /usr/bin/python3.2
# getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="Hola Mamá."                                     <--- Mamá lo agradece, pero PaX no. No hay comprobación de seguridad.

3. paxctl-ng

paxctl-ng el la nueva navaja suiza para trabajar con marcados PT_PAX y XATTR_PAX. Se puede construir con soporte para uno, otro o ambos tipos de marcados. Cuando se construye con soporte para ambos, puede copiar campos PT_PAX a campos XATTRP_PAX o viceversa, para asegurarse de que hay consistencia. En definitiva, puede hacer todo lo que paxctl y set/getfattr pueden hacer, salvo no intentar crear o convertir una cabecera de programa PAX_FLAGS. Esto no se recomienda y debe emplearse solo en el caso aislado mencionado arriba. A continuación mostramos un resumen de su utilización:

Listado de Código 5.4: paxctl-ng -h

Package Name : elfix 0.7.1
Bug Reports  : http://bugs.gentoo.org/
Program Name : paxctl-ng
Description  : Get or set pax flags on an ELF object

Usage        : paxctl-ng -PpEeMmRrSsv ELF | -Zv ELF | -zv ELF
             : paxctl-ng -Cv ELF | -cv ELF | -dv ELF
             : paxctl-ng -Fv ELF | -fv ELF
             : paxctl-ng -Lv ELF | -lv ELF
             : paxctl-ng -v ELF | -h

Options      : -P enable PAGEEXEC       -p disable  PAGEEXEC
             : -E enable EMUTRAMP       -e disable  EMUTRAMP
             : -M enable MPROTECT       -m disable  MPROTECT
             : -R enable RANDMMAP       -r disable  RANDMMAP
             : -S enable SEGMEXEC       -s disable  SEGMEXEC
             : -Z all secure settings   -z all default settings
             :
             : -C create XATTR_PAX with most secure setting
             : -c create XATTR_PAX all default settings
             : -F copy PT_PAX to XATTR_PAX
             : -f copy XATTR_PAX to PT_PAX
             : -L set only PT_PAX flags
             : -l set only XATTR_PAX flags
             :
             : -v view the flags, along with any accompanying operation
             : -h print out this help

Note         :  If both enabling and disabling flags are set, the default - is used

A continuación se muestra un ejemplo de paxctl-ng en acción:

Listado de Código 5.5: paxctl-ng en acción

# paxctl-ng -v /usr/bin/python3.2                        <--- Ver los campos PT_PAX y XATTR_PAX (-v)
/usr/bin/python3.2:
        PT_PAX   : Pem--
        XATTR_PAX: Pem--

# paxctl-ng -lPpv /usr/bin/python3.2                     <--- Definir el valor por defecto '-' para PAGEEXEC (-Pp)
/usr/bin/python3.2:                                     <--- Solo para XATTR_FLAGS (-l)
        PT_PAX   : Pem--                                <--- E informar del resultado (-v)
        XATTR_PAX: -em--

# paxctl-ng -dv /usr/bin/python3.2                       <--- Borrar todo el campo XATTR_PAX (-d)
/usr/bin/python3.2:                                     <--- E informar del resultado (-v)
        PT_PAX   : Pem--
        XATTR_PAX: not found

# paxctl-ng -lemv /usr/bin/python3.2                     <--- Definir los ajustes "em" (-em)
/usr/bin/python3.2:                                     <--- Solo para XATTR_FLAGS (-l)
        PT_PAX   : Pem--                                <--- E informar del resultado (-v)
        XATTR_PAX: -em--

# paxctl-ng -fv /usr/bin/python3.2                       <--- Copiar los ajustes XATTR_PAX a PT_PAX, sobreescribiendo estos últimos (-f)
/usr/bin/python3.2:                                     <--- E informar del resultado (-v)
        PT_PAX   : -em--
        XATTR_PAX: -em--

# paxctl-ng -d /usr/bin/python3.2                        <--- Borrar de forma silenciosa el campo XATTR_PAX (-d pero no -v)
# paxctl-ng -v /usr/bin/python3.2                        <--- Ver los campos PT_PAX y XATTR_PAX (-v)
/usr/bin/python3.2:
        PT_PAX   : -em--
        XATTR_PAX: not found

4.Módulo Python, pax.so, y una interfase simple de Python, pypaxctl.

También ofrecemos añadidos a python a través de un módulo, pax.so, el cual se instala haciendo emerge de dev-python/pypax. Este paquete es una dependencia de sys-apps/elfix ya que tanto revdep-pax como migrate-pax lo importan. Se puede compilar con soporta tanto para PT_PAX como para XATTR_PAX o para ambos a la vez. Es similar a paxctl-ng, per no tiene tantas características como éste, ya que su alcance está limitado las necesidades de revdep-pax y de migrate-pax. Esto puede cambiar en el futuro si hay necesidad de una mejor integración entre el marcado PaX con portage, el cual está escrito en python.

Actualmente pax.so exporta públicamente lo siguiente:

pax.setstrflags(str_flags):
Esta función definirá los ajustes PT_PAX y XATTR_PAX para que tengan el mismo valor. Los ajustes se especifican como una cadena de los siguientes caracteres: PpEeMmRrSs. Si, tanto el carácter para activar como para desactivar se indican para una protección en particular, entonces el valor por defecto '-' se utiliza en su lugar.
pax.setbinflags(bin_flags):
Esta función es la misma que pax.setstrflags pero toma los ajustes como un O lógico bit a bit de la representación en binario de los ajustes. El campo PT_PAX se almacena de esta forma, mientras que el campo XATTR_PAX se almacena como una cadena de los caracteres PpEeMmRrSs.
pax.getflags(elf):
Esta función devuelve los ajustes PaX como una tupla representando ambas formas (str_flags, bin_flags), esto es, se devuelve tanto como una cadena como su representación equivalente en binario. Si se han definido los dos PT_PAX y XATTR_PAX, entonces los ajustes XATTR_PAX sobreescribirán los ajustes PT_PAX.
pax.deletextpax(elf):
Esta función borrará el campo XATTR_PAX completamente. No toca el campo PT_PAX, que no se puede eliminar (¡fácilmente!).
pax.PaxError:
Esta excepción se lanza cada vez que se produce un fallo al obtener o se definir los ajustes, o cuando el borrado del campo XATTR_PAX falla.

pypaxctl es una interfase simple para pax.so que simplemente obtiene y define los valores de los ajustes de PaX utilizando la misma lógica. Cuando se obtiene el valor de los ajustes, si ambos PT_PAX y XATTR_PAX están presentes, el segundo tendrá prioridad sobre el primero. Cuando se define el valor, se definirán ambos campos siempre que sea posible. Aquí lo vemos en acción:

Listado de Código 5.6: pypaxctl en acción con PT_PAX y XATTR_PAX

# pypaxctl -g /usr/bin/python3.2         <--- Recuperar tanto PT_PAX como XATTR_PAX. El segundo tiene prioridad si está definido.
-em--                                   <--- La orden canónica es PEMRS.
# paxctl-ng -v /usr/bin/python3.2        <--- Resulta que XATTR_PAX no existe, por lo que obtenemos PT_PAX.
/usr/bin/python3.2:
        PT_PAX: -em--
        XT_PAX: not found

# paxctl-ng -lPMEv /usr/bin/python3.2    <--- Definir algunos ajustes XATTR_PAX.
/usr/bin/python3.2:
        PT_PAX: -em--
        XT_PAX: PEM--

# pypaxctl -g /usr/bin/python3.2         <--- ¡Ahora está mostrando los ajustes XATTR_PAX!
PEM--
# pypaxctl -s me /usr/bin/python3.2      <--- Definir "me" para PT_PAX y XATTR_PAX
# paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
        PT_PAX: -em--                   <--- Al igual que paxctl y paxctl-ng, no sobreescribimos los ajustes, solo los añadimos.
        XT_PAX: Pem--

# pypaxctl -s Pp /usr/bin/python3.2      <--- Pero, ¿Qué ocurre si queremos desactivar PAGEEXEC? Entonces definimos Pp al valor por defecto '-'.
# paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
        PT_PAX: -em--
        XT_PAX: -em--

Si no desea que la lógica de XATTR_PAX tenga precedencia sobre PT_PAX, is not what you want, se puede compilar con soporte PT_PAX xor XATTR_PAX. En este caso, el otro campo nunca se modifica, tal y como se muestra abajo:

Listado de Código 5.7: pypaxctl en acción con solo PT_PAX

#  paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
        PT_PAX: -em--
        XT_PAX: PEM--

# pypaxctl -g /usr/bin/python3.2
-em--
# pypaxctl -s p /usr/bin/python3.2
# paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
        PT_PAX: pem--
        XT_PAX: PEM--

# pypaxctl -s PpEem /usr/bin/python3.2
# paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
        PT_PAX: --m--
        XT_PAX: PEM--

5. revdep-pax

Esta utilidad se emplea para mapear los enlaces entre todos los objetos ELF en su sistema con sus objetos compartidos en ambas direcciones. Se puede entonces buscar marcados de ajustes PaX que no corresponden entre los objetos compartidos y los ejecutables y, opcionalmente, se permite al usuario migrar los marcados hacia delante o hacia atrás para cada objeto ELF. Aquí tenemos un resumen de su utilización:

Listado de Código 5.8: revdep-pax -h

Package Name : elfix
Bug Reports  : http://bugs.gentoo.org/
Program Name : revdep-pax
Description  : Get or set pax flags on an ELF object

Usage        : revdep-pax -f [-v]             print out all forward mappings for all system binaries
             : revdep-pax -r [-ve]            print out all reverse mappings for all system sonames
             : revdep-pax -b OBJECT  [-myv]   print all forward mappings only for OBJECT
             : revdep-pax -s SONAME  [-myve]  print all reverse mappings only for SONAME
             : revdep-pax -l LIBRARY [-myve]  print all reverse mappings only for LIBRARY file
             : revdep-pax [-h]                print out this help
             : -v                             verbose, otherwise just print mismatching objects
             : -e                             only print out executables in shell $PATH
             : -m                             don't just report, but mark the mismatching objects
             : -y                             assume "yes" to all prompts for marking (USE CAREFULLY!)

Aquí tenemos a revdep-pax en acción. Debido a que la salida es larga, la hemos acortado con algunos puntos suspensivos:

Listado de Código 5.9: revdep-pax en acción

# revdep-pax -f                                                          < --- Informar de todos los enlaces hacia delante que no concuerden.
          .....
/usr/bin/python3.2 ( --m-- )

        libpython3.2.so.1.0     /usr/lib64/libpython3.2.so.1.0 ( -e--- )
        libpthread.so.0 /lib64/libpthread-2.16.so ( -e--- )
        libc.so.6       /lib64/libc-2.16.so ( -e--- )
        libdl.so.2      /lib64/libdl-2.16.so ( -e--- )
        libutil.so.1    /lib64/libutil-2.16.so ( -e--- )
        libm.so.6       /lib64/libm-2.16.so ( -e--- )
          .....

# revdep-pax -m -b /usr/bin/python3.2                                    < --- Portar los ajustes PaX únicamente para python3.2.
/usr/bin/python3.2 (--m--)

        libpython3.2.so.1.0     /usr/lib64/libpython3.2.so.1.0 ( -e--- )
        libpthread.so.0 /lib64/libpthread-2.16.so ( -e--- )
        libc.so.6       /lib64/libc-2.16.so ( -e--- )
        libdl.so.2      /lib64/libdl-2.16.so ( -e--- )
        libutil.so.1    /lib64/libutil-2.16.so ( -e--- )
        libm.so.6       /lib64/libm-2.16.so ( -e--- )

        Will mark libraries with --m--

        Set flags for /usr/lib64/libpython3.2.so.1.0 (y/n): n            < --- Se solicitará confirmación a no ser que se emplee -y.
        Set flags for /lib64/libpthread-2.16.so (y/n): n                 < --- Contestaremos 'n' a cada pregunta de esta demostración.
        Set flags for /lib64/libc-2.16.so (y/n): n
        Set flags for /lib64/libdl-2.16.so (y/n): n
        Set flags for /lib64/libutil-2.16.so (y/n): n
        Set flags for /lib64/libm-2.16.so (y/n): n

# revdep-pax -r                                                          < --- Informar de todos los enlaces hacia atrás que no concuerden.
          .....
libpython3.2.so.1.0    /usr/lib64/libpython3.2.so.1.0 ( -e--- )         < --- El formato es soname /camino/a/su/objeto_elf (ajustes).

        /usr/bin/python3.2 ( --m-- )                                    < --- Aquí tenemos algo que no concuerda, tal y como esperábamos
          .....                                                                     en el paso anterior.

# revdep-pax -m -s libpython3.2.so.1.0                                   < --- Migraremos desde los ajustes de la librería al ejecutable
libpython3.2.so.1.0    /usr/lib64/libpython3.2.so.1.0 (-e---)                       utilizando el soname (-s). Podríamos también haber
                                                                                    utilizado /usr/lib64/libpython3.2.so.1.0 con el ajuste -l.
        /usr/bin/python3.2 ( --m-- )

        Will mark binaries with -e---

        Set flags for /usr/bin/python3.2 (y/n): y                        < --- Confirmar 'y' que queremos hacer esto.

                    /usr/bin/python3.2 ( -em-- )

# paxctl-ng -v /usr/bin/python3.2                                        < --- Comprobar de nuevo.
/usr/bin/python3.2:
        PT_PAX: -em--
        XT_PAX: -em--

6. migrate-pax

Llegados a este punto, probablemente estará harto de tanta gestión de los campos PT_PAX y XATTR_PAX su relación con la configuración del núcleo, y simplemente quiera eliminar los antiguos PT_PAX y ¡Continuar con su vida!. La herramienta migrate-pax hace exactamente eso. Recorrerá todos los objetos ELF en su sistema y migrará el campo PT_PAX a XATTR_PAX. Para obtener más detalles sobre cómo migrar, lea nuestra guía Migración de los ajustes PaX desde PT_PAX a XATTR_PAX .

Listado de Código 5.10: migrate-pax -h

Package Name : elfix
Bug Reports  : http://bugs.gentoo.org/
Program Name : migrate
Description  : Migrate PT_PAX to XATTR_PAX Flags on all system ELF objects

Usage        : migrate -v        print out all system ELF objects
             : migrate -m [-v]   migrate flags on all system ELF objects
             : migrate -d [-v]   delete XATTR_PAX on all system ELF objects
             : migrate [-h]      print out this help
             : -v                be verbose when migrating


Imprimir

Página actualizada 19 de diciembre, 2012

Sumario: Comprendiendo PaX y trabajando con él en Gentoo Hardened.

Anthony G. Basile
Autor

Francisco Izquierdo
Contribuyente

Brandon Hale
Contribuyente

blackace
Editor

solar
Editor

José María Alonso
Traductor

Donate to support our development efforts.

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