Terminal: lista todos os diretórios para os quais um usuário ou grupo possui permissão de gravação

7

Gostaria de listar todos os diretórios para os quais um usuário ou grupo tem permissões de gravação.

Encontrei essa pergunta no ServerFault , mas ela endereça um Windows Server, então estou otimista de que há algo melhor para nós na comunidade Linux. Ao mesmo tempo, percebo que há uma reviravolta recursiva a essa questão que pode torná-la impossível sem um script de longa duração.

Estou ciente dos seguintes comandos úteis:

  • Listar todos os grupos: cut -d : -f 1 /etc/group
  • Listar todos os usuários: cut -d : -f 1 /etc/passwd
  • Obtenha o diretório inicial de um usuário: getent passwd user-name| cut -d: -f 6
  • Este script que lista cada usuário e suas atribuições de grupo
  • Obtenha permissões e detalhes do usuário / grupo no conteúdo da pasta: ls -la

No entanto, quando não tenho a menor ideia do objetivo de um usuário, seria interessante abrir uma lista de TODOS os diretórios para os quais eles têm permissão de gravação e começar a procurar por lá. Se nada mais é uma auditoria super útil ..

Se isso ajuda a entender o meu propósito, eu herdei (ou estou pelo menos baby-sitting?) alguns sistemas depois que o nosso SysAdmin assumiu uma nova posição. Então, tenho tentado entender a evolução desses dois sistemas, como qual software está instalado e onde (..ugh), onde vários arquivos de configuração vivem, e agora, quais grupos e usuários diferentes foram criados - incluindo os diretórios que eles podem gravar. Normalmente eu posso encontrar comandos de terminal úteis aqui no askubuntu, mas não encontrando este, pensei em ir em frente e perguntar.

O sistema exato é o Ubuntu 10.04.2, mas também suportamos o Ubuntu 12.04.5, então a solução mais independente da versão seria a melhor. Agradecemos antecipadamente por qualquer ajuda.

[Atualização: resultados iniciais para as duas respostas rápidas]

Vale a pena notar que estou logado como root para estes, e / era meu diretório de trabalho. Além disso, eles levaram um tempo comparável para serem executados.

@ O comando combinado de Rinzwind obteve a seguinte saída em cerca de 5,5 min.

root@tatooine:/# sudo find -type d \( \( -user ftpgisdata -perm /u=w \) -o \( -group ftpgisdata -perm /g=w \) -o -perm /o=w \)
./tmp
./tmp/.ICE-unix
./tmp/.X11-unix
find: './proc/6594/task/6594/fd/5': No such file or directory
find: './proc/6594/task/6594/fdinfo/5': No such file or directory
find: './proc/6594/fd/5': No such file or directory
find: './proc/6594/fdinfo/5': No such file or directory
./var/tmp
./var/lib/php5
./var/crash
./var/lock
./home/ftpgisdata
./home/ftpgisdata/.ssh
./home/ftpgisdata/.cache
./home/sitename-i-changed.com/wp-content/profile-pics
./dev/shm

@ O comando revisado de Oli recebe algo muito semelhante, também em cerca de 5,5 minutos.

root@tatooine:/# sudo find / -type d -print0 | sudo -u ftpgisdata xargs -0 sh -c 'for p; do [ -w "$p" ] && echo "$p"; done' -
/tmp
/tmp/.ICE-unix
/tmp/.X11-unix
find: '/proc/15541': No such file or directory
find: '/proc/15542': No such file or directory
find: '/proc/15543': No such file or directory
find: '/proc/15567': No such file or directory
find: '/proc/15568/task/15568/fd/5': No such file or directory
find: '/proc/15568/task/15568/fdinfo/5': No such file or directory
find: '/proc/15568/fd/5': No such file or directory
find: '/proc/15568/fdinfo/5': No such file or directory
/var/tmp
/var/lib/php5
/var/crash
/var/lock
/home/ftpgisdata
/home/ftpgisdata/.ssh
/home/ftpgisdata/.cache
/home/sitename-i-changed.com/wp-content/profile-pics
/dev/shm

@PeterCordes answer também retornou resultados semelhantes em cerca de 5,5 minutos.

root@tatooine:~# username_to_check=ftpgisdata base_dir=/   # for example
root@tatooine:~# sudo -u "$username_to_check" find "$base_dir" -type d -writable  2>/dev/null ## GNU find, not POSIX
/tmp
/tmp/.ICE-unix
/tmp/.X11-unix
/proc/7159/task/7159/fd
/proc/7159/fd
/proc/7159/map_files
/var/tmp
/var/lib/php5
/var/crash
/var/lock
/home/ftpgisdata
/home/ftpgisdata/.ssh
/home/ftpgisdata/.cache
/home/sitename-i-changed.com/wp-content/profile-pics
/dev/shm
    
por elrobis 16.03.2016 / 19:28

4 respostas

7

Trabalhar fora do que um usuário pode fazer é difícil se você não for esse usuário. Você pode testar várias coisas (é proprietário, mesmo grupo, etc), mas a ACL pode se aplicar, pode não haver permissões na montagem, quem sabe. É difícil.

Se você puder transformar esse usuário, poderá test -w <path> para ver se ele pode escrever. Isso não é tão rápido quanto apenas olhar para o inode, mas é possível com sudo .

sudo -u oli test -w <path> && echo "HOORAY"

Podemos, então, dividir isso no back-end de find . Em vez de usar apenas -exec para mudar para o usuário oli repetidas vezes (veja as revisões anteriores), colocamos tudo em uma instância de xargs executando como oli. Isso é muito mais rápido.

