Llegas a la última lección del módulo con una deuda pendiente. Llevas seis lecciones viendo cadenas como -rw-r----- y drwxr-xr-x en cada ls -l, escribiendo sudo delante de ciertos comandos sin saber del todo por qué, y aceptando que /etc/tramontana/app.conf pertenece a root:tramontana sin poder explicar qué implica eso exactamente. Esta lección salda esa deuda.

El modelo de permisos de Unix tiene más de cincuenta años y sigue siendo, con diferencia, el mecanismo de seguridad más usado del planeta. Es sorprendentemente simple —nueve bits y dos identificadores— y sorprendentemente sutil: el mismo permiso significa cosas distintas en un archivo y en un directorio, y esa asimetría es la fuente de la mayoría de los malentendidos.

No es materia opcional. Un servidor con los permisos mal puestos funciona perfectamente hasta el día en que alguien lee un fichero que no debería, o borra uno que no era suyo, o consigue ejecutar código con privilegios ajenos. Al terminar esta lección sabrás diseñar los permisos de un despliegue completo y justificar cada decisión, que es exactamente lo que se espera de un administrador de sistemas.

Contenido

  1. El modelo de seguridad de Unix: usuario, grupo, otros
  2. Leer la cadena de ls -l carácter a carácter
  3. Los tres permisos en archivos y en directorios
  4. Notación octal y notación simbólica
  5. chmod en ambas notaciones
  6. chown y chgrp
  7. Grupos: por qué el trabajo en equipo no se resuelve con «otros»
  8. La máscara umask
  9. Bits especiales: SUID, SGID y sticky
  10. Caso práctico: los permisos de Tramontana Reservas

  1. El modelo de seguridad de Unix: usuario, grupo, otros

Todo archivo en Linux tiene exactamente un propietario y exactamente un grupo propietario. A partir de ahí, el sistema divide a todo el mundo en tres categorías, y cada una tiene su propio juego de permisos:

Categoría Letra Quién es
Usuario (user) u El propietario del archivo
Grupo (group) g Los miembros del grupo propietario
Otros (others) o Todos los demás usuarios del sistema

Cuando un proceso intenta acceder a un archivo, el kernel evalúa en este orden estricto:

flowchart TD
    A["Un proceso pide acceso a un archivo"] --> R{"¿El usuario<br/>es root?"}
    R -->|Sí| RA["ACCESO CONCEDIDO<br/>(root se salta los permisos)"]
    R -->|No| B{"¿El UID coincide con<br/>el propietario?"}
    B -->|Sí| C["Aplicar los permisos de USUARIO<br/>y no mirar más"]
    B -->|No| D{"¿El GID o alguno de<br/>sus grupos coincide?"}
    D -->|Sí| E["Aplicar los permisos de GRUPO<br/>y no mirar más"]
    D -->|No| F["Aplicar los permisos de OTROS"]

Hay un detalle en ese diagrama que sorprende y que hay que interiorizar: la primera categoría que coincide es la que se aplica, y no se sigue mirando. No es acumulativo.

Consecuencia práctica, y es contraintuitiva:

operador@srv-tramontana:~$ ls -l informe.txt
----rw-r-- 1 operador tramontana 240 ago 18 16:02 informe.txt

Ese archivo pertenece a operador, el propietario no tiene ningún permiso, y el grupo tiene lectura y escritura. Resultado: operador no puede leer su propio archivo, aunque pertenezca al grupo tramontana. El kernel comprueba primero si es el propietario, ve que sí, aplica --- y termina. No llega a mirar los permisos de grupo.

operador@srv-tramontana:~$ cat informe.txt
cat: informe.txt: Permiso denegado

Es raro encontrarlo en la práctica, pero explica el modelo mejor que cualquier ejemplo bien configurado: los permisos no se suman, se seleccionan.

La excepción es root, que se salta la comprobación entera. Por eso sudo cat funciona sobre cualquier archivo, y por eso los permisos no protegen contra un administrador. Los detalles de sudo son la lección 05-02.

Detrás de los nombres hay números. El sistema trabaja con UID y GID:

operador@srv-tramontana:~$ id
uid=1001(operador) gid=1001(operador) grupos=1001(operador),27(sudo)

operador@srv-tramontana:~$ id -u
1001
operador@srv-tramontana:~$ id -un
operador

Los nombres son una comodidad para las personas; el kernel solo ve números. Esto importa al mover archivos entre máquinas: si copias con tar -p un archivo del UID 1001 a otro servidor donde el 1001 es otra persona, el archivo pasa a pertenecer a esa persona.

  1. Leer la cadena de ls -l carácter a carácter

operador@srv-tramontana:~$ ls -l /etc/tramontana/app.conf
-rw-r----- 1 root tramontana 512 ago 18 08:47 /etc/tramontana/app.conf

La cadena -rw-r----- tiene 10 caracteres con una estructura fija:

 -    rw-    r--    ---
 │     │      │      │
 │     │      │      └── OTROS: sin permisos
 │     │      └───────── GRUPO (tramontana): solo lectura
 │     └──────────────── USUARIO (root): lectura y escritura
 └────────────────────── TIPO: archivo regular

Carácter 1, el tipo. Los siete que viste en el Módulo 1:

Carácter Tipo
- Archivo regular
d Directorio
l Enlace simbólico
c Dispositivo de caracteres
b Dispositivo de bloques
s Socket
p Tubería con nombre (FIFO)

Caracteres 2 a 10, tres bloques de tres. En cada bloque, siempre en el mismo orden: r, w, x. Un guion significa que ese permiso no está.

Léela así, en voz alta hasta que salga solo:

-rw-r----- → «archivo regular; el dueño lee y escribe; el grupo solo lee; los demás nada».

Más ejemplos del propio servidor:

operador@srv-tramontana:~$ ls -l /opt/tramontana/app/ejecutable /etc/passwd /tmp
-rwxr-xr-x 1 root root 50319872 ago 18 08:30 /opt/tramontana/app/ejecutable
-rw-r--r-- 1 root root     2891 ago 18 09:00 /etc/passwd
drwxrwxrwt 9 root root     4096 ago 18 16:10 /tmp
Cadena Lectura
-rwxr-xr-x Archivo; dueño lee, escribe y ejecuta; grupo y otros leen y ejecutan
-rw-r--r-- Archivo; dueño lee y escribe; todos los demás solo leen
drwxrwxrwt Directorio; todos pueden todo... con una t al final que cambia las reglas (apartado 9)

Y el caso especial:

operador@srv-tramontana:~$ ls -l /usr/bin/python3
lrwxrwxrwx 1 root root 10 ago  2 12:04 /usr/bin/python3 -> python3.12

lrwxrwxrwx: los permisos de un enlace simbólico son siempre estos y no significan nada. Como viste en la lección 02-06, los que se aplican son los del destino.

  1. Los tres permisos en archivos y en directorios

Aquí está el punto donde se pierde más gente. Las mismas tres letras significan cosas distintas según el objeto.

Permiso En un archivo En un directorio
r (4) Leer el contenido Listar los nombres que contiene
w (2) Modificar el contenido Crear, borrar y renombrar entradas
x (1) Ejecutarlo como programa Atravesarlo: acceder a lo que hay dentro

Cada una de las tres filas del lado derecho merece una demostración, porque las tres son contraintuitivas.

x en un directorio: atravesar

x en un directorio se llama a veces search permission. Sin él no puedes acceder a nada de dentro, aunque sepas el nombre exacto y aunque el archivo interior te dé todos los permisos.

operador@srv-tramontana:~$ mkdir -p prueba/interior
operador@srv-tramontana:~$ echo "contenido" > prueba/interior/dato.txt
operador@srv-tramontana:~$ chmod 666 prueba/interior/dato.txt
operador@srv-tramontana:~$ chmod 666 prueba          # rw- sin x

