Módulo 4: Permisos, procesos y entorno

4. Propiedad, sudo y root: el poder peligroso

Descripción

Al terminar esta lección vas a poder cambiar el propietario y el grupo de un archivo con chown y chgrp, usar sudo para pedir prestado el privilegio de root para un solo comando sin quedarte a vivir ahí, leer en sudoers exactamente qué tienes permitido hacer con sudo -l, e inspeccionar un script antes de correrlo con privilegios en vez de confiar a ciegas en un curl | sudo bash. Y, sobre todo, vas a reconocer el momento exacto en que sudo deja de resolver el problema y empieza a fabricar uno nuevo que vas a heredar dentro de tres días.

Esto es exactamente lo que separa a quien instala una dependencia con sudo por instinto de quien entiende qué acaba de autorizar. Un contenedor de Docker que escribe archivos en un volumen montado, un script de despliegue que corrió una sola vez con privilegios de más, un compañero que "arregló" un Permission denied agregando sudo al principio de la línea: los tres dejan archivos con el dueño equivocado, y ese archivo va a volver a fallar —para otra persona, en otro momento— hasta que alguien entienda por qué.

Conexión con el módulo: en la lección anterior aprendiste a leer y cambiar los permisos de un archivo con chmod —qué puede hacer cada clase de usuario con algo que ya existe—. Hoy respondes una pregunta anterior y más peligrosa: quién es el dueño de ese archivo, y qué pasa cuando necesitas actuar con la autoridad de otro usuario —típicamente root— para una sola tarea puntual. chmod es ajustar las reglas de tu propia casa. chown y sudo son, cada uno a su manera, pedirle permiso a una autoridad mayor para cambiar algo que no te pertenece del todo.


Propiedad: por qué no puedes regalar tú solo un archivo (chown y chgrp)

Piensa en el título de propiedad de un auto. Los permisos de chmod son como prestarle las llaves a alguien: decides quién puede manejarlo hoy, y puedes cambiar de opinión mañana sin que nadie más intervenga. Pero transferir el título —decir que el auto ya no es tuyo, sino de otra persona— no lo decides solo con un formulario que llenas tú: pasa por una autoridad que registra el cambio, precisamente para que nadie pueda regalar autos ajenos ni esconder de quién es en realidad un vehículo. La propiedad de un archivo en Unix funciona igual: cualquiera con permiso de escritura puede modificar un archivo, pero decidir que ese archivo ahora pertenece a otro usuario es un cambio de un nivel distinto, y por eso casi siempre requiere privilegios de root.

chown (change owner) cambia el propietario de un archivo; chgrp (change group) cambia su grupo. La sintaxis:

chown ana file.txt          # cambia solo el propietario
chown ana:staff file.txt    # cambia propietario y grupo a la vez
chown :staff file.txt       # cambia solo el grupo (equivalente a chgrp staff)
chgrp staff file.txt        # cambia solo el grupo

La razón por la que un usuario común no puede regalar un archivo suyo a otra persona no es capricho: si pudieras hacerlo, podrías evadir la cuota de disco de tu cuenta transfiriéndole tus archivos pesados a otro usuario, o hacer pasar un archivo tuyo como si lo hubiera creado otra persona. Por eso chown casi siempre exige privilegios de root. chgrp es un poco menos estricto: puedes cambiar el grupo de un archivo que ya te pertenece, pero solo hacia un grupo del que tú mismo eres miembro —no puedes asignarle a tu archivo un grupo cualquiera al que no perteneces—. La asimetría tiene sentido: cambiar de grupo entre grupos a los que ya perteneces no evade ninguna cuota ni oculta ninguna autoría; regalar el archivo entero, sí.

Ejemplo trabajado

Un script de despliegue corrió anoche con sudo y dejó un archivo de log con el dueño equivocado. Lo confirmas:

ls -l deploy.log

Qué esperar:

-rw-r--r-- 1 root staff 4096 Jul 20 23:58 deploy.log

El archivo pertenece a root, no a ti. Intentas arreglarlo directamente:

chown ana deploy.log

Qué esperar:

chown: deploy.log: Operation not permitted

Tiene sentido: cambiar el dueño de un archivo que no te pertenece es exactamente la operación que un usuario común no puede hacer solo. Necesitas pedir prestado el privilegio de root para esta única tarea:

sudo chown ana:staff deploy.log

Te pide tu contraseña —la tuya, no la de root— y no imprime nada si todo salió bien. Verificas:

ls -l deploy.log

Qué esperar:

-rw-r--r-- 1 ana staff 4096 Jul 20 23:58 deploy.log

