CAPÍTULO 23 · PARTE II

Linux y Unix como sistemas de seguridad

Cómo Linux y los sistemas Unix componen identidad de proceso, permisos de archivos, privilegios, aislamiento, políticas del kernel y servicios, y por qué ninguna capa equivale por sí sola a seguridad del sistema.

Nivel N2–N3 · Estado published

El problema: un sistema Unix no tiene una sola frontera de seguridad

Un host Linux puede aceptar una conexión, iniciar un proceso, abrir un archivo y entregar una respuesta sin que ninguna de esas acciones implique automáticamente que el resultado sea seguro. La decisión se construye en varias capas: identidad y credenciales del proceso, permisos del objeto, privilegios adicionales, política del kernel, aislamiento de recursos, configuración del servicio y operación del sistema.

La tradición Unix aporta una idea potente: muchos recursos se exponen mediante interfaces de procesos y archivos, y el kernel media el acceso. Esa idea no es una garantía universal. Un proceso puede tener la identidad correcta y carecer de permiso para atravesar un directorio; puede tener permiso DAC y ser rechazado por un Linux Security Module (LSM); puede estar limitado en un namespace y conservar una ruta hacia un socket del host; puede arrancar con una cuenta dedicada y escribir en un directorio compartido por otra aplicación.

Este capítulo enseña a reconstruir esas decisiones. Linux será el referente concreto; “Unix” nombra la familia de modelos portables, no una implementación única. Los detalles que no forman parte de POSIX se marcarán como específicos de Linux. El objetivo profesional es poder explicar una decisión de acceso, diseñar un límite de privilegio y probarlo con evidencia, no memorizar comandos de hardening.

De una identidad autenticada a un proceso con credenciales

Autenticación es la verificación de una credencial. Autorización es la decisión de permitir una operación. Entre ambas existe un paso que suele desaparecer en los diagramas: el sistema crea una sesión y un proceso con credenciales concretas. Esas credenciales son las entradas que el kernel y otros controles emplearán después; no son una descripción completa de la persona que inició sesión.

En Linux, un proceso puede tener identificadores de usuario real, efectivo, guardado y de filesystem, además de identificadores de grupo análogos y grupos suplementarios. El UID real suele conservar quién inició o posee el proceso; el UID efectivo participa en muchas comprobaciones de privilegio; el UID guardado permite ciertas transiciones; el filesystem UID interviene en comprobaciones de acceso a archivos. Las relaciones exactas dependen de la operación y de la llamada de sistema. La fuente primaria para esta distinción es credentials(7), no la salida simplificada de una herramienta de administración. Linux credentials(7)

Un servicio remoto añade otra frontera. Un servidor SSH puede validar una clave, aplicar una política de cuenta, seleccionar un shell y crear un proceso con un UID y grupos. Que la clave sea válida no concede lectura de /etc/shadow, acceso a un socket administrativo ni capacidad de cambiar la configuración del servicio. La autenticación establece un contexto; cada operación posterior debe atravesar sus propios controles.

La identidad tampoco es estable durante todo el proceso. Un programa puede ejecutar otro binario, cambiar su identidad bajo reglas del kernel, crear threads con atributos asociados o delegar una acción a otro servicio. Por eso una revisión debe observar el proceso efectivo en el momento de la operación, no inferirlo sólo desde el nombre de la cuenta en una configuración.

DAC: qué expresan los permisos Unix y qué dejan fuera

Una operación se evalúa con principal, objeto, DAC, capabilities, LSM, namespace y servicio; la decisión requiere evidencia positiva y negativa.
Una decisión de acceso se compone de capas.

POSIX aporta contratos; Linux añade controles específicos.

El discretionary access control (DAC) permite que el propietario de un objeto y las reglas administrativas definan qué clases de credenciales pueden realizar operaciones. El modo tradicional expresa lectura (r), escritura (w) y ejecución (x) para tres clases: propietario, grupo y otros. En un archivo, “ejecución” significa poder intentar ejecutar el contenido como programa; en un directorio, significa búsqueda o atravesamiento de esa parte de la ruta. Linux inode(7) Linux path_resolution(7)