operador@srv-tramontana:~$ ls prueba
interior
operador@srv-tramontana:~$ cat prueba/interior/dato.txt
cat: prueba/interior/dato.txt: Permiso denegado

El archivo tiene rw-rw-rw-: cualquiera puede leerlo. Pero para llegar hasta él, el kernel tiene que atravesar prueba, y ahí no hay x. Acceso denegado.

Y al revés, x sin r:

operador@srv-tramontana:~$ chmod 111 prueba          # --x--x--x

operador@srv-tramontana:~$ ls prueba
ls: no se puede abrir el directorio 'prueba': Permiso denegado

operador@srv-tramontana:~$ cat prueba/interior/dato.txt
contenido

No puedes ver qué hay dentro, pero sí acceder a lo que hay si sabes el nombre exacto. Es un directorio «a ciegas».

Esto no es una curiosidad: es un patrón de seguridad de uso habitual. Un directorio 711 permite que un servicio web sirva /var/www/sitio/pagina.html sin que nadie pueda listar el contenido del directorio y descubrir qué otros archivos hay. Lo mismo se aplica a /home, que en muchos sistemas es 711: los usuarios pueden entrar en su propio home, pero no listar los homes ajenos.

Regla que hay que memorizar: para acceder a /a/b/c/fichero, necesitas x en /, en a, en b y en c, y luego el permiso adecuado sobre fichero. Una sola carencia de x en cualquier punto del camino bloquea todo lo que hay debajo.

r sin x en un directorio

operador@srv-tramontana:~$ chmod 444 prueba          # r--r--r--
operador@srv-tramontana:~$ ls prueba
interior
operador@srv-tramontana:~$ ls -l prueba
ls: no se puede acceder a 'prueba/interior': Permiso denegado
total 0
d????????? ? ? ? ?            ? interior

Puedes leer los nombres, porque los nombres están en el propio directorio. Pero ls -l necesita consultar los inodos de cada entrada, y para eso hay que atravesar el directorio. De ahí esa salida con interrogantes: ls conoce el nombre y nada más.

r sin x en un directorio es prácticamente inútil. En la práctica, los directorios llevan r y x juntos o ninguno de los dos.

w en un directorio: el permiso que sorprende

Este es el más importante de entender, porque contradice la intuición.

operador@srv-tramontana:~$ chmod 777 prueba
operador@srv-tramontana:~$ sudo touch prueba/de-root.txt
operador@srv-tramontana:~$ sudo chmod 600 prueba/de-root.txt
operador@srv-tramontana:~$ ls -l prueba/de-root.txt
-rw------- 1 root root 0 ago 18 16:25 prueba/de-root.txt

operador@srv-tramontana:~$ cat prueba/de-root.txt
cat: prueba/de-root.txt: Permiso denegado

operador@srv-tramontana:~$ rm prueba/de-root.txt
operador@srv-tramontana:~$ ls prueba/
interior

Has borrado un archivo de root que ni siquiera podías leer.

La explicación es coherente con lo que sabes de la lección 02-06: borrar un archivo no es una operación sobre el archivo, es una operación sobre el directorio que lo contiene. rm elimina una entrada de la lista de nombres del directorio. Y para modificar esa lista solo hace falta w en el directorio.

Los permisos del archivo controlan su contenido. Los permisos del directorio controlan la lista de nombres. Son dos cosas distintas.

Resumen de qué permite w en un directorio:

Operación ¿Qué permiso hace falta?
Leer un archivo r en el archivo, x en el camino
Modificar el contenido de un archivo w en el archivo, x en el camino
Crear un archivo w + x en el directorio
Borrar un archivo w + x en el directorio (los del archivo dan igual)
Renombrar un archivo w + x en el directorio
Listar el directorio r en el directorio
Entrar (cd) x en el directorio

Este comportamiento es la razón de ser del sticky bit, que verás en el apartado 9, y explica por qué /tmp, donde todo el mundo escribe, no es un caos de gente borrándose archivos.

  1. Notación octal y notación simbólica

Los nueve bits de permisos se expresan de dos formas.

Octal

Cada permiso tiene un valor numérico y se suman por bloque:

Permiso Valor
r 4
w 2
x 1
- 0

Un dígito por bloque, tres dígitos en total: usuario, grupo, otros.

Octal Simbólico Suma
0 --- 0
1 --x 1
2 -w- 2
3 -wx 2+1
4 r-- 4
5 r-x 4+1
6 rw- 4+2
7 rwx 4+2+1

Los que aparecen de verdad en un sistema:

Octal Cadena Uso típico
644 rw-r--r-- Archivo normal, legible por todos
600 rw------- Archivo privado. Claves SSH
640 rw-r----- Configuración con secretos, legible por un grupo
755 rwxr-xr-x Ejecutable o directorio público
750 rwxr-x--- Directorio para un grupo concreto
700 rwx------ Directorio privado
711 rwx--x--x Directorio atravesable pero no listable
775 rwxrwxr-x Directorio de trabajo compartido por un grupo
777 rwxrwxrwx Todos pueden todo. Casi nunca correcto

Traducción en ambos sentidos

De simbólico a octal, bloque a bloque:

r w x   r - x   r - -
4+2+1   4+0+1   4+0+0
  7       5       4      ->  754

De octal a simbólico, descomponiendo cada dígito:

6 4 0
│ │ └── 0 = ---
│ └──── 4 = r--
└────── 6 = rw-       ->  rw-r-----

Practica con estos hasta que salgan sin pensar:

Octal Simbólico
644 rw-r--r--
755 rwxr-xr-x
600 rw-------
640 rw-r-----
664 rw-rw-r--
751 rwxr-x--x
400 r--------

Y al revés:

Simbólico Octal
rwxrwx--- 770
r-xr-x--- 550
rw-rw-rw- 666
--x--x--x 111
rwx------ 700

Truco mental: 7 es todo, 6 es leer y escribir, 5 es leer y ejecutar, 4 es solo leer, 0 es nada. Con esos cinco cubres el 95 % de los casos reales.

stat te da las dos notaciones a la vez, lo que va muy bien mientras aprendes:

operador@srv-tramontana:~$ stat -c '%a  %A  %n' /etc/tramontana/app.conf /opt/tramontana/app
640  -rw-r-----  /etc/tramontana/app.conf
755  drwxr-xr-x  /opt/tramontana/app

Simbólica

La notación simbólica se usa para modificar permisos sin tocar los demás. Su gramática es:

[quién][operador][permisos]
Quién Operador Permiso
u usuario + añadir r leer
g grupo - quitar w escribir
o otros = fijar exactamente x ejecutar
a todos (ugo) X x solo si ya es directorio o tenía algún x

Esa X mayúscula es una joya poco conocida y la verás en acción en el apartado siguiente.

  1. chmod en ambas notaciones

# Octal: fija los nueve bits de golpe
operador@srv-tramontana:~$ chmod 640 datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-rw-r----- 1 operador operador 446 ago 18 13:02 datos/casas.txt

# Simbólica: modifica solo lo indicado
operador@srv-tramontana:~$ chmod g+w datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-rw-rw---- 1 operador operador 446 ago 18 13:02 datos/casas.txt

operador@srv-tramontana:~$ chmod o=r datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-rw-rw-r-- 1 operador operador 446 ago 18 13:02 datos/casas.txt

operador@srv-tramontana:~$ chmod a-w datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-r--r--r-- 1 operador operador 446 ago 18 13:02 datos/casas.txt

Se pueden combinar varias reglas con comas:

operador@srv-tramontana:~$ chmod u=rw,g=r,o= datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-rw-r----- 1 operador operador 446 ago 18 13:02 datos/casas.txt

