2010-02-16 10 views
11

Ich versuche, die sichere Sache zu tun, und habe ein Programm, das als root laufen muss, um seine Privilegien fallenzulassen, wenn es sie nicht braucht. Dies funktioniert gut, wenn ich meine binäre bin mit dem SUID-Bit chmod und machen Sie es zu root gehören, wie jetzt habe ich UID = einige Benutzer und EUID = root, so kann ich seteuid(0) und seteuid(getuid()) verwenden, um jeweils Admin-Rechte zu erhöhen und zu löschen.Wie benutze ich setuid() von root um Benutzer zu werden, mit der Möglichkeit, später wieder root zu werden?

Aber wenn ich sudo anstelle der SUID verwenden, dann UID == EUID == 0, und so seteuid(getuid()) aufrufen wird keine Wirkung haben. Und ich kann UID nicht auf irgendeinen Wert von irgendeinem gelegentlichen Benutzer ändern, da die setuid() Mannseite klar besagt, dass, wenn es von einem Programm aufgerufen wird, das als root läuft, man die Vorzüge für gutes verliert, ohne Hoffnung, sie zurückzubekommen.

Also, wie mache ich mein Programm zeitweilig seine Privilegien verlieren, wenn es mit sudo ausgeführt wird?

+0

Müssen Sie zur UID des Benutzers zurückkehren, der 'sudo' ausgeführt hat, oder nur zu einem zufälligen, weniger privilegierten Benutzer? –

+0

Ich werde mich mit 'niemand' zufrieden geben. Aber wenn Sie einen einfachen Weg kennen, um den Sudo-Aufrufer zu bekommen, bin ich interessiert. – Florian

+3

meh, es ist einfach, muss nur 'getenv (" SUDO_UID ")'. – Florian

Antwort

10

seteuid(some random uid) zum Löschen von Privilegien, seteuid(0), um sie zurück zu bekommen, wenn sie als root ausgeführt wird.

+3

Natürlich - das bleibt das Problem, die ursprüngliche UID des Benutzers zu bekommen, der 'sudo' aufgerufen hat - wenn das OP zu diesem Benutzer zurückgehen muss? –

+0

Natürlich besteht die Chance, dass die zufällige UID, auf die Sie wechseln, zufälligerweise die UID des Systemadministrators ist. – immibis

+0

sudo erstellt Umgebungsvariablen, die die UID und GID des aufrufenden Benutzers enthalten. Sie können zu "nobody" wechseln, um die Variable zu lesen und zu diesem Benutzer zu wechseln. Ich empfehle nicht, Umgebungsvariablen als root zu lesen. "Niemand" ist ein eingeschränkter Account, der auf den meisten Unix-Systemen vorhanden ist. – wheredidthatnamecomefrom

3

Keine direkte Antwort, nur möchte Sie auf die Idee von privilege separation hinweisen. Hier ist eine großartige presentation von OpenBSD Gründer Theo de Raadt.

6

Es scheint wie seteuid (x) sollte privs fallen arbeiten und wieder zu heben ...

$ cat > t12.c 
#include <stdio.h> 
#include <unistd.h> 

void p(void) { printf("euid=%4d uid=%4d\n", geteuid(), getuid()); } 

int main(void) { p(); seteuid(100); p(); seteuid(0); p(); return 0; } 
$ cc -Wall t12.c 
$ sudo chown root a.out && sudo chmod 4555 a.out 
$ sudo ./a.out 
euid= 0 uid= 0 
euid= 100 uid= 0 
euid= 0 uid= 0 
$ ./a.out 
euid= 0 uid= 501 
euid= 100 uid= 501 
euid= 0 uid= 501 
$ 
+0

Wie stellen Sie sicher, dass uid = 100 nicht in sudoers group ist? – dashesy

+0

Das ist nur für sudo wichtig. Das einzige spezielle Privileg, das die Gruppe sudoers gewährt, ist die Möglichkeit, den Befehl sudo zu verwenden. Die Benutzer-ID hat keinen Root-Zugriff. – wheredidthatnamecomefrom

1

Fork(), bevor Sie Privilegien fallen. Warten Sie in der übergeordneten Aufgabe, bis das Kind mit eingeschränkten Berechtigungen fertig ist, und fahren Sie dann mit dem übergeordneten Element mit root fort.

seteuid ist nicht zu allen Units übertragbar und hat auch andere Nachteile.