Gruppenmitgliedschaften und setuid / setgid-Prozesse

10

Prozesse, die Berechtigungen über de-eskalierensetuid() und setgid()die Gruppenmitgliedschaften der von ihnen festgelegten UID / GID nicht zu erben scheinen.

Ich habe einen Serverprozess, der als Root ausgeführt werden muss, um einen privilegierten Port zu öffnen. Danach deeskaliert es zu einer bestimmten nicht privilegierten UID / GID, 1 - z. B. der des Benutzers foo(UID 73). Benutzer fooist Mitglied der Gruppe bar:

> cat /etc/group | grep bar
bar:x:54:foo

Wenn ich mich als anmelde foo, kann ich eine Datei /test.txtmit folgenden Merkmalen lesen :

> ls -l /test.txt
-rw-r----- 1 root bar 10 Mar  8 16:22 /test.txt

Allerdings das folgende C-Programm (kompilieren std=gnu99), wenn root ausgeführt wird:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}   

Meldet immer, dass die Berechtigung verweigert wurde . Ich stelle mir vor, dass dies damit zu tun hat, dass es sich nicht um einen Anmeldevorgang handelt, aber es behindert die Art und Weise, wie Berechtigungen funktionieren sollen.


1. Das ist oft SOP für Server, und ich denke, es muss einen Weg geben, dies zu umgehen, da ich einen Bericht von jemandem gefunden habe, der es mit Apache macht - Apache wurde der Audiogruppe hinzugefügt und kann anscheinend dann das Soundsystem verwenden. Natürlich geschieht dies wahrscheinlich in einem Fork und nicht im ursprünglichen Prozess, aber tatsächlich ist der Fall in meinem Kontext der gleiche (es ist ein untergeordneter Prozess, der nach dem Aufruf von setuid gegabelt wird).

Goldlöckchen
quelle
Schalten Sie die setuid()/ setgid()Anrufe um.
vonbrand
@vonbrand ROTFL Ich dachte, ich hätte dort eine Gesichtspalme - aber das gleiche Ergebnis, also werde ich die Frage bearbeiten, um den roten Hering zu beseitigen.
Goldlöckchen
1
Wenn Sie setgid(54)anstelle von setgid(73)(wie in /etc/groups, Gruppe barhat GID 54) verwenden, funktioniert es?
Lgeorget
@lgeorget Sicher, aber das macht den Zweck zunichte. Der Prozess benötigt aus anderen Gründen eine eigene GID. Ebenso müssen diese Dateien über die Berechtigungen verfügen, über die sie verfügen. Aus diesem Grund ist eine Mitgliedschaft in mehreren Gruppen erforderlich - z. B. wenn Sie zwei Benutzer haben, die dies tun müssen. Beachten Sie, dass Sie nicht setuid()wieder können, nachdem Sie es getan haben ... aber, hmmm ... ich denke, Sie können mit seteuid()...
Goldlöckchen
1
Meine Frage war, ob es irgendwo kein anderes verstecktes subtiles Problem gab. :-)
Lgeorget

Antworten:

14

Das Problem ist , dass setuidund setgid nicht ausreichend sind , Ihrem Prozess die Anmeldeinformationen alle es braucht zu geben. Die Berechtigungen eines Prozesses hängen davon ab

  • seine UID
  • seine GID
  • seine ergänzenden Gruppen
  • seine Fähigkeiten.

Sehen Sie man 7 credentials, um eine detailliertere Übersicht zu erhalten. In Ihrem Fall besteht das Problem darin, dass Sie die UID und die GID korrekt festgelegt haben, aber nicht die zusätzlichen Gruppen des Prozesses. Und die Gruppe barhat GID 54, Nr. 73, sodass sie nicht als Gruppe erkannt wird, in der sich Ihr Prozess befindet.

Du solltest tun

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <grp.h>

int main (void) {
    gid_t supplementary_groups[] = {54};

    setgroups(1, supplementary_groups);
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}  
lgeorget
quelle
1
Das war eine interessante Frage, die mehr Gegenstimmen verdient, weil sie für viele Leute da draußen tatsächlich nützlich sein könnte. :-)
Lgeorget
Ich hatte also ein ähnliches Problem mit seriellen Schnittstellen. Ich habe dies für die dialoutGruppe implementiert und es hat beim ersten Mal funktioniert.
18.
0

OK, ein bisschen im Netz herumgeschleppt. Ich dachte zuerst, dass APUE alle Antworten enthalten würde, aber ich habe mich geirrt. Und meine Kopie (alte Ausgabe) ist in Arbeit, also ... Kapitel 5 des Unix- und Linux-Administrationshandbuchs sieht vielversprechend aus, aber ich habe es nicht (nur eine Kopie der ersten beiden Ausgaben, ebenfalls in Arbeit).

Die kleinen Ressourcen, die ich gefunden habe (Google für "Daemon Writing Unix"), sprechen alle über wichtige Schritte, wie das Trennen von der Tty usw. Aber nichts über UID / GID. Seltsamerweise scheint nicht einmal die umfangreiche HOWTO-Sammlung unter http://tldp.org Details zu enthalten. Nur excetion ist Jason Shorts schreiben Lassen Sie uns ein Linux - Daemon - Teil I . Alle Details darüber, wie SUID / SGID und all das Durcheinander funktionieren, sind Chen, Wagner und Deans SUID entmystifiziert (ein Artikel in USENIX 2002). Aber seien Sie vorsichtig, Linux hat eine zusätzliche UID, die FSUID ( eine Diskussion finden Sie in Wolters Unix-Inkompatibilitätshinweisen: UID-Einstellungsfunktionen ).

Das Dämonisieren eines Prozesses ist definitiv nichts für schwache Nerven. Allgemeine Sicherheitsüberlegungen finden Sie in D. Wheelers Secure Programming für Linux und Unix HOWTO - Erstellen sicherer Software . Systemd verspricht, das meiste davon zu vereinfachen (und damit den Spielraum für Fehler zu verringern, die zu Sicherheitsproblemen führen), siehe das Daemon-Handbuch .

vonbrand
quelle
1
Die Frage betrifft nicht die Dämonisierung. Sie haben das SUID-Bit (das einem Prozess die Berechtigungen des Eigentümers seiner ausführbaren Datei gibt) mit verwechselt setuid(), wodurch der Prozess seine UID willkürlich ändern kann. SUID soll normalerweise eine Eskalation von Berechtigungen ermöglichen (nicht privilegiert -> privilegiert), wohingegen setuid()nur das Gegenteil möglich ist.
Goldlöckchen