Prozessberechtigungen löschen

12

Ich habe einen Prozess, der von einem Damon gestartet wird, der als Root ausgeführt wird. Jetzt möchte ich die Berechtigungen dieses Prozesses auf die eines durchschnittlichen Benutzers "herabstufen". Ist das möglich? Wenn ja wie?

PS: Unix auf einem Mac ausführen

Samantha Catania
quelle

Antworten:

5

Der Prozess selbst muss setuid (2) aufrufen. Sie sollten auch untersuchen, wie Sie es in chroot (8) ausführen, wenn Sie es noch nicht sind. Soweit ich weiß, gibt es für root keine Möglichkeit, die UID eines anderen Prozesses zu ändern.

Wenn der Grund, warum Sie es als Root ausführen, darin besteht, Ports zu binden, würde ich empfehlen, es als normaler Benutzer auf einem höheren Port auszuführen und ipfw (8) unter OS X zu verwenden, um Port 80/443 / etc an den höheren Port weiterzuleiten:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx

Polynom
quelle
Ich habe setuid (uid) in mein Programm eingefügt, das als root ausgeführt wird, aber ich brauche es, um als normaler Benutzer ausgeführt zu werden und nichts passiert, dh es wird weiterhin als root ausgeführt
Samantha Catania
Sie müssen dann wahrscheinlich die Fehler daraus abfangen (möglicherweise erhalten Sie ein EINVAL für die UID). Die unwahrscheinliche Setuid ist auf Ihrem Computer fehlerhaft. Sie können überprüfen, ob Apache als _www ausgeführt wird. Programmiererdokumente: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
Polynom
Sie haben Recht, es gibt einen Syntaxfehler von der UID, obwohl es korrekt ist. Ist dies das richtige Format setuid (500)?
Samantha Catania
habe das Problem gefunden: Ich habe versucht, den Befehl über system () auszuführen, aber ich habe nur den Befehl ausgeführt, der funktioniert, und mein Problem gelöst. Danke für die Hilfe
Samantha Catania
Nein, das ist kein guter Rat: setuid()Allein zu telefonieren ist absolut nicht genug.
Nicholas Wilson
13

sudo tcpdump -Z verwendet initgroups (3), setgid (2) und setuid (2), um die Root-Berechtigungen seines eigenen Prozesses zu löschen.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}
Phron
quelle
2
Richtig. initgroups, setgid, setuid(Endlich!) Ist genau das richtige Paradigma auf Unix, und immer befolgt werden sollte. Darüber hinaus überprüft eine verantwortliche "Droproot" -Funktion, ob ihre UID und GID tatsächlich festgelegt wurden, selbst wenn alle drei Hauptfunktionen erfolgreich waren.
Nicholas Wilson
3

Sie können Befehle wie andere Benutzer ausführen, indem Sie su:

 su USERNAME -c COMMAND

Läuft COMMANDmit Berechtigungen USER.


Beachten Sie, dass standardmäßig suder Shell-Interpreter des Zielbenutzers zum Ausführen des Befehls verwendet wird. Im Gegensatz dazu wird standardmäßig sudodas COMMANDals eigenständiges Programm behandelt, das in der aktuellen Umgebung ausgeführt wird. Natürlich können diese Standardverhalten mit verschiedenen Schaltern und Umgebungsvariablen geändert werden.

rozcietrzewiacz
quelle
Sieht so aus, als würde sues nicht funktionieren, wenn in USERNAME keine Shell definiert ist (oder /bin/false), während sudo funktioniert.
Aif
1
@Aif Wenn der Benutzer nicht erlaubt ist , interaktive Befehle auszuführen, dann ist das Standardverhalten wird das widerspiegelt. Dies kann man jedoch jederzeit mit dem Schalter überschreiben . Beachten Sie, dass der Zweck von darin besteht, das Verhalten eines bestimmten Benutzers nachzuahmen - das normalerweise von seiner Shell beeinflusst wird. Im Gegensatz dazu würde (standardmäßig) die Shell-Einstellung des Zielbenutzers ignoriert. su-ssusudo
Rozcietrzewiacz
Nein, bitte führen Sie Dinge nicht mit einer Shell aus, nur um Berechtigungen zu löschen. Dadurch bleibt viel zu viel Kontrolle über einen Angreifer, der verschiedene Konfigurationsdateien einliest, die Sie nicht berühren möchten.
Nicholas Wilson
2

Zum Löschen von Berechtigungen benötigen Sie einen Benutzer ohne Rootberechtigung. Dann müssen Sie nur noch zu diesem Benutzer wechseln:

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

Beachten Sie, dass dies im Programm selbst und nicht in einem Wrapper-Skript erfolgt. Viele Programme benötigen Root-Rechte für einen bestimmten Zweck (z. B. zum Binden an einen Port mit niedriger Nummer), benötigen danach jedoch kein Root mehr. Diese Programme starten also als root, löschen jedoch Berechtigungen, sobald sie nicht mehr benötigt werden.

Wenn Sie überhaupt keine Root-Rechte benötigen, führen Sie sie einfach nicht als Root aus. Z.B:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
tylerl
quelle
1
Beachten Sie, dass der Prozess dadurch die Berechtigungen wiederherstellen kann, wenn er möchte! Die setuidFunktion legt nur die effektive UID fest, nicht die tatsächliche UID. Sie sollten verwenden, setreuidwenn Sie nicht möchten, dass der Prozess die Berechtigungen zurückerhält. (Und der obige Code behandelt auch keine zusätzlichen Gruppenrechte. Er ist nur zum Starten von meist vertrauenswürdigem Code geeignet.)
David Schwartz
@ David Schwartz-Code wurde absichtlich vereinfacht, um den verwendeten Mechanismus zu zeigen.
Tylerl
Wenn Sie vorhaben , sicherheitskritischen Code zu vereinfachen, müssen Sie machen es sehr klar , dass das ist , was du tust. Und Sie sollten Dinge wie "es ist nur eine Frage von" sagen, wenn dies nicht der Fall ist.
David Schwartz
2
@David Setzt tatsächlich setuid()echte und gespeicherte Benutzer-IDs. Sie können daran denken seteuid(). Nicht alle Systeme haben setreuid(), daher kann es nicht überall verwendet werden. Die genaue Semantik von setuid()ist kompliziert, aber wenn Sie euid 0 haben, können Sie alle herkömmlichen Benutzer-ID-Berechtigungen mit löschen setuid(). Die größte Lücke in dieser Antwort ist, dass initgroupsoder setgroupsmuss sowie setgidund aufgerufen werden setuid, und dass am Ende gründlichere Aussagen gemacht werden sollten.
Nicholas Wilson
0

Wenn Sie eine andere ausführbare sind ausgeführt wird , dh Sie anrufen execveoder eine andere der execFamilie der Funktion, vielleicht indirekt durch eine Funktion wie systemoder popen, und das Kind Prozess sollte ohne Privilegien von Anfang an laufen, dann ist der einfachste Weg ist , eine bekommen Shell beteiligt, und anrufen su. Hier ist eine Übersicht darüber, wie der Code in Perl aussehen könnte, mit den Anführungszeichen für:

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

Wenn der untergeordnete Prozess als Root gestartet werden muss, aber später Berechtigungen löschen muss, lesen Sie den Code in dieser Antwort , der veranschaulicht, wie Berechtigungen in einem Prozess herabgestuft werden.

Gilles 'SO - hör auf böse zu sein'
quelle