sudo find / -type d -print0 | sudo -u oli xargs -0 -I{} sh -c 'test -w "$0" && echo "$0"' {}

Uma versão um pouco otimizada (mas visualmente mais flácida) envolve a minimização da quantidade de subshells que os xargs executam, canalizando um fluxo de caminhos para um número baixo de subshells bash. Isso é, sem dúvida, mais rápido para grandes pesquisas.

sudo find / -type d -print0 | sudo -u oli xargs -0 sh -c 'for p; do [ -w "$p" ] && echo "$p"; done' -
    
por Oli 16.03.2016 / 19:49
4

No bate-papo, chegamos às seguintes instruções para usuário e grupo:

sudo find / -type d -user rinzwind -perm /u=w
sudo find / -type d -group rinzwind -perm /g=w
sudo find / -type d -perm /o=w

Ou combine todos os três em um:

sudo find -type d \( \( -user rinzwind -perm /u=w \) -o \( -group rinzwind -perm /g=w \) -o -perm /o=w \)

Sem o / ele pesquisa o diretório atual.

Demorei menos de 2 segundos em 67Gb de dados no meu sistema;)

    
por Rinzwind 16.03.2016 / 19:58
2

Resposta em construção, por favor, seja paciente

Teste para si mesmo

Pode-se testar permissões de escrita para si mesmo com o seguinte código:

[ -w /home/$USER ] && echo yes # using home directory as example

Usando -d flag para teste, podemos testar se algo é um diretório.

Sabendo tudo isso e find nós podemos fazer

find /home/ -print0 2> /dev/null | while IFS=""  read -r -d "" file ; do [ -d "$file"  ] &&  [ -w "$file" ]  && echo "$file" is writeable ; done

Nota lateral: Obviamente, se você obtiver erros de permissão com o find, não poderá ler esse arquivo, portanto, não há razão para gerar esses erros, portanto, o redirecionamento para o dev null. Obviamente, isso não funcionará se quisermos descobrir permissões para outros usuários além de si mesmo, e note que / home é apenas um exemplo aqui. Pastas como /var têm pastas compartilhadas entre vários usuários

Teste para outras pessoas

Pode-se usar stat por cada arquivo encontrado pelo find e filtrá-lo com o awk

 find /var -type d -exec stat --format '%g %n'  {} \; 2> /dev/null | awk '$1=='1000'{print}' 

Aqui estou filtrando por ID numérica do meu próprio usuário, 1000, mas pode ser um ID de qualquer usuário. Claro que se pode jogar com opções, use o nome do grupo ao invés de ids numéricos. É algo que é muito flexível e adaptável ao propósito que você precisa

Pequenos ajustes

Então notei que você mencionou estar logado como root. Aqui está uma saída do meu comando, onde eu declaro os arquivos e imprimo o nome do grupo e do arquivo, e depois filtro usando o AWK pelo nome do grupo apropriado.

$ find /proc -type d -exec stat --format '%G %n'  {} \; 2> /dev/null  | awk '$1=="syslog"{print}'
syslog /proc/560
syslog /proc/560/task
syslog /proc/560/task/560
syslog /proc/560/task/560/net
syslog /proc/560/task/560/attr
syslog /proc/560/task/562
syslog /proc/560/task/562/net
syslog /proc/560/task/562/attr
syslog /proc/560/task/563
syslog /proc/560/task/563/net
syslog /proc/560/task/563/attr
syslog /proc/560/task/564
syslog /proc/560/task/564/net
syslog /proc/560/task/564/attr
syslog /proc/560/net
syslog /proc/560/attr
^C
    
por Sergiy Kolodyazhnyy 16.03.2016 / 20:26
2

Se você tiver o GNU find, você pode usar o -writable test (observe a ortografia, não é writeable ). Isso usa a chamada do sistema access(2) em vez de apenas tentar descobrir as permissões, para que funcione corretamente com as ACLs. (Mas pode quebrar no NFS com mapeamentos de ID).

Ele também encontrará diretórios graváveis pelo usuário, por ser um membro de um grupo secundário. (por exemplo, um diretório em /usr/local gravável por usuários no grupo admin , ou algo parecido com chown root:users /data/share && chmod 2775 /data/share , em que algumas contas são membros do grupo users .)

username_to_check=peter base_dir=/   # for example
sudo -u "$username_to_check" find "$base_dir" -type d -writable  2>/dev/null ## GNU find, not POSIX

Haverá erros quando find encontrar diretórios nos quais o usuário não pode entrar, então redirecionamos os erros para /dev/null .

Isso não encontrará nenhum diretório que possa ser gravado, mas dentro de diretórios, sem permissão de execução, porque find em execução como o usuário não pode percorrer os diretórios superiores. No entanto, se um processo que eles possuem for iniciado dentro de um diretório, eles poderão gravar nele com caminhos relativos. (ou eles pegam um descritor de arquivo aberto para tal diretório, eles podem usar openat(2) ). pwd não funcionará se eles não tiverem permissão de execução em um dos componentes de diretório do caminho completo, por isso não é uma configuração comum.

Isso também perde os diretórios graváveis que estão dentro dos diretórios executáveis, mas não legíveis . Para contornar essas limitações, provavelmente execute find -type d como root e use find -writable como usuário para verificar os caminhos resultantes. Isso pode ser mais eficiente que um loop de shell usando [ -w "$f" ] .

POSIX find(1) tem muito menos opções do que o GNU find. Se o seu script tiver que ser portável para o POSIX, é provavelmente mais fácil canalizar para outra coisa que verifique as permissões, como um shell com [ -w "$f" ] (veja a outra resposta que sugere isso).

    
por Peter Cordes 17.03.2016 / 02:55