Administração Linux
Usuários, grupos e permissões no Linux: bits rwx, umask, ACLs e sudo
Iniciante11 min de leituraAtualizado
Esta página foi traduzida do inglês com a ajuda de IA e conferida com o original. Ler a versão em inglês
Em uma máquina Linux, toda decisão de acesso se resume a um ID numérico de usuário, um conjunto de IDs de grupo e doze bits associados a um arquivo. Este guia mostra onde as contas ficam armazenadas, como o kernel avalia uma verificação de permissão e como ampliar ou restringir o acesso com segurança usando chmod, umask, ACLs e sudo. Ele termina com SSH baseado em chaves, o mecanismo de login que você deveria usar em qualquer servidor exposto à rede.
O que você vai aprender
- Descrever como contas, grupos primários e grupos suplementares são armazenados e criados
- Ler e definir modos de arquivo nas formas simbólica e octal, e prever o que o umask vai produzir
- Explicar o que setuid, setgid e o sticky bit fazem e onde cada um tem uso legítimo
- Conceder uma exceção a um usuário ou grupo específico com uma ACL POSIX em vez de afrouxar o modo
- Delegar comandos administrativos com regras de sudo e fazer login com um par de chaves SSH
Permissões são a primeira coisa que um sistema Linux verifica e a última que a maioria das pessoas aprende direito. O modelo é pequeno o bastante para caber na cabeça — um ID numérico de usuário, uma lista de IDs de grupo e doze bits por arquivo —, mas é nos detalhes que você tropeça: por que um chmod 777 em um diretório web é ao mesmo tempo um problema de segurança e, em geral, nem sequer a solução; por que se adicionar ao grupo docker não tem efeito até você fazer logout; por que uma pasta compartilhada vive gerando arquivos que mais ninguém consegue editar.
Este guia começa pelas próprias contas, passa pelos bits rwx clássicos e pelos bits especiais acima deles e depois trata dos dois mecanismos a que você recorre quando o modelo clássico não é granular o suficiente: listas de controle de acesso e sudo. Os exemplos pressupõem um sistema Debian, Ubuntu ou da família RHEL atual. Se o formato de saída do ls -l ainda não é familiar, leia antes o guia sobre o sistema de arquivos.
Quem você é para o kernel
O kernel não conhece nomes de usuário. Ele conhece um ID de usuário (UID) e um conjunto de IDs de grupo (GIDs) associados a cada processo. Os nomes existem só para que pessoas consigam ler a saída; a tradução acontece em espaço de usuário, por meio de /etc/passwd, /etc/group e do serviço de diretório que a máquina estiver configurada para consultar.
$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),110(www-data)
O /etc/passwd tem uma linha por conta, com campos separados por dois-pontos: nome, um x no lugar onde antes ficava o hash da senha, UID, GID primário, um campo de comentário livre, diretório home e shell de login. Ele é legível por todos porque muitos programas precisam mapear IDs para nomes.
alice:x:1000:1000:Alice Martin:/home/alice:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
Os hashes de senha de verdade ficam em /etc/shadow, legível apenas pelo root, junto com as informações de envelhecimento da senha: quando ela foi alterada pela última vez, validade mínima e máxima, período de aviso e data de expiração. Um ! ou * no campo do hash significa que nenhuma senha jamais vai corresponder, e é assim que contas de serviço são bloqueadas. Essas contas também recebem /usr/sbin/nologin como shell, para que nem uma autenticação bem-sucedida consiga abrir uma sessão interativa.
Na maioria das distribuições, UIDs abaixo de 1000 são reservados ao sistema; usuários humanos começam em 1000. O UID 0 é especial no próprio kernel: é o superusuário, e a maioria das verificações de permissão simplesmente é ignorada para ele.
Criando e modificando contas
sudo useradd -m -s /bin/bash -c "Bob Chen" bob # -m creates and populates /home/bob
sudo passwd bob
sudo usermod -aG www-data,sudo bob # -a is essential: append, do not replace
sudo usermod -L bob # lock the password
sudo userdel -r bob # -r also removes the home directory
Debian e Ubuntu também trazem o adduser, um wrapper interativo que escolhe padrões sensatos e pede a senha. Seja qual for a ferramenta, a flag mais importante é o -a no usermod -G: sem ela, a lista de grupos suplementares é substituída, e mais de um administrador já perdeu o acesso ao sudo desse jeito.
Diretórios home novos são preenchidos a partir de /etc/skel, então tudo o que você colocar ali — um .bashrc padrão, uma configuração de editor, um diretório .ssh com o modo certo — é copiado para cada conta criada depois.
Grupos primários e suplementares
Cada conta tem exatamente um grupo primário, registrado em /etc/passwd e usado como grupo dono dos arquivos que ela cria. Ela pode ainda pertencer a qualquer número de grupos suplementares, listados em /etc/group.
www-data:x:33:alice,bob
developers:x:1500:alice,bob,carol
A maioria das distribuições cria um grupo privado por usuário (alice:alice), de modo que um modo padrão 0644 não concede nada a mais ninguém, mesmo que o arquivo seja movido depois para uma área compartilhada. O acesso compartilhado passa então a ser expresso criando um grupo com nome que indique sua finalidade e adicionando membros a ele.
Como as credenciais são definidas no início da sessão, o id é a fonte da verdade sobre o que seus processos atuais podem fazer, enquanto /etc/group mostra o que o seu próximo login vai receber. Se você não puder fazer logout, newgrp developers abre um subshell com a nova participação.
Os doze bits
Todo arquivo tem um UID dono, um GID de grupo e um modo: três conjuntos de três bits, mais três bits especiais por cima.
| Bit | Em um arquivo comum | Em um diretório |
|---|---|---|
r | ler o conteúdo | listar os nomes que ele contém |
w | modificar o conteúdo | criar, renomear e excluir entradas |
x | executá-lo como programa | atravessá-lo, ou seja, resolver nomes através dele |
O kernel avalia em uma ordem rígida e para na primeira correspondência: se o seu UID é igual ao do dono, vale o trio do dono e nada mais é consultado; caso contrário, se algum dos seus GIDs corresponde ao grupo do arquivo, vale o trio do grupo; senão, vale o trio de outros. É por isso que ----rwxrwx nega tudo ao dono e libera para todos os demais — uma ordem que surpreende quem imagina que os conjuntos se somam.
Duas consequências decorrem da linha de diretórios da tabela. Primeiro, excluir um arquivo é uma escrita no diretório, não no arquivo, então você consegue remover um arquivo somente leitura de um diretório em que pode escrever. Segundo, x sem r em um diretório é um padrão útil: você consegue abrir /srv/data/report.pdf se souber o nome, mas não consegue listar o que existe ali.
Modos octais
Cada trio é um número de três bits: r=4, w=2, x=1. Basta somar.
| Octal | Simbólico | Uso típico |
|---|---|---|
644 | rw-r--r-- | arquivos comuns de dados e de configuração |
600 | rw------- | chaves privadas, credenciais, ~/.ssh/id_ed25519 |
755 | rwxr-xr-x | programas, scripts e a maioria dos diretórios |
750 | rwxr-x--- | um diretório compartilhado com um único grupo |
775 | rwxrwxr-x | um diretório em que um grupo pode escrever |
700 | rwx------ | um diretório privado como ~/.ssh |
O chmod aceita as duas formas. A simbólica é relativa e muitas vezes mais segura, porque altera apenas os bits que você nomeia:
chmod 640 /etc/myapp/secrets.env
chmod u+x deploy.sh # add execute for the owner only
chmod go-w,o-rx /srv/private # remove group write, and all "other" access
chmod -R u=rwX,g=rX,o= /srv/app # capital X: execute only where it is already set, or on directories
Vale guardar esse X maiúsculo: chmod -R 755 marca todos os arquivos de dados como executáveis, enquanto chmod -R u=rwX,go=rX corrige os diretórios sem mentir sobre quais arquivos são programas.
A posse é alterada com chown e chgrp, e só o root pode transferir um arquivo para outra pessoa:
sudo chown -R www-data:www-data /var/www/example.com
sudo chgrp developers /srv/shared
sudo chown --reference=/etc/nginx/nginx.conf /etc/nginx/conf.d/site.conf
umask: as permissões com que os arquivos nascem
Os programas pedem um modo ao criar um arquivo — por convenção, 0666 para dados e 0777 para diretórios. O umask do processo remove bits desse pedido antes de o arquivo ser criado. É uma máscara de bits a zerar, não a conceder.
Com o padrão comum 022, um arquivo novo recebe 0666 & ~022 = 0644 e um diretório novo 0777 & ~022 = 0755. Com umask 027, o mesmo arquivo vira 0640 e o diretório 0750, invisíveis para usuários de fora do grupo. Use umask 077 em uma máquina onde nada deve ser compartilhado por padrão.
$ umask
0022
$ umask 027; touch a; mkdir b; ls -ld a b
-rw-r----- 1 alice alice 0 Sep 7 11:20 a
drwxr-x--- 2 alice alice 4096 Sep 7 11:20 b
Como o umask é uma propriedade do processo, ele é herdado pelos processos filhos e precisa ser definido onde o processo começa: em /etc/profile ou ~/.profile para shells de login, com uma diretiva UMask= em um serviço do systemd ou na configuração do próprio daemon. Observe que arquivos nunca recebem o bit de execução a partir de um pedido 0666, e é por isso que um script extraído de um arquivo compactado tantas vezes precisa de um chmod +x explícito.
setuid, setgid e o sticky bit
Acima dos nove bits de permissão ficam mais três, exibidos nas posições x do ls -l.
setuid (4000, um s no trio do dono) faz um executável rodar com os privilégios do seu dono, e não de quem o chama. /usr/bin/passwd é o exemplo clássico: um usuário sem privilégios precisa conseguir reescrever uma linha de /etc/shadow, e o setuid root é o que torna isso possível. O setuid é poderoso e historicamente foi a origem de muitas escalações de privilégio locais, então o lugar dele é nos binários da distribuição e praticamente em nenhum outro. Procurar surpresas cabe em uma linha:
sudo find / -xdev -type f -perm -4000 -printf '%M %u %p\n' 2>/dev/null
setgid (2000) faz o mesmo com o grupo em um executável, mas sua forma mais útil é em um diretório: arquivos criados dentro dele herdam o grupo do diretório em vez do grupo primário de quem os criou, e novos subdiretórios também herdam o bit setgid. É a receita padrão para uma área de projeto compartilhada.
sudo install -d -o root -g developers -m 2775 /srv/projects
O sticky bit (1000, um t no trio de outros) faz com que, em um diretório gravável por todos, só o dono de cada arquivo possa apagá-lo. O /tmp é drwxrwxrwt exatamente por isso: qualquer um pode criar arquivos ali, ninguém pode apagar os de outra pessoa.
chmod 2775 /srv/projects # setgid directory
chmod 1777 /srv/scratch # sticky, world-writable
chmod g+s,o-rwx /srv/team # symbolic equivalents
Diretórios setgid fixam o grupo, mas não o modo, então um membro que cria um arquivo com umask 022 ainda produz rw-r--r--, que os colegas não conseguem editar. Combine o bit setgid com umask 002 para os usuários envolvidos ou use uma ACL, que é a melhor resposta.
ACLs, quando três conjuntos não bastam
Uma lista de controle de acesso (ACL) POSIX associa a um arquivo entradas nomeadas de usuários e grupos, para que você possa dar acesso a mais uma pessoa sem inventar um grupo nem afrouxar other. O sistema de arquivos precisa estar montado com suporte a ACL, o que é o padrão para ext4 e XFS nos kernels atuais.
$ setfacl -m u:jenkins:rx /srv/app/bin
$ setfacl -m g:auditors:r /var/log/app/audit.log
$ getfacl /srv/app/bin
# file: srv/app/bin
# owner: deploy
# group: deploy
user::rwx
user:jenkins:r-x
group::r-x
mask::r-x
other::---
O ls -l marca um arquivo que tem ACL com um + no final. A entrada mask é um teto para todas as entradas nomeadas e para a classe de grupo; em um arquivo com ACL, chmod g= ajusta a máscara e não a entrada do grupo, o que explica a confusão ocasional do tipo “eu concedi e continua sem funcionar”.
As ACLs padrão de um diretório são o mecanismo de herança que falta aos bits clássicos. Elas se aplicam às entradas criadas depois, então um usuário de deploy pode manter acesso de escrita a tudo o que um build colocar em uma árvore:
sudo setfacl -R -m u:deploy:rwx -m d:u:deploy:rwx /var/www/example.com
sudo setfacl -x u:jenkins /srv/app/bin # remove one entry
sudo setfacl -b /srv/app/bin # remove the whole ACL
Use ACLs de forma deliberada e documente-as. Em um ls -l simples, nada as denuncia além daquele +, e um enigma de permissões que ninguém consegue explicar é pior do que um grupo meio desajeitado.
Delegando privilégios com sudo
A prática moderna é desativar o login direto como root e conceder privilégios específicos por meio do sudo. A política fica em /etc/sudoers e, de preferência, em arquivos dentro de /etc/sudoers.d/. Edite sempre com o visudo, que valida a sintaxe antes de instalar o arquivo.
# /etc/sudoers.d/deploy (mode 0440, edited with: sudo visudo -f /etc/sudoers.d/deploy)
Cmnd_Alias APPCTL = /usr/bin/systemctl restart app, /usr/bin/systemctl status app
%developers ALL=(ALL) APPCTL
deploy ALL=(www-data) NOPASSWD: /usr/bin/rsync
Leia uma regra como quem host=(como quem) o quê. A primeira linha permite que membros do grupo developers reiniciem um serviço depois de digitar a própria senha. A segunda permite que a conta deploy rode rsync como www-data sem senha, que é exatamente do que um pipeline automatizado precisa.
Dois hábitos mantêm o sudo sob controle. Conceda comandos, não shells: %developers ALL=(ALL) NOPASSWD: ALL é acesso root com passos extras, e qualquer comando permitido que consiga abrir um shell ou editar um arquivo arbitrário (vi, less, find, tar) equivale a root completo. E preserve o log: cada invocação é registrada no journal ou no syslog, o que faz do journalctl -t sudo uma trilha de auditoria realmente útil, como mostra o guia de logs e solução de problemas.
Fazendo login com chaves em vez de senhas
A autenticação SSH por senha atrai ataques de força bruta a partir do momento em que uma máquina ganha um endereço público. Pares de chaves eliminam por completo o segredo que dá para adivinhar.
ssh-keygen -t ed25519 -C "alice@laptop" # private key stays on your machine
ssh-copy-id [email protected] # appends the public key remotely
ssh -o PreferredAuthentications=publickey [email protected]
A chave privada precisa ter modo 600 e o diretório ~/.ssh, 700; o sshd recusa chaves legíveis pelo grupo ou por todos, e recusa o authorized_keys se o próprio diretório home for gravável pelo grupo. Quando todas as contas que precisam de acesso tiverem uma chave, faça o hardening do daemon em /etc/ssh/sshd_config.d/:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AllowGroups sshusers
Valide com sudo sshd -t e faça reload em vez de restart, e — esta é a parte que o pessoal pula — mantenha sua sessão atual aberta enquanto testa uma nova a partir de outro terminal. Um erro de digitação no sshd_config de uma máquina remota é, na melhor das hipóteses, um chamado de suporte.
Erros comuns
chmod 777 como passo de depuração. Dá acesso de escrita a todos os usuários da máquina e raramente resolve o problema real, que costuma ser um dono errado ou um x faltando em um diretório pai. Encontre o ponto do caminho que falha com namei -l /var/www/example.com/index.php.
usermod -G sem -a. Remove silenciosamente todos os outros grupos suplementares, incluindo sudo e wheel.
chmod recursivo com modo numérico. chmod -R 755 torna executáveis todos os arquivos de configuração e imagens. Use u=rwX,go=rX, ou find … -type d -exec chmod 755 e -type f -exec chmod 644.
Achar que permissões protegem o histórico de um arquivo. Restringir um modo não faz nada pelas cópias já feitas, e um segredo que entrou em um commit no Git ou foi gravado em uma imagem de contêiner continua lá. Faça a rotação dele.
Esquecer que o root ignora os bits. Um modo somente leitura não protege contra um processo root, nem dentro de um contêiner que roda como root com o caminho montado via bind mount.
Mudanças de grupo sem uma nova sessão. O id reflete a sessão; confira ali antes de concluir que o grupo não fez efeito.
Principais pontos
- O kernel autoriza por UID e GID; os nomes vêm de
/etc/passwde/etc/group, e os hashes e a expiração, de/etc/shadow. - As verificações de permissão param na primeira classe correspondente — dono, depois grupo, depois outros —, então os trios nunca se somam.
- Em diretórios,
xsignifica atravessar ewsignifica criar ou excluir, e é por isso que dá para apagar um arquivo somente leitura e que umxfaltando quebra um caminho inteiro. - O
umasksubtrai bits no momento da criação; defina-o no perfil de login ou em uma unit de serviço, não a posteriori. - setgid em um diretório resolve a herança de grupo, o sticky bit protege diretórios graváveis por todos e o setuid pertence quase exclusivamente aos binários da distribuição.
- Recorra a uma ACL POSIX, com uma entrada padrão para herança, quando um usuário ou grupo precisar de uma exceção; recorra a regras de
sudolimitadas a comandos específicos quando uma pessoa precisar de privilégios. - Troque as senhas do SSH por pares de chaves, depois desative
PasswordAuthenticatione verifique a partir de uma segunda sessão antes de fechar a primeira.
Fontes e leituras complementares
Perguntas frequentes
- Por que não consigo entrar em um diretório mesmo que os arquivos dele sejam legíveis?
- Diretórios usam o bit de execução de outro jeito: x significa o direito de atravessar o diretório, ou seja, de resolver um nome dentro dele. Sem x em cada diretório do caminho, o kernel para antes mesmo de olhar o arquivo. Um diretório com r mas sem x permite listar os nomes, mas não fazer stat nem abrir nada, e é por isso que 0644 em um diretório quase sempre é um erro.
- Eu me adicionei a um grupo, mas continuo recebendo “permission denied”. O que está errado?
- A participação em grupos é copiada para as credenciais do processo no momento do login. Seu shell atual foi iniciado antes da mudança, então ainda carrega a lista antiga. Faça logout e login de novo, abra uma nova sessão ou rode newgrp nomedogrupo no shell em que você está. Confira a lista efetiva com o comando id, e não lendo /etc/group, porque o kernel usa o que foi atribuído à sua sessão.
- Devo editar o /etc/sudoers diretamente?
- Não. Use o visudo, que bloqueia o arquivo e se recusa a instalar uma versão que não passe na verificação de sintaxe. Um arquivo sudoers malformado pode impedir que qualquer administrador eleve privilégios naquela máquina. Melhor ainda: coloque um arquivo pequeno em /etc/sudoers.d/ e edite-o com visudo -f, assim as atualizações de pacotes nunca entram em conflito com suas regras e cada delegação fica em seu próprio arquivo.
- Qual é a diferença entre su e sudo?
- O su abre um shell como outro usuário e pede a senha desse usuário, então quem o usa precisa das credenciais da conta de destino. O sudo executa um único comando segundo uma política guardada em /etc/sudoers, autentica com a senha de quem o chama e registra cada execução. O sudo permite delegar com precisão e auditar depois, e é por isso que a maioria das distribuições hoje desativa completamente o login direto como root.