La diferencia del directorio es crítica. Para abrir /srv/data/informe.pdf, el proceso necesita encontrar cada componente de la ruta y tener permisos de búsqueda en /srv y /srv/data, además de permisos adecuados sobre el archivo. Conceder lectura al archivo no sirve si un directorio intermedio impide atravesarlo. A la inversa, poder atravesar un directorio no concede listar su contenido: son operaciones distintas y deben probarse por separado.

El kernel compara propietario y grupo del objeto con las credenciales del proceso y aplica la clase de modo correspondiente. La intuición “pertenece al grupo, por tanto puede leer” es incompleta: importa el grupo del objeto, los grupos suplementarios efectivos, el modo real, la ruta y cualquier control adicional. Las ACL extendidas y los atributos del filesystem pueden añadir condiciones que no aparecen en una lectura superficial de nueve caracteres.

umask interviene al crear objetos: filtra bits que el programa solicitó, pero no es una política retrospectiva para archivos ya existentes. Un servicio que crea un resultado con una umask permisiva puede producir artefactos legibles por más principales de los previstos. Una revisión profesional registra quién crea, quién consume, qué modo se espera y qué pasa cuando el proceso se reinicia con otra cuenta.

Los bits especiales tienen semánticas concretas. Set-user-ID y set-group-ID pueden hacer que una ejecución adquiera una identidad efectiva distinta bajo condiciones definidas. El sticky bit en un directorio restringe ciertas eliminaciones o renombrados a quienes tienen autoridad sobre el archivo, el directorio o el administrador. No son “permisos extra” genéricos. POSIX chmod()

El error frecuente es corregir un fallo de escritura con chmod 777. El cambio puede hacer que la operación funcione, pero también permite que cualquier principal relevante modifique o sustituya contenido. La alternativa no es siempre “denegar todo”: consiste en identificar productor y consumidor, separar directorios de entrada y salida, asignar una cuenta o grupo dedicado y probar tanto el camino permitido como el no permitido.

Privilegio: de root a capacidades más acotadas

Identidad, DAC, capabilities, namespaces, LSM y servicio responden preguntas distintas; root no resume todas las capas.
Los límites de privilegio responden preguntas diferentes.

La configuración efectiva y el kernel deben observarse.

En el modelo Unix tradicional, el UID efectivo 0 se trata como superusuario y evita muchas comprobaciones de permisos. Linux divide privilegios históricamente asociados al superusuario en capabilities, atributos por thread que pueden habilitar acciones concretas. capabilities(7) documenta conjuntos como permitted, effective, inheritable, ambient y bounding; la relación entre ellos determina qué puede ejercerse, qué puede heredarse y qué privilegios quedan bloqueados para descendientes. Linux capabilities(7)

Esta descomposición mejora el diseño de mínimo privilegio, pero no convierte una capability en autorización de negocio. Una capability que permite una operación del kernel no responde si el usuario debía hacerla, sobre qué objeto ni con qué límites de volumen. Tampoco basta con quitar una capability nominal si el proceso conserva otra ruta equivalente, acceso a un dispositivo, un socket privilegiado o una credencial que puede delegar.

Las capacidades pueden proceder de la ejecución, de atributos del archivo o de un servicio que las configura. La revisión debe observar el estado efectivo y el camino de herencia, no sólo la línea de configuración que el administrador esperaba aplicar. Una unidad puede declarar un conjunto restringido y una dependencia puede iniciar otro helper con privilegios diferentes. La pregunta es qué proceso obtiene qué capability en el momento de la operación.

root tampoco es una garantía universal en sentido contrario. El proceso puede estar limitado por un user namespace, un bounding set, un LSM, un filesystem de sólo lectura o una política del kernel. Que una identidad sea privilegiada en una frontera no demuestra control sobre todas las fronteras. El modelo correcto es “principal, capability, objeto y operación”, no “nombre de cuenta, por tanto resultado”.

Procesos, IPC y namespaces: aislar una vista no es aislar todo el host

Linux expone recursos globales mediante interfaces que otros procesos pueden observar o usar. Señales, memoria compartida, sockets Unix, /proc, dispositivos, montajes y mecanismos de depuración crean superficies de interacción. Un proceso con acceso de lectura a información de otro puede inferir estado; uno con permiso para enviar señales o adjuntar un depurador puede alterar el flujo. Los límites de proceso son reales, pero dependen de credenciales, capacidades, políticas y configuración.

