Encontrar arquivos que um usuário não pode ler?

12

Quero encontrar arquivos que um usuário em particular não possa ler.

Suponha que o nome de usuário seja "user123" e eles estejam em um grupo chamado "user123". Quero encontrar arquivos que, se pertencem ao user123, têm u + r; falhando que, se o arquivo for do grupo user123, ele deve ter g + r ativado; falhando que ele pode ter o + r ligado.

Como o GNU find tem "-readable", eu poderia fazer isso:

sudo -u user123 find /start ! -readable -ls

No entanto, o processo precisa ser executado por um usuário que não possui acesso ao sudo. Portanto, eu tentei o seguinte: (não verifica o + r, mas isso não é importante neste momento)

find /start \( -user user123 ! -perm -u=r  \) -o \( -group user123 ! -perm -g=r  \) -ls

mas lista este arquivo:

272118    4 -rw-------   1 user123   user123       3243 Jul  3 19:50 /start/blah/blah/file.txt

Este arquivo é o único arquivo /startpertencente ao user123 com g=rdesativado. É como se find estivesse interpretando o -u=ras -g=r.

Decidi tentar reverter a lógica e, em not ( truth )vez disso, testar :

find /etc/puppet ! \( \( -user puppet -perm -u=r  \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \)  -ls

Isso funciona!

Por que o original findfalhou? É um erro find(improvável) ou a lógica está errada?

Atualização: eu estava com a lógica errada. Como apontado abaixo, desde! (A || B || C) == (! A &&! B &&! C) estas são as duas instruções equivalentes:

find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls

Meu objetivo não era ter que testar usuário / grupo duas vezes. O que eu realmente preciso é de uma estrutura se-então-mais mais complicada, que provavelmente só seria possível se houvesse um operador -xor. Eu poderia criar um xor a partir e / ou não, mas seria mais complexo do que as duas soluções acima.

TomOnTime
fonte
1
Até a segunda lógica está errada, porque diria que puppettem acesso a um arquivo com --wxrwxrwx puppet puppet.
Stéphane Chazelas

Respostas:

7

A lógica está errada. Você está pensando que esse arquivo não deveria ter sido listado porque pertence user123e tem o rbit do usuário definido. No entanto, ele é listado porque corresponde ao segundo critério (pertence ao grupo user123e tem o rbit do grupo não definido).

Sua segunda versão funciona devido a uma das leis de Morgan : negar o ORing lógico de um grupo de declarações é logicamente equivalente a ANDing a negação das declarações individuais. Em outras palavras:

 ! ( A || B || C ) == ( !A && !B && !C )

Então, o trabalho findestá procurando um arquivo que

  • Não é (de propriedade do usuário user123e legível pelo usuário) AND
  • Não é (pertencente ao grupo user123e legível pelo referido grupo) AND
  • Não é legível para o mundo.

enquanto o primeiro findestá procurando um arquivo que

  • É de propriedade do usuário user123e não pode ser lido pelo referido usuário OU
  • É de propriedade do grupo user123e não pode ser lido pelo referido grupo OU (se você o tiver concluído)
  • Não é legível para o mundo

Portanto, um arquivo que corresponda a QUALQUER dos três critérios acima (e não necessariamente a todos) será listado como você viu.

Editar

Aliás (depois de ver o seu perfil), sou um grande fã do seu livro O'Reilly :)

Joseph R.
fonte
Obrigado pela análise. Sim, foi uma aplicação incorreta da lei de Morgan. Eu estava tentando fazer, ( !A && !B && !C )mas mudei !para o interior de cada parte, o que não é válido. Obrigado!
TomOnTime 29/08
PS Fico feliz que você é um fã do meu livro! Estou curioso para saber em que idioma você o lê.
TomOnTime 29/08
@TomOnTime Inglês, é claro. Tento ler qualquer livro em seu idioma original, se posso ajudá-lo.
Joseph R.
8

Há muito mais coisas a serem levadas em consideração para verificar se um usuário tem acesso a um arquivo por um determinado caminho:

  • O proprietário do arquivo
  • o grupo do arquivo
  • as ACLs no arquivo
  • os uid, gid e gids complementares do usuário
  • procure o acesso a qualquer componente do caminho que leva a esse arquivo.
  • se o arquivo é um link simbólico
  • permissões se aplicam de maneira diferente para usuários com o ID 0.
  • possivelmente mais recursos de segurança como o SELinux ...

Antes de realmente mudar todos os uids e gids para os do usuário e verificar, é muito difícil implementar a mesma lógica que o sistema faz.

Com o zsh, você pode fazer (como root):

readable() (
  USERNAME=$u
  [ -r "$REPLY" ]
)
u=some-user
print -rl -- **/*(DoN^+readable)

Ou com perl:

find . -print0 | sudo -u some-user perl -Mfiletest=access -l -0ne '
  print unless -r'

Nos dois casos, desça a árvore de diretórios, rootmas teste o acesso ao arquivo como o usuário correspondente.

Executando find -readablecomo some-usernão, nos casos em que não poderá passar pelos diretórios para os quais o usuário não tem acesso ou permissão de leitura (mas possivelmente acesso).

Mesmo considerando apenas a permissão e a propriedade do próprio arquivo (e não ACLs ou componentes de caminho ...), você precisa de pelo menos (aqui sintaxe GNU):

u=some-user; g=$(id -G "$u" | sed 's/ / -o -group /g'); IFS=" "
find . ! \( -user "$u" -perm -u=r -o \
          ! -user "$u" \( -group $g \) -perm -g=r -o \
          ! -user "$u" ! \( -group $g \) -perm -o=r \)

A ideia é que, se o arquivo pertencer ao usuário, todas as outras permissões serão irrelevantes. Caso contrário, se o arquivo pertencer a um grupo de qualquer um dos grupos de usuários, a permissão "other" será irrelevante.

Stéphane Chazelas
fonte
1
Bom argumento sobre ACLs e outros fatores. A única avaliação 100% correta é access()que ela usa o mesmo código do kernel que open(). Assim sudo -u user123 find /start -readableé a melhor solução se sudofor uma opção.
TomOnTime 29/08
1
@TomOnTime. Bem, não, se você usar sudo -u user123 find -readable, ele não reportará arquivos em diretórios que você não pode entrar ou em diretórios que você não pode ler (portanto, haverá falsos negativos e positivos). É por isso que eu sugiro usar zshpara descer da árvore de diretórios como root e fazer access()( [ -r ... ]) como o usuário real (ajuste $USERNAMEem zshmudanças todos os UIDs e GIDs como sudofaria).
Stéphane Chazelas