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

11

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

Suponha que o nome de usuário seja "user123" e eles estão em um grupo chamado "user123". Eu quero encontrar arquivos que, se eles são de propriedade do usuário 123 têm u + r on; Caso contrário, se o arquivo for group user123, ele deverá ter g + r on; falhando que pode ter o + r on.

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

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

No entanto, o processo deve ser executado por um usuário que não tenha acesso ao sudo. Portanto, eu tentei isso: (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 em /start que pertence ao user123 com g=r off. É como se find estivesse interpretando o -u=r as -g=r .

Eu decidi tentar inverter a lógica e, em vez disso, testar not ( truth ) :

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 find falhou? É um erro em find (improvável) ou a lógica está errada?

Atualização: Eu tive a lógica errada. Como apontado abaixo, desde     ! (A || B || C) == (! A &; B & & C) estas são as duas declaraçõ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 if-then-else mais complicada, que provavelmente só seria possível se houvesse um operador -xor. Eu poderia construir um xor de e / ou não, mas seria mais complexo do que as duas soluções acima.

    
por TomOnTime 28.08.2013 / 19:28

2 respostas

7

A lógica está errada. Você está pensando que esse arquivo não deveria ter sido listado porque é de propriedade de user123 e tem o r bit do usuário configurado. No entanto, ele está listado porque corresponde ao segundo critério (é de propriedade do grupo user123 e tem o r bit do grupo não definido).

Sua segunda versão funciona devido a uma das leis de Morgan : negando a ORing lógica 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 )

Portanto, o trabalho find está procurando por um arquivo que

  • Não é (pertence ao usuário user123 e pode ser lido pelo usuário) E
  • Não é (pertencente ao grupo user123 e legível pelo dito grupo) E
  • Não é legível pelo mundo.

enquanto o primeiro find está procurando por um arquivo que

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

Assim, um arquivo correspondente a QUALQUER um dos 3 critérios acima (e não necessariamente todos) seria listado como você viu.

Editar

Por acaso (depois de ver o seu perfil), eu sou um grande fã do seu livro O'Reilly:)

    
por 28.08.2013 / 19:40
6

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

  • O proprietário do arquivo
  • o grupo do arquivo
  • as ACLs no arquivo
  • os recursos uid, gid e suplementares do usuário
  • pesquisar o acesso a qualquer componente de caminho que leve a esse arquivo.
  • se o arquivo é um link simbólico
  • As permissões
  • aplicam-se de forma diferente aos usuários do ID 0.
  • possivelmente mais recursos de segurança como o SELinux ...

Além de trocar todos os uids e gids pelos do usuário e verificar, é muito difícil implementar a mesma lógica que o sistema faz.

Com zsh, você poderia 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'

Em ambos os casos, desça a árvore de diretórios como root , mas teste o acesso a arquivos como o usuário correspondente.

A execução de find -readable como some-user não será possível, pois não poderá passar pelos diretórios para os quais o usuário não tem acesso ou nenhuma permissão de leitura (mas possivelmente acesso).

Mesmo considerando apenas a permissão e 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 idéia é que, se o arquivo é de propriedade do usuário, todas as outras permissões são irrelevantes. Caso contrário, se o arquivo for de propriedade de grupo de qualquer grupo do usuário, a "outra" permissão é irrelevante.

    
por 28.08.2013 / 21:24

Tags