Los namespaces de Linux aíslan aspectos concretos de la vista del sistema: nombres de procesos, montajes, red, IPC, UTS, usuarios y otros recursos. namespaces(7) define la idea general; user_namespaces(7) explica cómo los identificadores internos se relacionan con el namespace padre. Un UID 0 dentro de un user namespace puede representar una identidad distinta fuera de él y tener capabilities limitadas a ese contexto. Linux namespaces(7) Linux user_namespaces(7)

El aislamiento es, por tanto, una relación entre una operación y una frontera. Un namespace de red cambia interfaces visibles; no impide por sí solo que el proceso alcance una ruta de administración mediante un montaje o un socket compartido. Un mount namespace separa una vista de montajes; no convierte automáticamente cada archivo en una copia privada ni resuelve la autoridad del filesystem subyacente. Los contenedores combinan namespaces, cgroups, capacidades, filesystem y políticas; el capítulo 21 desarrolla esa composición con más detalle.

Una afirmación defendible debe indicar qué se aísla, de quién y mediante qué interfaz. “Está en un namespace” no identifica una propiedad. “El proceso no puede ver los procesos del host, no comparte el socket Docker y no puede escribir fuera de /srv/output bajo la configuración evaluada” sí expresa preguntas comprobables, aunque todavía necesite evidencia.

DAC y MAC/LSM responden preguntas diferentes

Linux Security Modules (LSM) es un framework de hooks del kernel que permite módulos aplicar controles y conservar atributos de seguridad. El framework no constituye por sí solo una política: la política activa puede provenir de SELinux, AppArmor, Smack, TOMOYO u otra combinación soportada por la construcción y configuración del kernel. Linux kernel, LSM LSM Usage

La diferencia conceptual es útil. DAC pregunta si las credenciales del proceso satisfacen la relación de propietario, grupo y modo del objeto. Un mecanismo de Mandatory Access Control (MAC) puede añadir una regla que el propietario no puede desactivar libremente o que restringe el dominio del proceso, aun cuando DAC permitiría la operación. Que un archivo sea legible según sus bits no implica que la política LSM permita entregarlo a ese proceso.

Un Permission denied no explica qué capa decidió. La investigación debe comparar permisos, identidad efectiva, capabilities, contexto LSM, montaje, namespace y argumentos de la llamada. Los logs del módulo pueden ayudar, pero no sustituyen una prueba controlada. También hay que distinguir modo de aplicación y modo de aprendizaje: una política que sólo registra no tiene el mismo efecto que una que bloquea.

La política MAC tiene límites operativos. Un perfil incompleto puede dejar una ruta sin cubrir; una actualización puede cambiar etiquetas, nombres o interfaces; un servicio auxiliar puede trabajar fuera del dominio previsto. La recomendación profesional no es asumir que “SELinux/AppArmor está activado”, sino documentar módulo, política, estado, excepciones, evidencia de denegaciones y prueba de un flujo permitido y otro rechazado.

Servicios y arranque: la seguridad empieza antes de aceptar tráfico

Un servicio tiene fronteras de proceso, filesystem, IPC, red, kernel y operador; cada cruce requiere evidencia y control negativo.
La misión del servicio se valida contra sus fronteras.

Un proceso activo no demuestra hardening ni mínimo privilegio.

Un servicio es un proceso con una misión, una identidad, una configuración y dependencias. El servicio manager —por ejemplo, systemd en muchos Linux actuales— puede establecer usuario, grupos, límites de capabilities, namespaces, montajes, acceso al filesystem y otras restricciones. systemd.exec(5) documenta esas opciones, pero una directiva no funciona como una propiedad abstracta: depende de la versión, del kernel, de la unidad efectiva, de drop-ins, dependencias y recursos compartidos. systemd.exec(5)

El servicio de conversión del caso conductor debería separar al menos cuatro decisiones. Primero, qué principal acepta la conexión y cómo se autentica. Segundo, qué cuenta y grupos usa el worker. Tercero, qué entradas puede leer y qué resultados puede crear. Cuarto, qué recursos del host necesita: red, dispositivos, sockets, reloj, claves o acceso a otros servicios.

