martes, 22 de febrero de 2011

Seguridad en GNU/Linux: Administrando Capabilities

En una entrega anterior vimos cómo se ponía en duda que las capabilities del kernel Linux le dieran seguridad, cosa que quedó clara para algunos aunque para otros no. 

A continuación veremos cómo el fichero /proc/sys/kernel/cap-bound nos proporciona una herramienta extraordinaria a la hora de agregar seguridad a nuestros sistemas. Este fichero contiene el valor delimitador de las capabilities o capacidades. Este ajuste es un ANDed (AND, en lógica) de las capabilities para permitir a un proceso ser ejecutado. Podemos hacer cambios a este fichero, restringiendo algunas capabilities de procesos y poner restricciones a los procesos de root también. 

Utilizando esta herramienta podemos habilitar o deshabilitar la carga de módulos del kernel, firewall, routing, raw sockets, locking de segmentos de memoria, restricciones a los cambios de propietarios de ficheros, restricciones en lectura y búsqueda de ficheros y carpetas, enviar señales a los procesos de otros, modificación de atributos especiales de ficheros, uso de chroot(), reiniciar el sistema, tareas comunes de sys admin como mount, quotas, swapping y mucho más.

Para ver el valor actual de las capabilities del kernel:

$ cat /proc/sys/kernel/cap-bound

Este fichero acepta valores hexadecimales, por lo que debemos ser cuidadosos a la hora de enviarle cualquier valor que deseamos ponerle. Por ejemplo, para impedir que se cargue módulos después del arranque del sistema tenemos a CAP_SYS_MODULE, que es quien permite agregar y remover módulos del kernel sin límites. Su valor por defecto es 16.

$ echo 0xFFFEFFFF > /proc/sys/kernel/cap-bound

Así que ahora podemos probar utilizando el comando modprobe para cargar o remover algun módulo del kernel. Pero ya que hemos activado esta capability nos devolverá un mensaje de error de que no pudo cargar o remover el módulo según sea el caso.

Al hacer este cambio sobre el fichero cap-bound de forma directa solo es funcional hasta el próximo reinicio, pues el valor anterior vuelve a ser configurado en dicho fichero, pero si queremos que este cambio sea permanente es necesario modificar el fichero sysctl.conf y agregar el comando anterior al final de dicho fichero.

$ nano /etc/sysctl.conf

echo 0xFFFEFFFF > /proc/sys/kernel/cap-bound

Para ver un listado completo de las capabilites en nuestro sistema:

$ cat /usr/src/linux/include/linux/capability.h | grep 'define CAP'


#define CAP_CHOWN            0
#define CAP_DAC_OVERRIDE     1
#define CAP_DAC_READ_SEARCH  2
#define CAP_FOWNER           3
#define CAP_FSETID           4
#define CAP_KILL             5
#define CAP_SETGID           6
#define CAP_SETUID           7
#define CAP_SETPCAP          8
#define CAP_LINUX_IMMUTABLE  9
#define CAP_NET_BIND_SERVICE 10
#define CAP_NET_BROADCAST    11
#define CAP_NET_ADMIN        12
#define CAP_NET_RAW          13
#define CAP_IPC_LOCK         14
#define CAP_IPC_OWNER        15
#define CAP_SYS_MODULE       16
#define CAP_SYS_RAWIO        17
#define CAP_SYS_CHROOT       18
#define CAP_SYS_PTRACE       19
#define CAP_SYS_PACCT        20
#define CAP_SYS_ADMIN        21
#define CAP_SYS_BOOT         22
#define CAP_SYS_NICE         23
#define CAP_SYS_RESOURCE     24
#define CAP_SYS_TIME         25
#define CAP_SYS_TTY_CONFIG   26
#define CAP_MKNOD            27
#define CAP_LEASE            28
#define CAP_AUDIT_WRITE      29
#define CAP_AUDIT_CONTROL    30
#define CAP_SETFCAP     31
#define CAP_MAC_OVERRIDE     32
#define CAP_MAC_ADMIN        33
#define CAP_LAST_CAP         CAP_MAC_ADMIN
#define CAP_TO_INDEX(x)     ((x) >> 5)        /* 1 << 5 == bits in __u32 */
#define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */

Todo esto funciona exactamente así en Fedora/CentOS/Red Hat, no así en Ubuntu por ejemplo. En tal caso el fichero cap-bound no existe. Además el fichero capability.h no se encuentra en la misma ubicación. Puedes buscarlo así: 

$ locate capability.h


No hay comentarios:

Publicar un comentario