El archivo vuelve a ser tuyo. De aquí en más puedes leerlo, editarlo o borrarlo sin necesitar sudo de nuevo para ese archivo puntual.


sudo: privilegio prestado para un comando, no una llave maestra

Imagina un edificio con una sala restringida. En vez de darte una llave maestra que abre cualquier puerta indefinidamente, hay un guardia que revisa tu credencial contra una lista —esta persona puede entrar a esta sala puntual, a estas horas, para esta tarea— y te deja pasar solo para esa visita. Terminaste, sales, y la próxima vez que quieras entrar el guardia vuelve a revisar la lista. Eso es sudo: no te entrega las llaves del edificio, te acompaña a una puerta puntual, verifica que estás autorizado, y te deja hacer una cosa con privilegios que normalmente no tienes.

Concretamente, cuando escribes sudo algún-comando, esto es lo que pasa:

  1. sudo te pide tu propia contraseña —la de tu usuario, no la de root—. Esto confirma que de verdad eres tú quien está sentado frente al teclado en este momento, no que conoces el secreto de root.
  2. Con tu identidad confirmada, sudo consulta el archivo de política /etc/sudoers para ver si tu usuario (o un grupo al que perteneces) tiene permiso para correr ese comando puntual, como ese usuario objetivo puntual (normalmente root, pero no siempre).
  3. Si sudoers lo autoriza, sudo ejecuta solo ese comando con privilegios elevados, y en cuanto termina, vuelves a ser tu usuario normal para la siguiente línea que escribas.
  4. Para no pedirte la contraseña en cada línea, sudo guarda tu autenticación por defecto durante cinco minutos, asociada a esa terminal puntual. Por eso a veces te pide contraseña y a veces no: depende de cuánto hace que la usaste por última vez en esa misma terminal.

El archivo /etc/sudoers nunca se edita con un editor cualquiera: se edita con visudo, que valida la sintaxis antes de guardar. Un error de sintaxis en sudoers escrito a mano puede dejar el archivo inutilizable —y con él, a todo el mundo sin poder usar sudo, incluido tú mismo— hasta que alguien lo repare desde un modo de recuperación. visudo existe precisamente para que eso no pase.

Puedes ver exactamente qué tienes permitido hacer, sin adivinar, con sudo -l.

Ejemplo trabajado

sudo -l

Qué esperar, en una máquina donde tu usuario tiene acceso completo:

Matching Defaults entries for ana on webserver01:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

User ana may run the following commands on webserver01:
    (ALL : ALL) ALL

(ALL : ALL) ALL se lee de derecha a izquierda: puedes correr cualquier comando (ALL), como cualquier usuario (el primer ALL entre paréntesis) y cualquier grupo (el segundo ALL). Es acceso equivalente a root, solo que gateado por tu propia contraseña.

Compáralo con una configuración deliberadamente más estrecha, típica de un servidor compartido donde nadie necesita acceso total:

