Trouver des fichiers qu'un utilisateur ne peut pas lire?


12

Je souhaite rechercher des fichiers qu'un utilisateur particulier ne pourra pas lire.

Supposons que le nom d'utilisateur est "user123" et qu'ils appartiennent à un groupe appelé "user123". Je veux trouver des fichiers qui, s'ils appartiennent à user123, ont u + r on; à défaut, si le fichier appartient au groupe user123, il devrait avoir g + r activé; à défaut, il peut avoir o + r allumé.

Puisque GNU find a "-readable", je pourrais faire ceci:

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

Cependant, le processus doit être exécuté par un utilisateur qui n'a pas accès à sudo. Par conséquent, j'ai essayé ceci: (il ne vérifie pas o + r mais ce n'est pas important à ce stade)

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

mais il répertorie ce fichier:

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

Ce fichier est le seul fichier sous /startqui appartient à user123 avec g=roff. C'est comme si find interprétait le -u=ras -g=r.

J'ai décidé d'essayer d'inverser la logique et de tester à la not ( truth )place:

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

Ça marche!

Pourquoi l'original a- findt-il échoué? Est-ce un bug dans find(peu probable) ou la logique est-elle erronée?

Mise à jour: j'ai eu une mauvaise logique. Comme indiqué ci-dessous, depuis! (A || B || C) == (! A &&! B &&! C) ce sont les deux déclarations équivalentes:

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

Mon objectif n'était pas de devoir tester deux fois l'utilisateur / groupe. Ce dont j'ai vraiment besoin, c'est d'une structure if-then-else plus compliquée, qui ne serait probablement possible que s'il y avait un opérateur -xor. Je pourrais construire un xor à partir de et / ou / mais ce serait plus complexe que les deux solutions ci-dessus.


1
Même la deuxième logique est erronée, car elle dirait puppetavoir accès à un fichier avec --wxrwxrwx puppet puppet.
Stéphane Chazelas

Réponses:


7

La logique est fausse. Vous pensez que ce fichier n'aurait pas dû être répertorié car il appartient à user123l'utilisateur et le rbit de l'utilisateur est défini. Cependant, il est répertorié car il correspond au deuxième critère (il appartient au groupe user123et le rbit du groupe n'est pas défini).

Votre deuxième version fonctionne en raison de l'une des lois de Morgan : la négation de l'OR logique d'un groupe d'instructions est logiquement équivalente à l'AND de la négation des instructions individuelles. En d'autres termes:

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

Donc, le travail findcherche un fichier qui

  • N'est pas (détenue par l'utilisateur user123et lisible par cet utilisateur) ET
  • N'est pas (appartenant au groupe user123et lisible par ledit groupe) ET
  • N'est pas lisible dans le monde.

tandis que le premier findrecherche un fichier

  • Appartient à l'utilisateur user123et n'est pas lisible par cet utilisateur OU
  • Appartient à un groupe user123et n'est pas lisible par ledit groupe OU (si vous l'avez terminé)
  • N'est pas lisible dans le monde

Ainsi, un fichier correspondant à N'IMPORTE QUEL des 3 critères ci-dessus (et pas nécessairement tous) serait répertorié comme vous l'avez vu.

Éditer

Soit dit en passant (après avoir consulté votre profil), je suis un grand fan de votre livre O'Reilly :)


Merci pour l'analyse. Oui, c'était une mauvaise application de la loi de Morgan. J'essayais de le faire ( !A && !B && !C )mais j'ai déplacé l' !intérieur à l'intérieur de chaque partie, ce qui n'est pas valable. Merci!
TomOnTime

PS Je suis content que vous soyez fan de mon livre! Je suis curieux de savoir dans quelle langue vous l'avez lu.
TomOnTime

@TomOnTime English, bien sûr. J'essaie de lire n'importe quel livre dans sa langue d'origine si je peux l'aider.
Joseph R.

8

Il y a beaucoup plus de choses à prendre en considération pour vérifier si un utilisateur a accès à un fichier via un chemin donné:

  • Le propriétaire du fichier
  • le groupe du fichier
  • les ACL dans le fichier
  • l'uid, le gid et les gids supplémentaires de l'utilisateur
  • rechercher l'accès à tout composant de chemin d'accès menant à ce fichier.
  • si le fichier est un lien symbolique
  • les autorisations s'appliquent différemment pour les utilisateurs de l'ID 0.
  • éventuellement plus de fonctionnalités de sécurité comme SELinux ...

À moins de passer réellement tous les UID et GID à ceux de l'utilisateur et de vérifier, il est très difficile d'implémenter la même logique que ce que fait le système.

Avec zsh, vous pouvez faire (en tant que root):

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

Ou avec perl:

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

Dans les deux cas, descendez l'arborescence des répertoires en tant que, rootmais testez l'accès aux fichiers en tant qu'utilisateur correspondant.

Courir find -readablecomme some-userne dans les cas car il ne sera pas en mesure d'aller au- delà des répertoires pour lesquels l'utilisateur n'a pas accès ou aucune autorisation de lecture (mais peut - être accès).

Même en ne considérant que l'autorisation et la propriété du fichier lui-même (et non les ACL ou les composants de chemin ...), vous avez au moins besoin (ici la syntaxe 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 \)

L'idée étant que si le fichier appartient à l'utilisateur, toutes les autres autorisations ne sont pas pertinentes. Si ce n'est pas le cas, alors si le fichier appartient à un groupe appartenant à l'un des groupes de l'utilisateur, l'autorisation "autre" n'est pas pertinente.


1
Bon point sur les ACL et d'autres facteurs. La seule évaluation correcte à 100% est access()qu'elle utilise le même code de noyau que open(). C'est donc sudo -u user123 find /start -readablela meilleure solution si sudoc'est une option.
TomOnTime

1
@TomOnTime. Eh bien non, si vous utilisez sudo -u user123 find -readable, il ne signalera pas les fichiers dans des répertoires que vous ne pouvez pas entrer, ou dans des répertoires que vous ne pouvez pas lire (il y aura donc de faux négatifs et de faux positifs). C'est pourquoi je suggère d'utiliser zshpour descendre l'arborescence de répertoires en tant que root et do access()( [ -r ... ]) en tant qu'utilisateur réel (la définition $USERNAMEde zshchange tous les uids et gids comme le sudoferait).
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.