Ejecutar el worker como una cuenta dedicada reduce el radio de una lectura o escritura accidental, pero no corrige un directorio compartido con propiedad incorrecta. Reducir capabilities limita operaciones del kernel, pero no impide un abuso lógico de la API. Hacer el filesystem de sólo lectura protege una clase de persistencia, pero puede romper actualizaciones o logs si no se prevén rutas separadas. Cada control debe asociarse a una pérdida y a una prueba.

El arranque también es una frontera de confianza. Un servicio puede heredar variables, sockets, claves o directorios de un proceso gestor; una actualización puede cambiar el binario o sus dependencias; una tarea de mantenimiento puede crear archivos con una umask distinta. La comprobación profesional compara configuración declarada y efectiva, inspecciona el árbol de procesos y dependencias, y conserva una vía de rollback o recuperación antes de aplicar cambios.

Evidencia: una observación no es una garantía

Un listado de procesos demuestra que algo estaba ejecutándose en un instante. Un stat muestra atributos de un objeto observado. Un log de arranque o de denegación conserva una señal producida por una ruta concreta. Ninguna observación por sí sola prueba que no exista otra identidad, dependencia, interfaz o configuración capaz de cambiar la conclusión.

La evidencia útil conserva contexto: host, versión del kernel y del servicio, unidad efectiva, UID/GID y capabilities observadas, namespace, ruta, operación, hora, estado de la política y resultado. Para un claim de mínimo privilegio convienen al menos dos pruebas: una operación que debe funcionar y otra que debe fallar. La segunda evita confundir “el servicio no funciona” con “el servicio está correctamente limitado”.

Los resultados negativos requieren prudencia. Que un proceso no pueda escribir /etc/example no demuestra que no pueda lograr el mismo efecto mediante una API de administración, un socket, un helper o una dependencia. Que una auditoría no registre una acción no demuestra que no ocurrió si la ruta no era auditable o si la telemetría se perdió. El capítulo 20 aporta el modelo de logging y trazabilidad; aquí interesa conservar la relación entre la decisión de acceso y la evidencia.

Método profesional para revisar un host Linux

Una revisión puede estructurarse como una cadena de seis preguntas:

  1. ¿Quién es el principal? Identifique cómo se autenticó, qué cuenta de servicio representa y qué actores administrativos tienen acceso.
  2. ¿Qué credenciales tiene el proceso? Registre UID/GID efectivos, grupos, capabilities, entorno, binario ejecutado y transiciones de identidad.
  3. ¿Qué operación solicita? Diferencie leer, escribir, crear, borrar, ejecutar, atravesar, abrir un socket, cargar un módulo o cambiar atributos.
  4. ¿Qué objeto y qué ruta están implicados? Incluya propietarios, modos, ACL, montajes, enlaces, directorios intermedios, dispositivos y dependencias.
  5. ¿Qué capas adicionales actúan? Revise LSM, namespaces, límites de recursos, service manager, políticas de red y controles del kernel.
  6. ¿Qué evidencia y recuperación existen? Ejecute controles positivos y negativos, conserve procedencia y defina cómo revertir un cambio o recuperar el servicio.

Este orden evita dos atajos. El primero es empezar por un comando de hardening sin definir la pérdida. El segundo es atribuir un fallo a permisos cuando la causa está en una identidad remota, un namespace o un LSM. La revisión no debe ser una colección de outputs: debe explicar la transición causal desde solicitud hasta decisión.

Errores frecuentes y su corrección

“UID 0 puede hacerlo todo.” La afirmación ignora namespaces, capabilities, LSM, montajes y dependencias. Corrija describiendo el contexto y probando la operación relevante.

“Si el archivo tiene rwx, el servicio está protegido.” Los bits son una capa DAC, no una garantía de identidad del consumidor, integridad del proceso ni aislamiento del host. Añada propietarios, grupos, rutas, políticas y pruebas.

“Un contenedor es una máquina virtual pequeña.” Un contenedor puede compartir kernel y superficies con el host. Declare namespaces, capabilities, montajes, dispositivos, runtime y política; remita al capítulo 21 para la comparación completa.