User diego may run the following commands on webserver01:
    (root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

Aquí diego puede reiniciar y consultar el estado de nginx como root, sin que le pidan contraseña (NOPASSWD) precisamente para esos dos comandos —ni uno más—. Si diego intenta sudo apt install algo, sudoers lo rechaza aunque técnicamente sepa invocar sudo. Esto es sudo funcionando como estaba pensado: no es "todo o nada", es una lista quirúrgica de qué puede hacer cada persona, con qué privilegio, en qué máquina.


El antipatrón del sudo por reflejo

Aquí es donde el principio de menor privilegio que ya conoces de la lección de permisos se pone a prueba de verdad. El patrón es siempre el mismo: aparece Permission denied, el reflejo es anteponer sudo a la línea, el comando "funciona", y sigues con tu día. El problema es que sudo no resuelve el síntoma sin dejar huella: el comando corrió como root, y cualquier archivo que ese comando haya creado o modificado ahora pertenece a root. Tres días después, cuando tú —o un compañero, o un script de CI corriendo como usuario normal— intenten tocar ese mismo archivo sin sudo, va a fallar exactamente con el mismo Permission denied que creías haber resuelto.

Un caso típico: instalas dependencias con npm install y falla.

npm install

Qué esperar:

npm error code EACCES
npm error syscall mkdir
npm error path /home/ana/project/node_modules/lodash
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/home/ana/project/node_modules/lodash'

El reflejo es repetir el comando con sudo:

sudo npm install

Y funciona: la instalación termina sin errores. Pero el problema real nunca era que npm necesitara privilegios de root —nunca los necesita para instalar dependencias en tu propio proyecto—. El problema real es que node_modules/ ya pertenecía a root, probablemente porque otra vez alguien corrió sudo npm install antes. Confirmas la causa real:

ls -ld node_modules

Qué esperar:

drwxr-xr-x 42 root root 4096 Jul 18 10:02 node_modules

La corrección correcta no es repetir sudo npm install para siempre —es arreglar la propiedad del directorio, una sola vez, y no volver a necesitar sudo para este proyecto:

sudo chown -R ana:ana node_modules
npm install

Qué esperar: la primera línea no imprime nada; la segunda instala normalmente, sin sudo y sin errores, porque node_modules/ vuelve a pertenecerte a ti.

El mismo patrón aparece con sudo nano archivo o sudo vim archivo cuando el archivo ya te pertenecía y era perfectamente editable sin sudo —la costumbre de anteponer sudo "por si acaso" deja ese archivo con dueño root desde ese momento, esperando romper el próximo proceso que intente escribirlo como usuario normal.


El riesgo real de curl ... | sudo bash

Es la instrucción de instalación que ves en la mitad de los proyectos: una sola línea, copiar y pegar, listo.

curl -fsSL https://get.example.com/install.sh | sudo bash

Esa línea descarga un script y lo entrega directamente a bash, corriendo como root, sin que tengas ninguna oportunidad de mirar su contenido antes de que se ejecute. Los riesgos concretos, no teóricos:

  • Ninguna verificación de contenido. Confías por completo en lo que ese servidor decida entregarte en este momento exacto, y lo ejecutas con la autoridad máxima de la máquina. Si el servidor fue comprometido, o el dominio cambió de manos, no hay ningún paso intermedio que te proteja.
  • HTTPS protege el canal, no el contenido. Que la URL empiece con https:// garantiza que nadie interceptó la descarga en el camino —pero no dice absolutamente nada sobre si lo que el servidor te mandó es seguro. Un servidor comprometido sirve el script malicioso sobre una conexión HTTPS perfectamente válida.
  • El servidor puede servir contenido distinto según quién pregunta. Existen técnicas documentadas donde el servidor detecta que la petición viene de un curl en modo tubería —en vez de un navegador o una descarga normal a archivo— y responde con un script diferente del que vería alguien que audita el instalador bajando el archivo primero.
  • Una descarga interrumpida puede ejecutar un script a medias. Si la conexión se corta antes de que termine de llegar el script completo, bash puede quedarse ejecutando solo la mitad de las instrucciones que alcanzaron a llegar —y una instrucción destructiva cortada a la mitad no siempre falla de forma segura.

La alternativa, usando exactamente lo que ya sabes leer del módulo 2, es descargar primero e inspeccionar antes de ejecutar:

curl -fsSL https://get.example.com/install.sh -o install.sh
less install.sh

Con less recorres el script completo buscando señales de alerta: otro curl | bash escondido adentro que descarga algo más, bloques de texto codificado (base64) que se decodifican y se ejecutan sin que se vea qué hacen, o comandos que tocan rutas fuera de lo que el instalador dice que va a instalar. Si el proyecto publica un checksum, lo verificas antes de confiar en el archivo:

shasum -a 256 install.sh

Recién con el contenido revisado, lo ejecutas de forma explícita —y con sudo solo si de verdad hace falta, no por costumbre—:

bash install.sh

La diferencia no es la desconfianza por la desconfianza misma: es que ejecutar algo con privilegios de root debería ser siempre una decisión deliberada, nunca un paso invisible escondido dentro de una tubería.


su frente a sudo -i: por qué no vives en una sesión de root

Imagina la diferencia entre que alguien te preste su credencial maestra para que te quedes trabajando desde la oficina de seguridad el resto del día, contra que te dejen entrar con tu propia credencial cada vez que necesitas algo puntual de esa oficina. La primera opción borra de qué usuario fue cada acción una vez que estás adentro; la segunda deja registro de que fuiste tú, en cada visita.

su (switch user, sin argumento cambia a root) te pide la contraseña del usuario destino —para hacer su a root necesitas conocer la contraseña real de root—. Muchas distribuciones de Linux, y macOS por defecto, ni siquiera tienen una contraseña de root configurada, así que su sin más simplemente no funciona hasta que alguien la establezca —lo cual, de entrada, ya es una señal de que no es el camino recomendado—. Una vez adentro, tienes una sesión de shell completa como root que dura hasta que salgas explícitamente con exit.

sudo -i (o sudo -s) hace algo distinto: te da un shell como root, pero usando tu propia contraseña, verificada contra sudoers igual que cualquier otro comando de sudo. Cada vez que lo usas queda registrado contra tu nombre de usuario real, no contra un genérico "alguien entró como root".

La razón práctica para preferir sudo —ya sea comando por comando, o con sudo -i cuando de verdad necesitas varias operaciones seguidas— por encima de su es doble: nadie en el equipo necesita conocer ni compartir una contraseña de root, y los registros del sistema muestran exactamente quién hizo qué, cuándo, en una máquina que probablemente comparten varias personas. Vivir instalado en una sesión de root todo el día, además, es la forma más fácil de olvidar en qué nivel de privilegio estás parado y ejecutar por descuido algo que pensabas que ibas a correr como usuario normal.


Errores comunes

1. Pensar que sudo te "convierte" en root para el resto de la sesión (conceptual). Qué pasa: corres sudo mkdir carpeta, y en la siguiente línea escribes otro comando dando por hecho que sigues siendo root, para descubrir que te volvió a negar el permiso. Por qué: sudo eleva privilegios solo para el comando puntual que le sigue en esa misma línea; en cuanto termina, vuelves a ser tu usuario normal —a menos que hayas entrado explícitamente con sudo -i o sudo -s—. Cómo detectarlo: te sorprende un Permission denied justo después de un comando con sudo que sí funcionó. Cómo corregirlo: antepón sudo a cada comando que efectivamente lo necesite, o usa sudo -i de forma deliberada cuando de verdad vas a hacer varias tareas seguidas como root —y sal de esa sesión en cuanto termines.

2. Creer que HTTPS en un curl | bash garantiza que el script es seguro (conceptual). Qué pasa: alguien justifica correr un instalador de una sola línea diciendo "es seguro, la URL usa HTTPS". Por qué: HTTPS protege el canal —que nadie intercepte o altere los bytes mientras viajan de servidor a tu máquina—, pero no dice nada sobre si el contenido que el servidor decidió enviarte es confiable. Un servidor comprometido, o que sirve contenido distinto según quién pregunta, entrega igual el script malicioso sobre una conexión HTTPS perfectamente válida. Cómo detectarlo: la justificación para confiar en un script se basa únicamente en el protocolo de transporte, no en haber leído una sola línea de lo que hace. Cómo corregirlo: descarga el script a un archivo, léelo con less o cat, y solo entonces ejecútalo de forma explícita —con sudo únicamente si de verdad lo necesita.

3. Editar /etc/sudoers con un editor cualquiera en vez de visudo. Qué pasa: abres sudoers con nano o vim directamente, cometes un error de sintaxis sin darte cuenta, y a partir de ese momento sudo deja de funcionar para todo el mundo en esa máquina —incluido tú mismo—. Por qué: sudoers controla quién tiene privilegios elevados en todo el sistema; un error de sintaxis puede dejarlo en un estado que ningún usuario puede usar para recuperar el control con sudo. Cómo detectarlo: después de editar sudoers a mano, cualquier sudo — incluido sudo -l— empieza a fallar con un error de sintaxis. Cómo corregirlo: edita siempre sudoers con sudo visudo, que valida la sintaxis antes de guardar y rechaza el archivo si tiene un error, en vez de dejarte guardar una versión rota.


Ejercicios

1. Corriste sudo pip install -r requirements.txt dentro de un entorno virtual que ya existía y te pertenecía. Ahora, sin sudo, cualquier pip install paquete-nuevo falla con Permission denied. ¿Cuál es la causa raíz, y qué comando la corrige sin tener que recrear el entorno virtual desde cero?

Ver solución

La causa raíz es que sudo pip install corrió como root, y cualquier archivo que escribió dentro del entorno virtual (los paquetes, la carpeta site-packages) quedó con dueño root en vez de tu usuario. La corrección es devolverle la propiedad completa del entorno virtual a tu usuario, de forma recursiva:

sudo chown -R ana:ana venv/

Después de esto, pip install paquete-nuevo vuelve a funcionar sin sudo, porque todos los archivos del entorno virtual te pertenecen de nuevo.

Por qué funciona: el problema nunca fue que pip necesitara privilegios de root —nunca los necesita para instalar paquetes dentro de tu propio entorno virtual—; el problema era la propiedad de los archivos que un sudo anterior dejó mal puesta. Corregir la propiedad una sola vez evita repetir sudo por reflejo cada vez que instalas algo.

2. Corres sudo -l en un servidor compartido y ves esta línea:

User diego may run the following commands on webserver01:
    (root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

¿Qué puede hacer exactamente diego, y qué pasa si intenta sudo apt update en esa misma máquina?

Ver solución

diego puede correr únicamente esos dos comandos —systemctl restart nginx y systemctl status nginx— como root, y sudoers ni siquiera le va a pedir contraseña para esos dos comandos puntuales (eso es lo que significa NOPASSWD). Si intenta cualquier otro comando con sudo, incluido sudo apt update, sudoers lo rechaza: no está en la lista de comandos permitidos para su usuario en esa máquina, aunque técnicamente sepa cómo invocar sudo.

Por qué funciona: sudoers no es una llave de todo o nada —permite definir exactamente qué comando, como qué usuario, y con qué requisito de contraseña, para cada persona. Eso es lo que hace posible dar acceso puntual sin entregar acceso total.

3. Te llega esta instrucción de instalación en la documentación de una herramienta nueva:

curl -sSL https://install.example.dev/setup.sh | sudo bash

Antes de correrla en tu máquina de trabajo, ¿qué harías distinto, y por qué?

Ver solución

Descargaría el script a un archivo primero, sin ejecutarlo, y lo leería antes de correr nada:

curl -sSL https://install.example.dev/setup.sh -o setup.sh
less setup.sh

Buscaría señales de alerta —otro curl | bash escondido adentro, bloques codificados en base64 que se decodifican y ejecutan, comandos que tocan rutas fuera de lo que el instalador dice instalar—. Si el proyecto publica un checksum, lo verificaría contra el archivo descargado antes de confiar en él. Recién con el contenido revisado, lo correría de forma explícita (bash setup.sh, con sudo solo si de verdad hace falta).

Por qué funciona: que la URL use HTTPS solo garantiza que nadie interceptó la descarga en el camino —no dice nada sobre si el contenido que el servidor decidió enviarte es seguro, y un servidor comprometido puede servir un script malicioso sobre una conexión HTTPS perfectamente válida. Inspeccionar antes de ejecutar es la única forma de saber qué autorizaste correr con privilegios de root.

4. Un sysadmin de un servidor con seis ingenieros distintos con acceso prohíbe expresamente el uso de su y exige sudo -i para cualquier tarea administrativa. ¿Qué gana el equipo con esa regla que no tendría si todos usaran su?

Ver solución

Con su, todos tendrían que conocer y compartir la misma contraseña de root, y una vez adentro de esa sesión, los registros del sistema no distinguen quién de los seis hizo cada acción —todo queda como "root hizo esto". Con sudo -i, cada ingeniero se autentica con su propia contraseña, verificada contra sudoers, y cada invocación queda registrada contra su nombre de usuario real.

Por qué funciona: el equipo gana dos cosas que su no da —nadie necesita conocer ni compartir una contraseña maestra, y hay un registro auditable de quién ejecutó qué como root, en vez de una sesión anónima donde cualquiera de los seis pudo haber sido responsable.


Resumen y siguiente paso

Ya sabes cambiar el propietario y el grupo de un archivo con chown y chgrp, y por qué esa operación —a diferencia de chmod— casi siempre exige privilegios de root. Entiendes qué pasa exactamente cuando escribes sudo: te pide tu propia contraseña, no la de root; consulta sudoers para ver si tienes permiso para ese comando puntual; y eleva privilegios solo para esa línea, no para el resto de tu sesión. Sabes leer con sudo -l exactamente qué tienes permitido hacer, reconoces el antipatrón del sudo por reflejo que deja archivos con el dueño equivocado esperando romper algo más adelante, sabes inspeccionar un script antes de entregarlo a bash con privilegios, y entiendes por qué sudo -i es preferible a vivir instalado en una sesión de su.

Todo lo que viste en esta lección son formas de pedir prestado un privilegio para una tarea puntual —un archivo, un comando, un instalador—. Lo que sigue es lo que ese privilegio termina lanzando en la máquina: procesos. Todo comando que corres, con o sin sudo, se convierte en un proceso vivo con su propio identificador, y saber encontrarlo, leerlo y terminarlo con criterio —en vez de con kill -9 como primer recurso— es la otra mitad de diagnosticar en vez de adivinar.

Antes de avanzar deberías poder:

  • explicar por qué chown casi siempre requiere privilegios de root mientras que chgrp a veces no, y usar ambos para corregir un archivo con el dueño equivocado;
  • describir qué verifica sudo exactamente cuando te pide tu contraseña, y leer una línea de sudo -l para saber qué tienes permitido hacer y qué no;
  • identificar un caso de sudo por reflejo con solo mirar la salida de ls -l de un archivo o directorio, y corregirlo con chown -R en vez de repetir sudo para siempre;
  • explicar con tus propias palabras por qué sudo -i es preferible a su en una máquina que comparten varias personas.

Recursos