Wie führe ich Datei- / Verzeichnismanipulationen mit Benutzerrechten durch?

8

Ich habe eine Serveranwendung, die unter einem Systemkonto ausgeführt wird, weil sie zu jedem beliebigen Zeitpunkt Anfragen im Auftrag eines Benutzers auf dem System verarbeitet. Diese Anfragen bestehen aus Anweisungen zum Manipulieren des Dateisystems.

Hier ist der Haken: Das Programm muss die Berechtigungen des jeweiligen Benutzers berücksichtigen, wenn er die Aktionen ausführt. Beispiel: joe sollte /home/larry nicht ändern können, wenn die Berechtigungen 755 sind.

Momentan ist meine Strategie das

  • Erhalte den Besitzer / die Gruppe der Datei
  • Vergleichen Sie sie mit der Benutzer-ID / Gruppen-ID des Benutzers, der versucht, die Aktion
  • auszuführen
  • Wenn beide übereinstimmen (oder wenn keine übereinstimmen), verwenden Sie den entsprechenden Teil des Berechtigungsfelds in der Datei, um die Aktion zuzulassen oder zu verweigern

Ist das klug? Gibt es einen einfacheren Weg, dies zu tun?

Zuerst dachte ich daran, mehrere Instanzen der App unter den Benutzerkonten laufen zu lassen - aber das ist keine Option, weil dann nur eine der Instanzen auf einen bestimmten TCP-Port zugreifen kann.

    
Nathan Osman 31.01.2011, 04:57
quelle

3 Antworten

3

Sieh dir Samba an, um ein Beispiel dafür zu bekommen. Der Samba-Daemon läuft als root, aber verzweigt und übernimmt so schnell wie möglich die Anmeldeinformationen eines normalen Benutzers.

Unix-Systeme verfügen über zwei getrennte Anmeldeinformationen: die echten Benutzer- / Gruppen-IDs und die effektiven Benutzer- / Gruppen-IDs. Das reale Set identifiziert, wer Sie tatsächlich sind, und das effektive Set definiert, worauf Sie zugreifen können. Sie können die effektive uid / gid nach Belieben ändern, wenn Sie root sind - einschließlich eines normalen Benutzers und wieder zurück -, da Ihre echten Benutzer- / Gruppen-IDs während des Übergangs root bleiben. Eine andere Möglichkeit, dies in einem einzigen Prozess zu tun, besteht darin, seteuid/gid zu verwenden, um die Berechtigungen verschiedener Benutzer nach Bedarf vor- und zurückzuschalten. Wenn Ihr Server-Daemon als root läuft oder CAP_SETUID hat, ist dies erlaubt.

Beachten Sie jedoch, dass, wenn Sie die effektive uid / gid nach Belieben wechseln können und Ihre Anwendung unterlaufen ist, diese Subversion beispielsweise die effektive uid / gid zurück auf 0 setzen könnte und Sie eine ernsthafte Sicherheitslücke haben könnten . Aus diesem Grund ist es ratsam, alle Privilegien so schnell wie möglich dauerhaft zu löschen, einschließlich Ihres echten Benutzers uid / gid.

Aus diesem Grund ist es normal und sicherer, wenn ein einzelner abhörender Socket als root ausgeführt wird, dann abzweigt und sowohl die echten als auch die effektiven Benutzer-IDs durch Aufruf von setuid ändert. Dann kann es nicht zurück wechseln. Ihr gegabelter Prozess hat den Socket, der accept() ed ist, da es sich um eine Verzweigung handelt. Jeder Prozess schließt nur die Dateideskriptoren, die er nicht benötigt; Die Sockets bleiben lebendig, da sie von den Dateideskriptoren in den entgegengesetzten Prozessen referenziert werden.

Sie könnten auch versuchen, die Berechtigungen zu erzwingen, indem Sie sie einzeln untersuchen, aber ich hoffe, es ist offensichtlich, dass dies potentiell fehleranfällig ist, viele Randfälle hat und eher schief geht (zB wird es nicht funktionieren mit POSIX-ACLs, es sei denn, Sie implementieren dies auch speziell).

Sie haben also drei Möglichkeiten:

  1. Fork und setgid() / setuid() an den von Ihnen gewünschten Benutzer. Wenn eine Kommunikation erforderlich ist, verwenden Sie pipe(2) oder socketpair(2) , bevor Sie fork.
  2. Verzweigen Sie nicht und seteuid() / setegid() nach Bedarf (weniger sicher: es ist wahrscheinlicher, dass Ihr Server versehentlich beschädigt wird).
  3. Verwechseln Sie nicht die Anmeldeinformationen des Systems. Führen Sie die Rechteerzwingung manuell durch (weniger sicher: Wahrscheinlicher, dass die Autorisierung falsch ist).

Wenn Sie mit dem Daemon kommunizieren müssen, ist es zwar schwieriger, einen Socket oder eine Pipe zu verwenden, aber die erste Option ist wirklich der richtige sichere Weg. Sehen Sie sich an, wie SSH die Rechtetrennung vornimmt . Sie können auch überlegen, ob Sie Ihre Architektur so ändern können, dass der Prozess statt irgendeiner Kommunikation nur etwas Speicherplatz oder Speicherplatz freigibt.

Sie erwähnen, dass Sie in Betracht gezogen haben, für jeden Benutzer einen separaten Prozess auszuführen, aber einen einzigen empfangenden TCP-Port benötigen. Du kannst das immer noch tun. Lassen Sie einen Master-Daemon den TCP-Port abhören und Anfragen an jeden Benutzer-Daemon senden und kommunizieren Sie wie gewünscht (z. B. über Unix-Domain-Sockets). Dies wäre tatsächlich fast dasselbe wie ein Forking-Master-Daemon; Ich denke, Letzteres würde sich leichter umsetzen lassen.

Weitere Informationen: Die Hilfeseite credentials(7) . Beachten Sie auch, dass Linux über das Dateisystem uid / gids verfügt. Dies ist fast dasselbe wie effektive UID / GIDs, außer für andere Dinge wie das Senden von Signalen. Wenn Ihre Benutzer keinen Shell-Zugriff haben und keinen beliebigen Code ausführen können, müssen Sie sich keine Gedanken über den Unterschied machen.

    
Robie Basak 13.02.2011, 23:08
quelle
3

Ich hätte meinen Server fork () und sofort setuid(uid) , um root-Privilegien aufzugeben. Dann würde jede Dateimanipulation im Namen des Benutzers sein, der Sie geworden sind. Da du ein Kind des Servers bist, hättest du immer noch den accept () Ed Child-Socket, den die Anfrage (und ich nehme eine Antwort) weitermachen würde. Dies erfordert (offensichtlich) root-Rechte für den Daemon.

Das Übergeben von Dateideskriptoren zwischen Prozessen erscheint in diesem Fall unnötig kompliziert, da das Kind bereits den Deskriptor "request" hat.

    
CoreyStup 31.01.2011 06:50
quelle
2

Lassen Sie einen Server auf dem previlegierten Server-Port laufen und erstellen Sie untergeordnete Prozesse für Benutzer, die sich beim System anmelden. Die untergeordneten Prozesse sollten Privilegien löschen und die Identität des angemeldeten Benutzers annehmen. Jetzt können die Kinder keinen Schaden mehr anrichten.

    
Daniel 31.01.2011 05:03
quelle