Je suis root. Je voudrais savoir si un utilisateur non root a un accès en écriture à certains fichiers - des milliers d'entre eux. Comment le faire efficacement tout en évitant la création de processus?
shell
files
permissions
users
Howard
la source
la source
access(2)
avec un vrai UID correctement défini (par exemple viasetresuid(2)
ou l'équivalent portable)? Je veux dire, j'aurais du mal à le faire depuis bash, mais je suis sûr que Perl / Python peut le gérer.[ -w
utilisent généralement access (2) ou équivalent. Vous devez également définir les gids en plus de uid (comme le font su ou sudo). bash n'a pas de support intégré pour cela, mais zsh en a un.chgrp
dans n'importe quel shell.Réponses:
Peut-être comme ça:
Ce qui précède exécute un seul programme externe pour chaque fichier, à savoir
stat(1)
.Remarque: Cela suppose
bash(1)
, et l'incarnation Linux destat(1)
.Note 2: Veuillez lire les commentaires de Stéphane Chazelas ci-dessous pour connaître les dangers et limites passés, présents, futurs et potentiels de cette approche.
la source
-
. Vous pouvez le modifier pour accepter une liste délimitée NUL à la place avecread -d ''
util-linux
) spécifiquement écrites pour Linux, ce dontstat
vous parlez ne l'est pas, c'est une commande GNU qui a été portée sur la plupart des systèmes, pas seulement Linux. Notez également que vous aviez unestat
commande sur Linux bien avant l'stat
écriture de GNU (lestat
zsh intégré).stat(1)
". Je fais référence à unstat(1)
qui accepte la-c <format>
syntaxe, par opposition à, disons, la syntaxe BSD-f <format>
. Je crois aussi qu'il était assez clair que je ne parlais passtat(2)
. Je suis sûr qu'une page wiki sur l'historique des commandes communes serait cependant assez intéressante.TL; DR
Vous devez demander au système si l'utilisateur dispose d'une autorisation d'écriture. Le seul moyen fiable est de basculer l'uid efficace, le gid efficace et les gids de supplémentation sur celui de l'utilisateur et d'utiliser l'
access(W_OK)
appel système (même cela a des limites sur certains systèmes / configurations).Et gardez à l'esprit que le fait de ne pas avoir la permission d'écrire sur un fichier ne garantit pas nécessairement que vous ne pouvez pas modifier le contenu du fichier sur ce chemin.
L'histoire la plus longue
Considérons ce qu'il faut , par exemple , pour un utilisateur $ pour avoir accès en écriture à
/foo/file.txt
( en supposant qu'aucun des/foo
et/foo/file.txt
des liens symboliques)?Il a besoin:
/
(pas nécessaireread
)/foo
(pas nécessaireread
)/foo/file.txt
Vous pouvez déjà voir que les approches (comme @ lcd047 ou @ apaul ) qui vérifient uniquement l'autorisation de
file.txt
ne fonctionneront pas car elles pourraient direfile.txt
est accessible en écriture même si l'utilisateur n'a pas l'autorisation de recherche pour/
ou/foo
.Et une approche comme:
Ne fonctionne pas , soit parce qu'elle ne rapportera pas les fichiers dans les répertoires que l'utilisateur n'a pas d' accès en lecture (en
find
cours d' exécution que$user
ne peut pas la liste de leur contenu) , même s'il peut y écrire.Si nous oublions les ACL, les systèmes de fichiers en lecture seule, les indicateurs FS (comme immuables), d'autres mesures de sécurité (apparmor, SELinux, qui peuvent même faire la distinction entre différents types d'écriture) et nous concentrer uniquement sur les attributs de permission et de propriété traditionnels, pour obtenir un étant donné (rechercher ou écrire) la permission, c'est déjà assez compliqué et difficile à exprimer
find
.Vous avez besoin:
En
find
syntaxe, ici à titre d'exemple avec un utilisateur de uid 1 et des gids 1 et 2, ce serait:Celui-ci élague les répertoires que l'utilisateur n'a pas droit de recherche pour et pour d'autres types de fichiers (les liens symboliques sont exclus car ils ne sont pas pertinents), vérifie l'accès en écriture.
Si vous souhaitez également envisager l'accès en écriture aux répertoires:
Ou pour un arbitraire
$user
et son appartenance au groupe récupéré de la base de données utilisateur:(ce qui est 3 processus au total:
id
,sed
etfind
)Le mieux ici serait de descendre l'arborescence en tant que root et de vérifier les autorisations en tant qu'utilisateur pour chaque fichier.
(c'est un
find
processus plus unsudo
etsh
traiter tous les quelques milliers de fichiers,[
etprintf
sont généralement construits dans le shell).Ou avec
perl
:(3 procédés au total:
find
,sudo
etperl
).Ou avec
zsh
:(0 processus au total, mais stocke la liste complète des fichiers en mémoire)
Ces solutions reposent sur l'
access(2)
appel système. C'est au lieu de reproduire l'algorithme que le système utilise pour vérifier l'autorisation d'accès, nous demandons au système de faire cette vérification avec le même algorithme (qui prend en compte les autorisations, les ACL, les indicateurs immuables, les systèmes de fichiers en lecture seule ... ) qu'il utiliserait si vous essayez d'ouvrir le fichier pour l'écriture, c'est donc le plus proche que vous obtiendrez d'une solution fiable.Pour tester les solutions données ici, avec les différentes combinaisons d'utilisateurs, de groupes et d'autorisations, vous pouvez faire:
Faire varier l'utilisateur entre 1 et 2 et le groupe entre 1, 2 et 3 et nous limiter aux 9 bits inférieurs des autorisations car c'est déjà 9458694 fichiers créés. Cela pour les répertoires et encore pour les fichiers.
Cela crée toutes les combinaisons possibles de
u<x>g<y>/<mode1>/u<z>g<w>/<mode2>
. L'utilisateur avec uid 1 et gids 1 et 2 aurait un accès en écritureu2g1/010/u2g3/777
mais pasu1g2/677/u1g1/777
par exemple.Maintenant, toutes ces solutions tentent d'identifier les chemins d'accès des fichiers que l'utilisateur peut ouvrir pour l'écriture, ce qui est différent des chemins d'accès par lesquels l'utilisateur peut modifier le contenu. Pour répondre à cette question plus générique, il y a plusieurs choses à prendre en compte:
/a/b/file
mais s'il en possèdefile
(et a un accès de recherche à/a/b
, et le système de fichiers n'est pas en lecture seule, et le fichier n'a pas l'indicateur immuable, et il a un accès shell au système), il serait alors en mesure de modifier les autorisations dufile
et de s'accorder l'accès./a/b
mais n'a pas accès à la recherche./a/b/file
car il n'a pas accès à la recherche de/a
ou/a/b
, mais ce fichier peut avoir un lien dur à/b/c/file
par exemple, auquel cas il peut être en mesure de modifier le contenu de/a/b/file
en l'ouvrant via son/b/c/file
chemin./a
, mais il/a/b
peut être monté en liaison/c
, il peut donc ouvrirfile
pour écrire via son/c/file
autre chemin./a/b/file
, mais s'il dispose d'un accès en écriture,/a/b
il peut le supprimer ou le renommerfile
et le remplacer par sa propre version. Il modifierait le contenu du fichier/a/b/file
même s'il s'agissait d'un fichier différent./a
(il pourrait renommer/a/b
à/a/c
, créer un nouveau/a/b
répertoire et une nouvellefile
en elle.Trouver les chemins qui
$user
pourraient être modifiés. Pour adresser 1 ou 2, nous ne pouvons plus compter sur l'access(2)
appel système. Nous pourrions ajuster notrefind -perm
approche pour supposer l'accès à la recherche aux répertoires, ou l'accès en écriture aux fichiers dès que vous en êtes le propriétaire:Nous pourrions aborder 3 et 4, en enregistrant les numéros de périphérique et d'inode ou tous les fichiers $ user a une autorisation d'écriture et rapporte tous les chemins de fichiers qui ont ces numéros de dev + inode. Cette fois, nous pouvons utiliser les
access(2)
approches plus fiables :Quelque chose comme:
5 et 6 sont à première vue compliqués par le
t
peu des permissions. Lorsqu'il est appliqué sur des répertoires, c'est le bit de suppression restreint qui empêche les utilisateurs (autres que le propriétaire du répertoire) de supprimer ou de renommer les fichiers qu'ils ne possèdent pas (même s'ils ont un accès en écriture au répertoire).Par exemple, si nous revenons à notre exemple précédent, si vous avez accès en écriture à
/a
, alors vous devriez être en mesure de renommer/a/b
à/a/c
, puis recréer un/a/b
répertoire et un nouveaufile
là - dedans. Mais si let
bit est activé/a
et que vous ne le possédez pas/a
, vous ne pouvez le faire que si vous le possédez/a/b
. Ça donne:t
bit n'est pas défini, et vous êtes dans le même cas que ci-dessus (tous les chemins d'accès aux fichiers vous appartiennent).Nous pouvons donc répondre à tous les 1, 2, 5 et 6 avec:
Cela et la solution pour 3 et 4 sont indépendants, vous pouvez fusionner leur sortie pour obtenir une liste complète:
Comme cela doit être clair si vous avez tout lu jusqu'à présent, une partie au moins ne concerne que les autorisations et la propriété, pas les autres fonctionnalités qui peuvent accorder ou restreindre l'accès en écriture (FS en lecture seule, ACL, indicateur immuable, autres fonctionnalités de sécurité ...). Et comme nous les traitons en plusieurs étapes, certaines de ces informations peuvent être erronées si les fichiers / répertoires sont créés / supprimés / renommés ou leurs autorisations / propriété modifiées pendant l'exécution de ce script, comme sur un serveur de fichiers occupé avec des millions de fichiers .
Notes sur la portabilité
Tout ce code est standard (POSIX, Unix pour
t
bit) sauf:-print0
est une extension GNU désormais également prise en charge par quelques autres implémentations. Avec lesfind
implémentations qui ne le prennent pas en charge, vous pouvez utiliser à la-exec printf '%s\0' {} +
place et remplacer-exec sh -c 'exec find "$@" -print0' sh {} +
par-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
.perl
n'est pas une commande spécifiée par POSIX mais est largement disponible. Vous avez besoinperl-5.6.0
ou au-dessus pour-Mfiletest=access
.zsh
n'est pas une commande spécifiée par POSIX. Cezsh
code ci-dessus devrait fonctionner avec zsh-3 (1995) et au-dessus.sudo
n'est pas une commande spécifiée par POSIX. Le code devrait fonctionner avec n'importe quelle version tant que la configuration du système permet de s'exécuter enperl
tant qu'utilisateur donné.la source
x
autorisation de recherche ( bit) sur le répertoire. Vous pouvez également avoir des autorisations de recherche mais pas lire , ce qui signifie que les fichiers qui s'y trouvent vous sont cachés, mais si vous connaissez leur nom, vous pouvez y accéder. Un exemple typique est le répertoire du fichier de session php (quelque chose comme / var / lib / php).Vous pouvez combiner des options avec la
find
commande, de sorte qu'il trouvera les fichiers avec le mode et le propriétaire spécifiés. Par exemple:La commande ci-dessus listera toutes les entrées qui appartiennent au groupe "staff" ou "users" et ont une autorisation d'écriture pour ce groupe.
Vous devez également vérifier les entrées qui appartiennent à votre utilisateur et les fichiers qui sont accessibles en écriture, donc:
Cependant, cette commande ne correspondra pas aux entrées avec ACL étendue. Vous pourrez
su
donc découvrir toutes les entrées accessibles en écriture:la source
r-xrwxrwx yourusername:anygroup
our-xr-xrwx anyone:staff
est accessible en écriture.yourusername
n'ont pas accès.L'approche dépend de ce que vous testez réellement.
C'est parce qu'il y a tellement de façons d'arriver à 2) et la réponse de Stéphane les couvre bien (immuable est à retenir), et rappelez-vous qu'il existe également des moyens physiques, tels que démonter le lecteur ou le rendre en lecture seule à un niveau matériel (onglets de disquette). Je suppose que vos milliers de fichiers se trouvent dans des répertoires différents et que vous voulez un rapport ou que vous vérifiez une liste principale. (Un autre abus de Puppet ne fait qu'attendre).
Vous voulez probablement que l'arborescence perl de Stéphane et "joignent" la sortie avec une liste si nécessaire (su attrapera également l'exécution manquante sur les répertoires parents?). Si la maternité de substitution est un problème de performances, faites-vous cela pour un "grand nombre" d'utilisateurs? Ou s'agit-il d'une requête en ligne? S'il s'agit d'une exigence permanente permanente, il peut être temps d'envisager un produit tiers.
la source
Tu peux faire...
... pour une liste de tous les fichiers dans lesquels l'utilisateur ne peut pas écrire comme écrit dans stderr sous la forme ...
...ou similaire.
Voir les commentaires ci-dessous pour des notes sur les problèmes que cette approche pourrait avoir, et l'explication ci-dessous pour savoir pourquoi cela pourrait fonctionner. Plus sainement, cependant, vous ne devriez probablement utiliser que
find
des fichiers normaux comme:En bref,
tee
affichera des erreurs lors d'une tentative deopen()
fichier avec l'un des deux drapeaux ...... et rencontres ...
... comme spécifié ici :
Parce qu'il doit vérifier de la même manière
test -w
que ...Ils vérifient tous les deux EACCESS .
la source
tee
va se bloquer à moins qu'il ne soit explicitement interrompu une fois par run. C'était la chose la plus proche à laquelle je pouvais penser[ -w
... cependant - ses effets devraient être proches en ce qu'ils garantissent que l'utilisateur peut OAPPENDRE le fichier. Beaucoup plus facile que l'une ou l'autre option seraitpax
avec les-o
options de format et / ou-t
pour vérifierEACCESS
- mais chaque fois que je suggère que lespax
gens semblent ignorer. Et, de toute façon, le seulpax
que j'ai trouvé qui réponde à la norme il y a des AST - dans ce cas, vous pourriez aussi bien utiliser leurls
.