Cuándo usar cada notación:

Situación Notación
Sabes exactamente qué permisos quieres Octal: chmod 640
Quieres hacer un cambio puntual sin tocar el resto Simbólica: chmod g+w
Scripts y documentación Octal: es explícita e inequívoca
Recursivo sobre árboles mixtos Simbólica con X

-v y --changes muestran lo que hace, útil para verificar:

operador@srv-tramontana:~$ chmod -v 644 datos/casas.txt
el modo de 'datos/casas.txt' cambiado de 0640 (rw-r-----) a 0644 (rw-r--r--)

Y --reference copia los permisos de otro archivo:

operador@srv-tramontana:~$ chmod --reference=datos/reservas.csv datos/casas.txt

-R y el problema del recursivo

operador@srv-tramontana:~$ chmod -R 644 /home/operador/trabajo

Parece razonable y acaba de romper todos los directorios del árbol. Al quitarles el x, ya no se pueden atravesar:

operador@srv-tramontana:~$ ls trabajo/2026
ls: no se puede abrir el directorio 'trabajo/2026': Permiso denegado

El problema es que archivos y directorios necesitan permisos distintos: los archivos normalmente no deben ser ejecutables, y los directorios siempre necesitan x.

La solución correcta es la X mayúscula:

operador@srv-tramontana:~$ chmod -R u=rwX,g=rX,o= /home/operador/trabajo

X aplica x solo a los directorios y a los archivos que ya tenían algún bit de ejecución. Los ficheros de datos no se vuelven ejecutables; los directorios conservan su capacidad de ser atravesados. Es exactamente lo que quieres en el 100 % de los casos recursivos.

La alternativa clásica, si prefieres separar explícitamente, usa find (lección 03-03):

operador@srv-tramontana:~$ find /home/operador/trabajo -type d -exec chmod 750 {} +
operador@srv-tramontana:~$ find /home/operador/trabajo -type f -exec chmod 640 {} +

Por qué chmod -R 777 nunca es la solución

Aparece en cientos de respuestas de foros como remedio para «permiso denegado». Merece una explicación seria de por qué está mal, porque el argumento «es inseguro» a secas no convence a nadie que tenga prisa.

1. No arregla el problema, lo enmascara. Si algo daba «permiso denegado», había una razón: un usuario equivocado, un grupo mal asignado, una x que falta en un directorio del camino. 777 hace que el síntoma desaparezca sin que sepas cuál era la causa. Volverá a aparecer en otro sitio.

2. Cualquier usuario del sistema puede modificarlo. Y en un servidor hay más usuarios de los que crees: cuentas de servicio como www-data, nobody, postgres. Si un atacante compromete el servicio web —que no tiene privilegios— y tu aplicación es 777, puede reescribirla entera. Le has dado ejecución de código como el usuario que ejecuta la aplicación.

3. Con -R sobre directorios, es peor. Los directorios 777 permiten a cualquiera borrar y sustituir archivos que no son suyos, por lo que viste en el apartado 3. Un atacante puede reemplazar un binario por el suyo.

4. Marca los archivos como ejecutables. Un .conf o un .csv con permiso de ejecución es una señal de alarma para cualquier auditoría, y en algunos servidores web una configuración desafortunada puede hacer que un archivo ejecutable se ejecute en vez de servirse.

5. Es prácticamente irreversible. Después de un chmod -R 777 /var, no hay forma de saber qué permisos tenía cada archivo. En algunos casos hay que reinstalar paquetes para recuperarlos.

El diagnóstico correcto cuando algo da «permiso denegado»:

# 1. ¿Quién soy y a qué grupos pertenezco?
operador@srv-tramontana:~$ id

# 2. ¿Qué permisos tiene el archivo y de quién es?
operador@srv-tramontana:~$ ls -l /ruta/al/archivo

# 3. ¿Y todos los directorios del camino? (esta es la que se olvida)
operador@srv-tramontana:~$ namei -l /ruta/al/archivo
f: /ruta/al/archivo
drwxr-xr-x root     root     /
drwxr-x--- root     root     ruta
drwxr-xr-x root     root     al
-rw-r--r-- root     root     archivo

namei -l muestra los permisos de cada componente de la ruta, y es la herramienta que resuelve el caso más frecuente: el archivo está bien, pero un directorio intermedio no te deja pasar. En este ejemplo, ruta es drwxr-x--- y pertenece a root:root: ahí está el bloqueo.

  1. chown y chgrp

chown cambia el propietario, chgrp el grupo:

operador@srv-tramontana:~$ sudo chown root /etc/tramontana/app.conf
operador@srv-tramontana:~$ sudo chgrp tramontana /etc/tramontana/app.conf

# Las dos cosas de una vez, con dos puntos
operador@srv-tramontana:~$ sudo chown root:tramontana /etc/tramontana/app.conf

operador@srv-tramontana:~$ ls -l /etc/tramontana/app.conf
-rw-r----- 1 root tramontana 512 ago 18 08:47 /etc/tramontana/app.conf

Formas de chown:

Sintaxis Qué cambia
chown usuario fichero Solo el propietario
chown usuario:grupo fichero Ambos
chown :grupo fichero Solo el grupo (como chgrp)
chown usuario: fichero Propietario, y el grupo pasa a ser el principal de ese usuario

Opciones:

Opción Qué hace
-R Recursivo
-v / --changes Informa de los cambios
--reference=fich Copia el dueño y grupo de otro archivo
-h Actúa sobre el enlace simbólico, no sobre su destino
--from=usr:grp Cambia solo los que ya tenían ese dueño

Importante: chown requiere root. Un usuario normal no puede regalar un archivo a otro:

operador@srv-tramontana:~$ chown alumno datos/casas.txt
chown: cambiando el propietario de 'datos/casas.txt': Operación no permitida

La razón es concreta: si pudieras, podrías burlar las cuotas de disco creando archivos enormes y asignándoselos a otro. Y podrías crear un archivo con SUID y regalárselo a root, lo que sería un agujero de seguridad inmediato.

chgrp sí lo puede hacer un usuario normal, pero solo si es miembro del grupo destino:

operador@srv-tramontana:~$ chgrp sudo datos/casas.txt
operador@srv-tramontana:~$ ls -l datos/casas.txt
-rw-r--r-- 1 operador sudo 446 ago 18 13:02 datos/casas.txt

operador@srv-tramontana:~$ chgrp adm datos/casas.txt
chgrp: cambiando el grupo de 'datos/casas.txt': Operación no permitida

operador es miembro de sudo, así que puede; no es miembro de adm, así que no.

--reference es muy práctico para replicar la propiedad de un archivo modelo:

operador@srv-tramontana:~$ sudo chown --reference=/etc/tramontana/app.conf /etc/tramontana/nuevo.conf

Y -h importa con enlaces:

operador@srv-tramontana:~$ sudo chown root:root ~/app-produccion      # cambia el DESTINO
operador@srv-tramontana:~$ sudo chown -h root:root ~/app-produccion   # cambia el ENLACE

Como el propietario de un symlink es irrelevante para el control de acceso, -h se usa poco; pero conviene saber que sin -h, chown sobre un enlace toca el destino, lo que puede tener consecuencias inesperadas al recorrer un árbol con -R.

  1. Grupos: por qué el trabajo en equipo no se resuelve con «otros»

Cada usuario tiene un grupo principal (el de sus archivos nuevos) y puede pertenecer a varios grupos secundarios.

operador@srv-tramontana:~$ id
uid=1001(operador) gid=1001(operador) grupos=1001(operador),27(sudo)

operador@srv-tramontana:~$ groups
operador sudo

operador@srv-tramontana:~$ id -Gn operador
operador sudo

