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:
sudote 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.- Con tu identidad confirmada,
sudoconsulta el archivo de política/etc/sudoerspara 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). - Si
sudoerslo autoriza,sudoejecuta solo ese comando con privilegios elevados, y en cuanto termina, vuelves a ser tu usuario normal para la siguiente línea que escribas. - Para no pedirte la contraseña en cada línea,
sudoguarda 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
curlen 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,
bashpuede 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é
chowncasi siempre requiere privilegios de root mientras quechgrpa veces no, y usar ambos para corregir un archivo con el dueño equivocado; - describir qué verifica
sudoexactamente cuando te pide tu contraseña, y leer una línea desudo -lpara saber qué tienes permitido hacer y qué no; - identificar un caso de
sudopor reflejo con solo mirar la salida dels -lde un archivo o directorio, y corregirlo conchown -Ren vez de repetirsudopara siempre; - explicar con tus propias palabras por qué
sudo -ies preferible asuen una máquina que comparten varias personas.
Recursos
- sudo(8) — Linux manual page — referencia
oficial de
sudo: por qué pide tu propia contraseña, la caché de credenciales de cinco minutos, y las opciones-l,-iy-s. - sudoers(5) — Linux manual page —
sintaxis completa del archivo
/etc/sudoers, incluida la etiquetaNOPASSWDy ejemplos de reglas restrictivas por usuario y por comando. - visudo(8) — Linux manual page — por qué
sudoersse edita siempre convisudoy nunca con un editor directo. - chown(1) — Linux manual page — sintaxis
completa de
chown, incluidas las variantesusuario:grupoy la opción-R. - su(1) — Linux manual page — qué contraseña
pide
suexactamente, y la diferencia entresuysu -(shell de login). - Friends don't let friends curl | bash — Sysdig — los riesgos concretos de los instaladores de una línea: verificación nula, descargas interrumpidas y contenido servido distinto según quién pregunta.