“El servicio está activo, así que está bien configurado.” Estado activo sólo confirma que el gestor inició un proceso. Verifique cuenta, privilegios, filesystem, red, dependencias, actualización y recuperación.

“Los logs demuestran la autorización.” Un log es evidencia de un evento observado y según una fuente. Compruebe la decisión con una operación reproducible y un control negativo.

“La distribución aplica el mismo modelo que cualquier Unix.” POSIX define contratos portables, pero capabilities, namespaces, LSM y muchas opciones del servicio son específicas de Linux. Separe la semántica portable del comportamiento de la versión desplegada.

Aplicación profesional: diseñar el límite de un servicio

Para el servicio de conversión, el claim podría ser: “Bajo la configuración evaluada, el worker puede leer archivos entregados por la API y escribir resultados en un directorio de salida dedicado, pero no modificar entradas, acceder a secretos del host ni usar interfaces administrativas no requeridas”. El claim no dice que el servicio sea seguro en absoluto. Define principal, operaciones, objetos y límites.

El diseño puede usar una cuenta dedicada, grupos mínimos, directorios separados, modos y ACL revisados, filesystem de sólo lectura salvo la salida, reducción de capabilities y namespaces coherentes con la misión. Un LSM puede imponer una política adicional. El service manager puede hacer efectivos algunos límites. El operador debe documentar dependencias y una vía de actualización.

La validación no termina al arrancar. Se prueba una entrada válida, un resultado permitido, una lectura fuera de alcance, una escritura sobre la entrada, una llamada a un socket no requerido y un reinicio o rollback. Si una prueba falla, se registra si revela una brecha del claim o una suposición errónea del diseño. El resultado profesional es una decisión acotada y reproducible, no una etiqueta.

Síntesis

Linux y Unix ofrecen un lenguaje de seguridad basado en procesos, credenciales, objetos y decisiones del kernel. Los permisos DAC expresan relaciones de propietario, grupo y otros; los directorios añaden la condición de atravesamiento; los bits especiales cambian comportamientos concretos. Capabilities separa privilegios; namespaces separa vistas; LSM puede imponer política adicional; el service manager compone esas piezas en un proceso operativo.

Ninguna capa se hereda automáticamente. Autenticar una cuenta no autoriza todas sus operaciones. Tener UID 0 no describe por sí solo el contexto completo. Un namespace no equivale a una máquina virtual. Un perfil LSM no cubre rutas que no modela. Un servicio activo y un log correcto no prueban mínimo privilegio ni ausencia de abuso.

La práctica profesional consiste en formular un claim con alcance, reconstruir principal, credenciales, objeto, operación y controles, y conservar evidencia de pruebas positivas y negativas con una vía de recuperación. Esta forma de pensar permite endurecer un host sin romper su misión y permite investigar un rechazo o una exposición sin atribuir causalidad a la primera línea de configuración que parece familiar.

Comprobación de comprensión

  1. ¿Qué diferencia existe entre una credencial de proceso y una identidad autenticada?
  2. ¿Por qué un permiso x en un directorio no significa lo mismo que x en un archivo?
  3. ¿Qué pregunta adicional aparece cuando DAC permite una operación pero LSM la rechaza?
  4. ¿Qué límite aporta una capability respecto de ejecutar todo como root?
  5. ¿Qué parte de la vista del sistema cambia con un namespace y qué parte puede seguir compartiéndose?
  6. ¿Qué evidencia necesita para afirmar que un servicio sólo escribe en su directorio de salida?

Problema de transferencia

Un equipo despliega un agente de inventario como root porque necesita leer información de varios directorios. El agente también acepta una orden remota para generar un archivo de diagnóstico y lo deja en /tmp. Reformula el claim de seguridad del despliegue. Identifica qué lecturas son realmente necesarias, qué proceso o helper podría separar la generación, qué riesgos introducen permisos de /tmp, qué capabilities, namespaces, política LSM y configuración del service manager son pertinentes, y qué pruebas positivas y negativas demostrarían que el agente no puede modificar entradas ni usar la orden remota fuera de su propósito. Explica también qué evidencia dejaría la decisión revisable después de una actualización.

Fuentes principales