En Ubuntu, cada usuario tiene por defecto un grupo propio con su mismo nombre (esquema UPG, User Private Group). El motivo es que permite trabajar con una umask más permisiva de forma segura: como el grupo del usuario solo lo contiene a él, dar permisos de grupo no expone nada.

Consultar los grupos del sistema:

operador@srv-tramontana:~$ getent group sudo
sudo:x:27:operador

operador@srv-tramontana:~$ getent group | tail -n 4
operador:x:1001:
tramontana:x:1002:operador
adm:x:4:syslog

El planteamiento

Marta plantea el escenario real: Luis Ferrer necesita poder leer los logs de la aplicación y escribir en el directorio de despliegues; en el futuro se incorporará otra persona con las mismas necesidades. ¿Cómo se resuelve?

Opción incorrecta: dar permisos a «otros».

sudo chmod o+rx /var/log/tramontana
sudo chmod o+rwx /srv/tramontana/backups

Qué has hecho realmente: has dado esos permisos a todos los usuarios del sistema. No solo a Luis, sino a www-data, a nobody, a cualquier cuenta de servicio y a cualquier cuenta que se cree en el futuro. Si un atacante compromete un servicio sin privilegios, tiene acceso a tus logs (que contienen nombres de usuario y patrones de uso) y puede escribir en tu directorio de copias.

Y para gestionarlo: si mañana quieres quitarle el acceso solo a Luis, no puedes. «Otros» no distingue personas.

Opción correcta: un grupo compartido.

# (Esto se hará formalmente en la lección 05-01)
sudo groupadd tramontana
sudo usermod -aG tramontana operador
sudo usermod -aG tramontana luis

sudo chgrp -R tramontana /var/log/tramontana /srv/tramontana/backups
sudo chmod -R g+rX /var/log/tramontana
sudo chmod -R g+rwX /srv/tramontana/backups
sudo chmod o= /var/log/tramontana /srv/tramontana/backups

Ventajas concretas:

Criterio Permisos a «otros» Grupo compartido
Alcance Todos, incluidas cuentas de servicio Solo los miembros
Dar acceso a alguien nuevo Ya lo tiene (mal) usermod -aG, un comando
Quitar acceso a una persona Imposible gpasswd -d, un comando
Auditar quién tiene acceso Imposible de responder getent group tramontana
Cuentas de servicio comprometidas Tienen acceso No lo tienen
Escala a más personas No Sí

La regla es absoluta: en un sistema multiusuario, el acceso compartido se resuelve con grupos. El permiso de «otros» se usa para lo que de verdad debe ser público, y en la mayoría de los casos correctos vale 0.

Un detalle que sorprende y hay que conocer: los grupos de un proceso se determinan al iniciar sesión. Si te añaden a un grupo mientras tienes la sesión abierta, tu shell no lo ve:

operador@srv-tramontana:~$ sudo usermod -aG tramontana operador
operador@srv-tramontana:~$ groups
operador sudo                    # <- tramontana no aparece
operador@srv-tramontana:~$ id -nG operador
operador sudo tramontana         # <- pero el sistema ya lo sabe

Hay que cerrar la sesión y volver a entrar (o usar newgrp tramontana para la sesión actual). Es una fuente clásica de «le he dado permisos y sigue sin funcionar».

Ojo también con usermod -aG: la -a es obligatoria. Sin ella, usermod -G tramontana operador sustituye todos los grupos secundarios por ese, lo que sacaría a operador del grupo sudo y le dejaría sin poder administrar el sistema. Es un error que se comete una vez en la vida.

  1. La máscara umask

Cuando creas un archivo, no eliges sus permisos: los pone el sistema. La umask es la máscara que decide cuáles se quitan.

Los valores de partida están fijados por el kernel:

Objeto Permisos base Por qué
Archivo 666 (rw-rw-rw-) Nunca ejecutable por defecto: crear un archivo no debe crear un programa
Directorio 777 (rwxrwxrwx) Necesita x para ser atravesable

La umask se resta de esos valores. Más exactamente, se aplica una operación de bits que elimina los permisos marcados en la máscara.

operador@srv-tramontana:~$ umask
0022
operador@srv-tramontana:~$ umask -S
u=rwx,g=rx,o=rx

Cálculo con umask 022:

Archivos:   666  -  022  =  644   (rw-r--r--)
Directorios: 777  -  022  =  755   (rwxr-xr-x)

Comprobación:

operador@srv-tramontana:~$ umask 022
operador@srv-tramontana:~$ touch prueba-022.txt && mkdir dir-022
operador@srv-tramontana:~$ ls -ld prueba-022.txt dir-022
drwxr-xr-x 2 operador operador 4096 ago 18 17:02 dir-022
-rw-r--r-- 1 operador operador    0 ago 18 17:02 prueba-022.txt

Cálculo con umask 027:

Archivos:   666  -  027  =  640   (rw-r-----)
Directorios: 777  -  027  =  750   (rwxr-x---)
operador@srv-tramontana:~$ umask 027
operador@srv-tramontana:~$ touch prueba-027.txt && mkdir dir-027
operador@srv-tramontana:~$ ls -ld prueba-027.txt dir-027
drwxr-x--- 2 operador operador 4096 ago 18 17:04 dir-027
-rw-r----- 1 operador operador    0 ago 18 17:04 prueba-027.txt

Comparativa de las máscaras habituales:

umask Archivos Directorios Efecto Dónde se usa
022 644 755 Todos leen, solo el dueño escribe Por defecto en la mayoría de distribuciones
002 664 775 El grupo también escribe Ubuntu para usuarios normales (con UPG)
027 640 750 «Otros» no ve nada Servidores con datos sensibles
077 600 700 Solo el dueño Máxima privacidad; cuentas de root
007 660 770 Grupo total, otros nada Directorios de equipo

Un matiz técnico importante: la umask quita bits, nunca los añade. Por eso decir «se resta» es una simplificación útil pero no exacta. Con umask 022 y permisos base 666, el resultado es 644. Pero si un programa pide crear un archivo con permisos 600 explícitamente, la umask no lo subirá a 644: el resultado será 600. La umask solo puede ser más restrictiva que lo que se pide.

Otro matiz: un dígito impar en la umask sobre archivos no tiene efecto visible, porque los archivos nacen sin x de todos modos. umask 023 y umask 022 producen archivos idénticos, pero directorios distintos (754 frente a 755).

Dónde se define la umask:

# Solo para la sesión actual
operador@srv-tramontana:~$ umask 027

# Permanente para tu usuario
operador@srv-tramontana:~$ echo "umask 027" >> ~/.bashrc

# Para todo el sistema
operador@srv-tramontana:~$ grep -r "UMASK" /etc/login.defs
UMASK		022

Los servicios de systemd tienen su propia directiva UMask= en su fichero de unidad, y no heredan la de tu shell. Lo verás en la lección 05-05.

Recomendación para srv-tramontana: umask 027 para las cuentas administrativas. Con datos de huéspedes en el sistema, el valor por defecto de que cualquier usuario pueda leer los archivos nuevos es demasiado permisivo. Con 027, todo lo que crees nace sin acceso para «otros», que es el principio de mínimo privilegio aplicado desde el origen.

  1. Bits especiales: SUID, SGID y sticky

Además de los nueve bits, hay tres más. Aquí solo vas a aprender a reconocerlos cuando los veas y qué hacen en una frase. Su estudio a fondo, con sus implicaciones de seguridad y su uso correcto, es la lección 05-02.

Bit Octal Se ve en ls -l Qué hace
SUID 4000 s en la x del usuario El programa se ejecuta con los privilegios de su propietario, no de quien lo lanza
SGID 2000 s en la x del grupo En un ejecutable: corre con el grupo del archivo. En un directorio: los archivos nuevos heredan el grupo del directorio
Sticky 1000 t en la x de otros En un directorio: solo el propietario de un archivo puede borrarlo

