Dateien finden, die ein Benutzer nicht lesen kann?

11

Ich möchte Dateien finden, die ein bestimmter Benutzer nicht lesen kann.

Angenommen, der Benutzername lautet "user123" und sie befinden sich in einer Gruppe namens "user123". Ich möchte Dateien finden, die, wenn sie Eigentum von user123 sind, u + r aktiviert haben. Andernfalls sollte g + r aktiviert sein, wenn die Datei der Gruppe user123 ist. Andernfalls kann o + r eingeschaltet sein.

Da GNU find "-readable" hat, könnte ich dies tun:

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

Der Prozess muss jedoch von einem Benutzer ausgeführt werden, der keinen Sudo-Zugriff hat. Deshalb habe ich folgendes versucht: (es prüft o + r nicht, aber das ist an dieser Stelle nicht wichtig)

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

aber es listet diese Datei auf:

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

Diese Datei ist die einzige Datei unter /start, die dem Benutzer123 mit g=roff gehört. Es ist, als würde find das -u=ras interpretieren -g=r.

Ich beschloss, die Logik umzukehren und stattdessen zu testen not ( truth ):

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

Das funktioniert!

Warum ist das Original findgescheitert? Ist es ein Fehler find(unwahrscheinlich) oder ist die Logik falsch?

Update: Ich hatte die Logik falsch. Wie unten ausgeführt, da! (A || B || C) == (! A &&! B &&! C) Dies sind die beiden äquivalenten Aussagen:

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

Mein Ziel war es, Benutzer / Gruppe nicht zweimal testen zu müssen. Was ich wirklich brauche, ist eine kompliziertere Wenn-Dann-Sonst-Struktur, die wahrscheinlich nur möglich wäre, wenn es einen -xor-Operator gäbe. Ich könnte ein xor daraus bauen und / oder / nicht, aber es wäre komplexer als die beiden obigen Lösungen.

TomOnTime
quelle
1
Sogar die zweite Logik ist falsch, weil sie sagen würde, dass sie puppetZugriff auf eine Datei mit hat --wxrwxrwx puppet puppet.
Stéphane Chazelas

Antworten:

7

Die Logik ist falsch. Sie denken, diese Datei sollte nicht aufgelistet sein, da sie Eigentum user123des Benutzers ist und das rBit des Benutzers gesetzt hat. Es wird jedoch aufgelistet, weil es dem zweiten Kriterium entspricht (es gehört der Gruppe user123und hat das rBit der Gruppe nicht gesetzt).

Ihre zweite Version funktioniert aufgrund eines von de Morgans Gesetzen : Das Negieren der logischen ODER-Verknüpfung einer Gruppe von Anweisungen entspricht logisch der UND-Verknüpfung der Negation der einzelnen Anweisungen. Mit anderen Worten:

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

Die Arbeit findsucht also nach einer Datei, die

  • Ist nicht (im Besitz des Benutzers user123und lesbar für diesen Benutzer) UND
  • Ist nicht (im Besitz der Gruppe user123und von dieser Gruppe lesbar) UND
  • Ist nicht weltlesbar.

während der erste findnach einer Datei sucht, die

  • Ist Eigentum des Benutzers user123und für diesen Benutzer nicht lesbar ODER
  • Ist im Besitz einer Gruppe user123und für diese Gruppe nicht lesbar ODER (falls Sie es abgeschlossen haben)
  • Ist nicht weltlesbar

Wie Sie gesehen haben, wird eine Datei aufgelistet, die mit JEDEM der oben genannten 3 Kriterien (und nicht unbedingt allen) übereinstimmt.

Bearbeiten

Übrigens (nach dem Betrachten Ihres Profils) bin ich ein großer Fan Ihres O'Reilly-Buches :)

Joseph R.
quelle
Danke für die Analyse. Ja, es war eine falsche Anwendung von Morgans Gesetz. Ich habe es versucht, ( !A && !B && !C )aber ich habe das !in das Innere jedes Teils verschoben , was nicht gültig ist. Vielen Dank!
TomOnTime
PS Ich bin froh, dass du ein Fan meines Buches bist! Ich bin gespannt, in welcher Sprache Sie es lesen.
TomOnTime
@ TomOnTime Englisch natürlich. Ich versuche, jedes Buch in seiner Originalsprache zu lesen, wenn ich helfen kann.
Joseph R.
7

Es sind noch viel mehr Dinge zu beachten, um zu überprüfen, ob ein Benutzer über einen bestimmten Pfad Zugriff auf eine Datei hat:

  • Der Besitzer der Datei
  • die Gruppe der Datei
  • die ACLs in der Datei
  • die uid, gid und ergänzenden gids des benutzers
  • Suchen Sie den Zugriff auf eine Pfadkomponente, die zu dieser Datei führt.
  • ob die Datei ein Symlink ist
  • Berechtigungen gelten für Benutzer mit der ID 0 unterschiedlich.
  • möglicherweise mehr Sicherheitsfunktionen wie SELinux ...

Es ist sehr schwierig, die gleiche Logik wie das System zu implementieren, ohne alle Uids und Gids auf die des Benutzers umzustellen und zu überprüfen.

Mit zsh können Sie (als root) Folgendes tun:

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

Oder mit perl:

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

In beiden Fällen müssen Sie den Verzeichnisbaum rootals den entsprechenden Benutzer absteigen, aber auf Dateizugriff testen.

Laufen find -readablewie some-usernicht in den Fällen , da es nicht in der Lage sein , über die Verzeichnisse zu gehen , für die der Benutzer keinen Zugang oder keine Leseberechtigung hat (aber möglicherweise Zugriff).

Auch wenn Sie nur die Berechtigung und den Besitz der Datei selbst berücksichtigen (und nicht ACLs oder Pfadkomponenten ...), benötigen Sie mindestens (hier GNU-Syntax):

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 \)

Die Idee ist, dass alle anderen Berechtigungen irrelevant sind, wenn die Datei dem Benutzer gehört. Wenn nicht, ist die "andere" Berechtigung irrelevant, wenn sich die Datei in Gruppenbesitz einer der Benutzergruppen befindet.

Stéphane Chazelas
quelle
1
Guter Punkt über ACLs und andere Faktoren. Die einzige 100% korrekte Bewertung besteht access()darin, dass derselbe Kernelcode wie verwendet wird open(). Somit sudo -u user123 find /start -readableist die beste Lösung, wenn sudoeine Option ist.
TomOnTime
1
@ TomOnTime. Nein, wenn Sie verwenden sudo -u user123 find -readable, werden keine Dateien in Verzeichnissen gemeldet, die Sie nicht eingeben können, oder in Verzeichnissen, die Sie nicht lesen können (es gibt also falsch negative und falsch positive Ergebnisse). Deshalb schlage ich vor , mit zshfür den Abstieg den Verzeichnisbaum als root und tun access()( [ -r ... ]) als die tatsächlichen Benutzer (Einstellung $USERNAMEin zshÄnderungen alle UIDs und GIDs wie sudowürde).
Stéphane Chazelas