SUID: /usr/bin/passwd

operador@srv-tramontana:~$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 mar 23 13:47 /usr/bin/passwd

Esa s donde debería ir la x del usuario es el bit SUID.

El problema que resuelve: las contraseñas se guardan cifradas en /etc/shadow, que es -rw-r----- de root:shadow. Un usuario normal no puede ni leerlo. Pero debe poder cambiar su propia contraseña, y eso implica escribir en ese archivo.

Con SUID, cuando operador ejecuta passwd, el proceso corre como root —el propietario del programa— y puede escribir en /etc/shadow. El programa está escrito para permitir únicamente cambiar la contraseña propia.

Esto es también la razón de que los programas SUID sean el objetivo favorito de los atacantes: un fallo en un binario SUID de root es una escalada de privilegios directa. Por eso son pocos, están auditados, y encontrar uno inesperado en un servidor es motivo de alarma.

SGID en directorios: herencia de grupo

operador@srv-tramontana:~$ ls -ld /srv/tramontana/compartido
drwxrws--- 2 root tramontana 4096 ago 18 17:20 /srv/tramontana/compartido

La s en la posición de la x del grupo. En un directorio, SGID hace que todo lo que se cree dentro herede el grupo del directorio, en lugar del grupo principal de quien lo crea.

Por qué importa para Tramontana: sin SGID, si Luis crea un archivo en el directorio compartido, el grupo será luis y operador no podrá acceder aunque ambos estén en tramontana. Con SGID, el archivo nace con grupo tramontana y el equipo puede trabajar. Es la pieza que hace que un directorio compartido funcione de verdad.

Sticky bit: /tmp

operador@srv-tramontana:~$ ls -ld /tmp
drwxrwxrwt 9 root root 4096 ago 18 17:22 /tmp

La t al final. /tmp es 777: todo el mundo escribe. Por lo que aprendiste en el apartado 3, eso significaría que cualquiera puede borrar los archivos temporales de cualquiera, incluidos los de procesos del sistema.

El sticky bit lo corrige: en un directorio con este bit, solo el propietario del archivo (o del directorio, o root) puede borrarlo o renombrarlo. Puedes crear tus archivos, pero no tocar los ajenos.

Cómo distinguir mayúscula de minúscula

Una sutileza que aparece en los exámenes de certificación y que conviene reconocer:

Se ve Significa
s minúscula El bit especial y el x correspondiente están activos
S mayúscula El bit especial está activo pero falta el x
t minúscula Sticky y x para otros
T mayúscula Sticky sin x para otros

Una S o una T mayúscula suele indicar un error de configuración: has puesto un bit especial sobre algo que no se puede ejecutar ni atravesar, así que no hará nada útil.

Consultar los tres con stat, donde aparecen como un cuarto dígito:

operador@srv-tramontana:~$ stat -c '%a  %A  %n' /usr/bin/passwd /tmp
4755  -rwsr-xr-x  /usr/bin/passwd
1777  drwxrwxrwt  /tmp

4755 y 1777: el primer dígito son los bits especiales.

Repito la frontera: cómo y cuándo usar estos bits, sus riesgos, cómo auditar los binarios SUID de un sistema y cómo se relacionan con sudo es materia de la lección 05-02. Aquí solo necesitas reconocerlos en un ls -l y no asustarte.

  1. Caso práctico: los permisos de Tramontana Reservas

Marta te pide un informe con el diseño de permisos del despliegue y su justificación. Vamos ruta por ruta.

El punto de partida es el principio de mínimo privilegio: cada cuenta tiene exactamente los permisos que necesita para su función, y ni uno más.

Actores del sistema:

Actor Qué es Qué necesita
root Administración Todo, por definición
operador Cuenta administrativa (grupo sudo) Administrar vía sudo
tramontana Grupo de la aplicación (se crea en 05-01) Acceso al despliegue
svc-tramontana Cuenta de servicio que ejecuta la app Lo mínimo para funcionar
Otros www-data, nobody, cuentas futuras Nada

/opt/tramontana/app — el código

operador@srv-tramontana:~$ sudo chown -R root:tramontana /opt/tramontana/releases
operador@srv-tramontana:~$ sudo chmod -R u=rwX,g=rX,o= /opt/tramontana/releases
operador@srv-tramontana:~$ sudo chmod 755 /opt/tramontana/releases/3.2.1/ejecutable

operador@srv-tramontana:~$ ls -ld /opt/tramontana/releases/3.2.1
drwxr-x--- 4 root tramontana 4096 ago 18 08:30 /opt/tramontana/releases/3.2.1
operador@srv-tramontana:~$ ls -l /opt/tramontana/releases/3.2.1/ejecutable
-rwxr-xr-x 1 root tramontana 50319872 ago 18 08:30 ejecutable

Directorios 750, archivos 640, ejecutable 755.

Justificación:

  • Propietario root: el servicio no debe poder modificar su propio código. Si un atacante compromete la aplicación explotando un fallo, no puede reescribir el ejecutable para persistir en el sistema. Esta es la decisión más importante de todo el diseño.
  • Grupo tramontana con r-x: el equipo puede leer el código y atravesar los directorios para diagnosticar.
  • Otros sin nada: ninguna cuenta de servicio ajena tiene por qué ver el código de la aplicación.
  • u=rwX,g=rX en el recursivo: los directorios reciben x y los archivos de datos no, gracias a la X mayúscula.

/etc/tramontana/app.conf — la configuración con credenciales

operador@srv-tramontana:~$ sudo chown root:tramontana /etc/tramontana/app.conf
operador@srv-tramontana:~$ sudo chmod 640 /etc/tramontana/app.conf
operador@srv-tramontana:~$ sudo chmod 750 /etc/tramontana

operador@srv-tramontana:~$ ls -ld /etc/tramontana /etc/tramontana/app.conf
drwxr-x--- 2 root tramontana 4096 ago 18 08:30 /etc/tramontana
-rw-r----- 1 root tramontana  512 ago 18 08:47 /etc/tramontana/app.conf

640, y el directorio 750.

Justificación:

  • Contiene la contraseña de la base de datos. Con el 644 habitual de /etc, cualquier usuario del sistema podría leerla. Eso incluye www-data y cualquier cuenta comprometida. Es la diferencia entre un incidente contenido y una filtración de la base de datos completa.
  • El servicio solo necesita leer, nunca escribir. Sin w para el grupo.
  • El directorio también 750: de nada sirve proteger el archivo si el directorio permite listar y atravesar. Recuerda el apartado 3: hacen falta las dos cosas.
  • Ninguna copia .bak puede quedar con permisos más laxos. Este es un fallo real y frecuente: se copia la configuración a app.conf.bak y la copia nace con la umask del momento, quizá 644. Se protege el original y se deja el secreto expuesto en la copia. Verifica siempre los permisos de tus copias de seguridad.
operador@srv-tramontana:~$ sudo cp -p /etc/tramontana/app.conf /etc/tramontana/app.conf.bak-$(date +%F)
operador@srv-tramontana:~$ ls -l /etc/tramontana/
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf.bak-2026-08-18

cp -p preserva los permisos, así que la copia nace igual de protegida. Sin -p habría nacido con la umask, que es justo lo que hay que evitar aquí.

/var/log/tramontana/ — los registros

operador@srv-tramontana:~$ sudo chown -R svc-tramontana:adm /var/log/tramontana
operador@srv-tramontana:~$ sudo chmod 750 /var/log/tramontana
operador@srv-tramontana:~$ sudo chmod 640 /var/log/tramontana/*.log

operador@srv-tramontana:~$ sudo ls -ld /var/log/tramontana
drwxr-x--- 2 svc-tramontana adm 4096 ago 18 09:00 /var/log/tramontana
operador@srv-tramontana:~$ sudo ls -l /var/log/tramontana
-rw-r----- 1 svc-tramontana adm 18432 ago 18 09:14 acceso.log
-rw-r----- 1 svc-tramontana adm  6348 ago 18 09:02 errores.log

Directorio 750, archivos 640.

Justificación:

  • El propietario es la cuenta de servicio, porque es quien tiene que escribir en los logs. Es la única ruta del despliegue donde el servicio necesita permiso de escritura.
  • El grupo adm es la convención de Debian y Ubuntu para «quien puede leer los registros del sistema». Encaja con el resto de /var/log.
  • Otros sin nada, y esto es importante: acceso.log contiene nombres de usuario, direcciones IP y patrones de actividad. Es información que ayuda a un atacante a preparar el siguiente paso, y que además puede constituir dato personal.
  • El directorio necesita w para el servicio porque logrotate y la propia aplicación crearán ficheros nuevos ahí.

/srv/tramontana/backups — las copias

operador@srv-tramontana:~$ sudo chown -R root:tramontana /srv/tramontana/backups
operador@srv-tramontana:~$ sudo chmod 2770 /srv/tramontana/backups
operador@srv-tramontana:~$ sudo chmod 640 /srv/tramontana/backups/*.tar.gz

operador@srv-tramontana:~$ ls -ld /srv/tramontana/backups
drwxrws--- 3 root tramontana 4096 ago 18 11:20 /srv/tramontana/backups

2770: 770 más el bit SGID.

Justificación:

  • El grupo necesita escribir, porque los operadores generan y rotan copias.
  • El SGID (2) hace que todo lo creado dentro herede el grupo tramontana. Sin él, una copia creada por Luis tendría grupo luis y el resto del equipo no podría gestionarla. Es el caso de uso del apartado 9, aplicado.
  • Otros, nada. Las copias contienen todo: el código, la configuración con credenciales y, según qué se respalde, datos de huéspedes. Un directorio de copias legible es una forma de dar acceso a todo lo demás saltándose los permisos que acabas de diseñar.

Cuadro resumen para el informe

Ruta Dueño:Grupo Octal Justificación en una línea
/opt/tramontana/releases/*/ root:tramontana 750 El servicio no puede modificar su propio código
/opt/tramontana/releases/*/ejecutable root:tramontana 755 Ejecutable por el servicio, no escribible
/opt/tramontana/app (enlace) root:tramontana 777 (irrelevante) Los permisos de un symlink no cuentan
/etc/tramontana/ root:tramontana 750 Proteger el directorio, no solo el fichero
/etc/tramontana/app.conf root:tramontana 640 Contiene credenciales
/var/log/tramontana/ svc-tramontana:adm 750 El servicio escribe; adm lee
/var/log/tramontana/*.log svc-tramontana:adm 640 Contienen datos de actividad de usuarios
/srv/tramontana/backups root:tramontana 2770 El grupo escribe; SGID para la herencia
/home/operador/scripts operador:operador 750 Scripts personales del operador

Verificación final del diseño:

operador@srv-tramontana:~$ sudo stat -c '%a  %U:%G  %n' \
    /opt/tramontana/releases/3.2.1 \
    /etc/tramontana/app.conf \
    /var/log/tramontana \
    /srv/tramontana/backups
750  root:tramontana  /opt/tramontana/releases/3.2.1
640  root:tramontana  /etc/tramontana/app.conf
750  svc-tramontana:adm  /var/log/tramontana
2770  root:tramontana  /srv/tramontana/backups

Advertencia necesaria

Este diseño es un ejercicio didáctico sobre datos ficticios. En un entorno real, reservas.csv y los logs de acceso contienen datos personales de huéspedes: nombres, fechas de estancia y patrones de comportamiento. Eso los somete al RGPD y a la normativa española de protección de datos.

En un despliegue real:

  • El diseño de permisos debe revisarlo el responsable de seguridad de la información o el delegado de protección de datos antes de pasar a producción, no el administrador por su cuenta.
  • Puede ser obligatorio cifrar los datos en reposo, no solo restringir el acceso mediante permisos.
  • Los registros de acceso a datos personales pueden tener que auditarse y conservarse durante un plazo determinado.
  • Los permisos de Unix son el primer nivel de control, no el único: en entornos exigentes se combinan con ACL (lección 05-02) y con control de acceso obligatorio mediante AppArmor o SELinux (lección 06-06).

Los permisos que has diseñado son necesarios y correctos. No son suficientes por sí solos cuando hay datos personales de por medio, y presentarlos como tales sería un error profesional.

Errores Comunes y Consejos

chmod -R 777 para «arreglar» un permiso denegado. Enmascara la causa, expone todo a cualquier cuenta del sistema y es casi irreversible. Diagnostica con id, ls -l y namei -l.

chmod -R 644 sobre un árbol. Deja los directorios sin x y los rompe todos. Usa chmod -R u=rwX,g=rX,o=.

Olvidar el x en los directorios del camino. El archivo está bien y sigue sin funcionar. namei -l /ruta/completa lo resuelve en un segundo.

Creer que los permisos se suman. Se aplica solo la primera categoría que coincide. Un propietario sin permisos no accede aunque el grupo los tenga.

Proteger un fichero y dejar la copia .bak abierta. Usa cp -p y verifica con ls -l después.

Dar acceso a un compañero con o+r. Se lo estás dando a todo el sistema. Grupo, siempre.

usermod -G sin -a. Sustituye todos los grupos secundarios. Puede sacarte del grupo sudo y dejarte sin administración.

No entender por qué el nuevo grupo «no funciona». Los grupos se aplican al iniciar sesión. Cierra la sesión y vuelve a entrar.

Consejo: adopta umask 027 en los servidores. Todo lo que crees nace ya cerrado para «otros». Es mínimo privilegio desde el origen.

Consejo: namei -l es la herramienta más infravalorada de esta lección. Memorízala.

Consejo: stat -c '%a %A %U:%G %n' es el formato de verificación. Te da octal, simbólico y propiedad en una línea, perfecta para informes.

Consejo: antes de cualquier chmod -R o chown -R, guarda el estado actual. Con getfacl -R directorio > permisos.bak puedes volver atrás. Es la versión de «copia antes de editar» aplicada a los permisos.

Ejercicios

Ejercicio 1: traducción y lectura

Sin ejecutar nada:

  1. Traduce a octal: rwxr-x---, rw-rw-r--, r--------, rwsr-xr-x.
  2. Traduce a simbólico: 750, 644, 2775, 1777.
  3. Explica qué puede hacer exactamente el usuario luis (miembro de tramontana, no de adm) con cada uno de estos, y por qué:
drwxr-x---  3 root  tramontana  4096 ago 18 09:00 /srv/datos
-rw-r-----  1 root  tramontana   512 ago 18 09:00 /srv/datos/config.txt
-rw-r-----  1 root  adm         2048 ago 18 09:00 /srv/datos/registro.log
  1. ¿Podría luis borrar registro.log? Justifica la respuesta.

Ejercicio 2: diagnóstico de un permiso denegado

La aplicación no arranca. En el log del servicio aparece:

FATAL: no se puede leer /etc/tramontana/app.conf: Permiso denegado

El servicio corre como svc-tramontana. Comprueba lo siguiente y da un diagnóstico razonado:

$ id svc-tramontana
uid=997(svc-tramontana) gid=997(svc-tramontana) grupos=997(svc-tramontana)

$ namei -l /etc/tramontana/app.conf
f: /etc/tramontana/app.conf
drwxr-xr-x root root       /
drwxr-x--- root tramontana etc/tramontana
-rw-r----- root tramontana app.conf

Identifica la causa exacta, propón la corrección con el comando concreto y explica por qué no debe resolverse con chmod 644.

Ejercicio 3: informe de permisos para Marta

Marta ha recibido una consulta del cliente y necesita un informe. Prepara para srv-tramontana:

  1. Una tabla con los permisos actuales de las cinco rutas de Tramontana, en octal y con propietario.
  2. La identificación de cualquier ruta cuyos permisos consideres incorrectos, con la corrección propuesta.
  3. Un párrafo, redactado para alguien no técnico, explicando qué protege este diseño y qué no protege.

Soluciones

Solución 1

1. A octal:

Simbólico Cálculo Octal
rwxr-x--- (4+2+1)(4+0+1)(0) 750
rw-rw-r-- (4+2)(4+2)(4) 664
r-------- (4)(0)(0) 400
rwsr-xr-x SUID + (4+2+1)(4+0+1)(4+0+1) 4755

En el último, la s en la posición de la x del usuario indica SUID, que aporta el 4 como cuarto dígito. Los nueve bits normales son 755.

2. A simbólico:

Octal Simbólico
750 rwxr-x---
644 rw-r--r--
2775 rwxrwsr-x (SGID)
1777 rwxrwxrwt (sticky)

En 2775, el 2 es SGID y se manifiesta como s en la x del grupo. En 1777, el 1 es el sticky bit y aparece como t en la posición de la x de otros. Ambas son minúsculas porque el x correspondiente también está presente.

3. Qué puede hacer luis:

  • /srv/datos (750, root:tramontana): luis no es root, así que no se le aplican los permisos de usuario. Sí es miembro de tramontana, así que se le aplica el grupo: r-x. Puede listar el directorio (ls) y atravesarlo (cd, acceder a lo de dentro). No puede crear, borrar ni renombrar nada dentro, porque le falta w.

  • config.txt (640, root:tramontana): se le aplica el grupo, r--. Puede leerlo con cat. No puede modificarlo. Y puede llegar hasta él porque tiene x en el directorio, condición necesaria que se comprueba primero.

  • registro.log (640, root:adm): luis no es root ni miembro de adm, así que se le aplican los permisos de otros: ---. No puede leerlo. El hecho de que pueda listar el directorio y por tanto ver que el archivo existe no le da ningún acceso a su contenido.

4. ¿Puede luis borrar registro.log?

No, pero la razón no es la que parece a primera vista.

Borrar un archivo no depende de los permisos del archivo: depende de tener w y x en el directorio que lo contiene. Si /srv/datos fuera 770, luis sí podría borrar registro.log aunque no pueda leerlo, porque estaría modificando la lista de nombres del directorio, no el archivo.

En este caso concreto no puede porque /srv/datos es 750: el grupo tiene r-x, sin w. Es la falta de w en el directorio lo que lo impide, no los permisos del log.

Esta distinción es la que hace necesario el sticky bit en directorios como /tmp, donde todos tienen w.

Solución 2

Causa exacta. namei -l muestra la cadena completa y el bloqueo está en la primera línea relevante:

drwxr-x--- root tramontana etc/tramontana

El directorio /etc/tramontana es 750, propiedad de root:tramontana. La cuenta de servicio:

uid=997(svc-tramontana) gid=997(svc-tramontana) grupos=997(svc-tramontana)

svc-tramontana no pertenece al grupo tramontana. Solo está en su propio grupo. Al evaluar el acceso a /etc/tramontana:

  • ¿Es el propietario root? No.
  • ¿Pertenece al grupo tramontana? No.
  • Se le aplican los permisos de otros: ---.

Sin x en /etc/tramontana, no puede atravesarlo, así que ni siquiera llega a evaluar los permisos de app.conf. Y aunque llegara, el fichero también le daría --- como otros.

El detalle importante: el fichero de configuración está perfectamente configurado. El problema es la pertenencia a grupo de la cuenta de servicio. Sin namei -l es fácil quedarse mirando el 640 del fichero y no ver el bloqueo real, que está un nivel más arriba.

Corrección:

operador@srv-tramontana:~$ sudo usermod -aG tramontana svc-tramontana

operador@srv-tramontana:~$ id svc-tramontana
uid=997(svc-tramontana) gid=997(svc-tramontana) grupos=997(svc-tramontana),1002(tramontana)

# El servicio no recoge el grupo nuevo hasta reiniciarse
operador@srv-tramontana:~$ sudo systemctl restart tramontana

operador@srv-tramontana:~$ sudo -u svc-tramontana cat /etc/tramontana/app.conf | head -n 1
# Configuración de Tramontana Reservas

La -a de usermod -aG es imprescindible: sin ella, sustituiría los grupos secundarios en lugar de añadir.

Y el systemctl restart es necesario porque, como viste en el apartado 7, los grupos de un proceso se fijan al arrancar. Añadir la cuenta al grupo no afecta a un proceso que ya está corriendo.

Por qué no chmod 644:

chmod 644 /etc/tramontana/app.conf haría que el servicio arrancara, sí. Y sería un fallo de seguridad grave.

El fichero contiene la contraseña de la base de datos. Con 644, cualquier usuario del sistema puede leerla: www-data, nobody, cualquier cuenta de servicio de otra aplicación, cualquier usuario que se cree en el futuro y cualquier proceso comprometido que consiga ejecutarse con una cuenta sin privilegios.

El escenario concreto: un atacante encuentra una vulnerabilidad menor en otro servicio del mismo servidor y consigue ejecutar comandos como www-data. Con 640 y el grupo bien puesto, no puede hacer nada con las credenciales de Tramontana. Con 644, lee la contraseña de la base de datos, se conecta directamente y se lleva todos los datos de huéspedes. Un incidente contenido se convierte en una filtración.

Además, 644 no arregla la causa. La cuenta de servicio sigue sin estar en el grupo al que pertenecen todos los demás recursos de la aplicación. El mismo error volverá a aparecer con los logs, con el directorio de copias y con cada recurso nuevo, y se irá parcheando cada vez abriendo permisos, hasta acabar con un despliegue completamente expuesto.

El principio general: cuando algo da «permiso denegado», la pregunta correcta no es «cómo abro esto», sino «quién debería tener acceso y cómo se lo doy solo a ellos». La respuesta casi siempre es la pertenencia a un grupo, no un chmod más permisivo.

Solución 3

1. Estado actual:

operador@srv-tramontana:~$ sudo stat -c '%a  %A  %U:%G  %n' \
    /opt/tramontana/app \
    /etc/tramontana/app.conf \
    /var/log/tramontana \
    /srv/tramontana/backups \
    /home/operador/scripts
777  lrwxrwxrwx  root:root  /opt/tramontana/app
640  -rw-r-----  root:tramontana  /etc/tramontana/app.conf
750  drwxr-x---  svc-tramontana:adm  /var/log/tramontana
770  drwxrwx---  root:tramontana  /srv/tramontana/backups
775  drwxrwxr-x  operador:operador  /home/operador/scripts
Ruta Octal Dueño:Grupo Valoración
/opt/tramontana/app 777 root:root Correcto: es un enlace, sus permisos no se aplican
/etc/tramontana/app.conf 640 root:tramontana Correcto
/var/log/tramontana 750 svc-tramontana:adm Correcto
/srv/tramontana/backups 770 root:tramontana Mejorable: falta SGID
/home/operador/scripts 775 operador:operador Incorrecto: legible y atravesable por todos

2. Correcciones propuestas:

# /srv/tramontana/backups: añadir SGID para que las copias hereden el grupo
operador@srv-tramontana:~$ sudo chmod 2770 /srv/tramontana/backups
operador@srv-tramontana:~$ ls -ld /srv/tramontana/backups
drwxrws--- 3 root tramontana 4096 ago 18 11:20 /srv/tramontana/backups

Sin SGID, una copia creada por otro miembro del equipo nacería con su grupo personal y el resto no podría gestionarla. Con SGID, todo lo creado dentro hereda tramontana. Es el requisito para que un directorio compartido funcione realmente en equipo.

# /home/operador/scripts: cerrar el acceso a otros
operador@srv-tramontana:~$ chmod 750 /home/operador/scripts
operador@srv-tramontana:~$ chmod -R u=rwX,go= /home/operador/scripts
operador@srv-tramontana:~$ chmod 750 /home/operador/scripts/*.sh

Con 775, cualquier usuario del sistema podía leer los scripts de administración. Eso no es trivial: los scripts revelan rutas internas, nombres de servicios, procedimientos de copia y a veces —por descuido— credenciales. Es información de reconocimiento gratis para un atacante.

Una comprobación adicional que merece la pena hacer siempre:

# Buscar copias de la configuración con permisos laxos
operador@srv-tramontana:~$ sudo ls -l /etc/tramontana/
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf
-rw-r----- 1 root tramontana 512 ago 18 08:47 app.conf.bak-2026-08-18

Ambas con 640. Correcto, gracias al cp -p.

3. Informe para Marta:

Diseño de permisos de acceso — Tramontana Reservas

El servidor controla quién puede ver y modificar cada archivo mediante un sistema de permisos que asigna a cada fichero un propietario, un grupo de trabajo y unos derechos concretos para cada uno. Hemos revisado y ajustado los cinco elementos del despliegue.

Qué protege el diseño actual. El código de la aplicación pertenece al administrador y la aplicación puede ejecutarlo pero no modificarlo: si alguien lograra explotar un fallo del programa, no podría alterar el propio programa para instalarse de forma permanente. El fichero de configuración, que contiene la contraseña de la base de datos, solo es legible por el administrador y por las cuentas del equipo de Tramontana; ninguna otra cuenta del servidor puede verlo, ni siquiera las de otros servicios que puedan estar instalados. Los registros de actividad, que incluyen datos de uso de los clientes, están igualmente restringidos. Las copias de seguridad son accesibles solo para el equipo, y hemos añadido un ajuste para que cualquier copia que genere cualquier miembro del equipo quede automáticamente accesible al resto, evitando que una copia acabe siendo inutilizable por un problema de permisos. Finalmente, hemos cerrado el acceso a los scripts de administración, que hasta ahora podía leer cualquier cuenta del servidor y que describen el funcionamiento interno del sistema.

Qué no protege. Este mecanismo controla el acceso desde dentro del servidor y entre cuentas distintas. No protege frente a tres cosas: quien tenga acceso de administrador puede leerlo todo, porque esa es la naturaleza del rol; los datos están almacenados sin cifrar, de modo que quien obtuviera acceso físico al disco o a una copia de seguridad podría leerlos sin necesidad de credenciales; y no impide que alguien con acceso legítimo copie información fuera del servidor.

Recomendación. Dado que el sistema almacena nombres de huéspedes, fechas de estancia e importes —datos personales sujetos al RGPD—, este diseño debería ser revisado y validado por el responsable de protección de datos antes de considerarlo definitivo. Es probable que la normativa exija, además del control de acceso que ya tenemos, el cifrado de los datos almacenados y un registro auditable de los accesos. Propongo tratarlo en la próxima reunión y planificar esas dos medidas como fase siguiente.

Ese informe cumple lo que se espera de un profesional: describe lo que se ha hecho en lenguaje comprensible, es honesto sobre los límites de la solución, y eleva a quien corresponde una decisión que no es técnica sino de cumplimiento normativo.

Conclusión

Cierras el Módulo 2 con la pieza que faltaba: la que convierte un servidor que funciona en un servidor que además es seguro.

  • El modelo de Unix asigna a cada archivo un propietario y un grupo, y divide al resto del mundo en tres categorías. Los permisos no se suman: se selecciona la primera categoría que coincide.
  • Sabes leer -rw-r----- carácter a carácter, y reconoces los siete tipos de archivo por su primera letra.
  • Entiendes que r, w y x significan cosas distintas en archivos y en directorios: que x es atravesar, que r sin x es casi inútil, y que w en un directorio permite borrar archivos que no son tuyos, porque borrar es una operación sobre la lista de nombres, no sobre el archivo.
  • Traduces entre octal y simbólico en ambos sentidos, y conoces los valores que aparecen de verdad: 644, 640, 600, 755, 750, 700, 711.
  • Usas chmod en las dos notaciones, y sabes que el recursivo correcto es u=rwX,g=rX,o= con X mayúscula, nunca -R 644 ni -R 777.
  • Sabes por qué chmod -R 777 no es una solución y cuál es el diagnóstico correcto: id, ls -l y sobre todo namei -l.
  • Manejas chown y chgrp, sabes que chown exige root y por qué, y conoces --reference y -h.
  • Tienes claro que el trabajo en equipo se resuelve con un grupo compartido y no con permisos para «otros», que usermod -aG necesita la -a, y que los grupos se aplican al iniciar sesión.
  • Calculas la umask y su efecto sobre las bases 666 y 777, y sabes que 027 es la recomendable en un servidor con datos sensibles.
  • Reconoces SUID, SGID y sticky en un ls -l, sabes qué hace cada uno en una frase, y sabes que su estudio a fondo es la lección 05-02.
  • Y has diseñado y justificado los permisos completos del despliegue de Tramontana Reservas, incluida la parte más profesional de todas: decir con claridad qué protege el diseño y qué no, y elevar a quien corresponde lo que excede tu ámbito de decisión.

Haz balance del módulo entero. Empezaste con un prompt parpadeando y sin saber cómo escribir un comando con soltura. Ahora manejas la línea de órdenes con atajos e historial, resuelves dudas con la documentación del sistema sin depender de un buscador, recorres y caracterizas un servidor desconocido con cinco comandos, creas, copias, mueves, empaquetas y verificas archivos con procedimientos reproducibles, lees y editas contenido con less, nano y el vim justo para no quedarte encerrado, entiendes qué es un inodo y has diseñado un patrón de despliegue con enlaces, y sabes decidir quién accede a qué y por qué. Eso ya no es «saber comandos»: es tener criterio.

En el Módulo 3: Habilidades Avanzadas en la Línea de Comandos todo esto se multiplica. Aprenderás a personalizar tu entorno con variables, alias e historial persistente, a describir conjuntos de archivos con comodines y patrones con expresiones regulares, a buscar cualquier cosa en cualquier sitio con find, locate y grep, a encadenar programas con tuberías y a redirigir su entrada y su salida —esa mecánica que has usado de refilón y que por fin entenderás del todo—, a procesar texto con cut, sort, uniq, sed y awk hasta convertir acceso.log y reservas.csv en los informes que Marta pide, a controlar los procesos del sistema y a programar tareas con cron para que se ejecuten solas de madrugada. Es el módulo donde dejas de ejecutar comandos uno a uno y empiezas a componerlos, que es exactamente lo que anunciaba la filosofía Unix del primer módulo. Actualiza el snapshot de tu VM y nos vemos allí.

Curso de Linux: De Principiante a Administrador de Sistemas

Módulo 1: Introducción a Linux

Módulo 2: Comandos Básicos de Linux

Módulo 3: Habilidades Avanzadas en la Línea de Comandos

Módulo 4: Scripting en Shell

Módulo 5: Administración del Sistema

Módulo 6: Redes y Seguridad

Módulo 7: Temas Avanzados

Módulo 8: Proyectos Prácticos

© Copyright 2026. Todos los derechos reservados