Was sich geändert hat, ist dieser /bin/sh
entweder wurde bash
oder blieb dash
die ein zusätzliches Flag -p
bekommen hat ahmt das Verhalten von bash nach.
Bash erfordert den -p
Flag, um das Setuid-Privileg nicht zu löschen, wie in seiner Manpage erklärt:
Wenn die Shell mit der effektiven Benutzer- (Gruppen-) ID gestartet wird, die nicht gleich der tatsächlichen Benutzer- (Gruppen-) ID ist, und die Option -p nicht angegeben ist, werden keine Startdateien gelesen, Shell-Funktionen werden nicht von der Umgebung geerbt, die SHELLOPTS, BASHOPTS-, CDPATH- und GLOBIGNORE-Variablen werden, wenn sie in der Umgebung erscheinen, ignoriert, und die effektive Benutzer-ID wird auf die tatsächliche Benutzer-ID gesetzt . Wenn die Option -p beim Aufruf angegeben wird, ist das Startverhalten dasselbe, aber die effektive Benutzer-ID wird nicht zurückgesetzt.
Vorher dash
kümmerte sich nicht darum und erlaubte die Ausführung von setuid (indem nichts dagegen unternommen wurde). Aber Ubuntu 16.04 ist dash
Auf der Manpage von wird eine zusätzliche Option beschrieben, ähnlich wie bei bash
:
-p priv
Versuchen Sie nicht, die effektive UID zurückzusetzen, wenn sie nicht mit der UID übereinstimmt. Dies ist nicht standardmäßig eingestellt, um eine falsche Verwendung zu vermeiden bysetuid-Root-Programme über system(3) oder popen(3).
Diese Option existierte weder im Upstream (der möglicherweise nicht auf einen vorgeschlagenen Patch reagiert hat) noch in Debian 9, ist aber in Debian Buster vorhanden, das den Patch seit 2018 erhalten hat.
HINWEIS:Wie von Stéphane Chazelas erklärt, ist es zu spät, um "/bin/sh -p"
aufzurufen in system()
weil system()
führt alles durch /bin/sh
gegebene aus und so wird die setuid bereits gelöscht. deroberts Antwort erklärt, wie man damit umgeht, im Code vor system()
.
mehr Details zur Geschichte hier und da.
Wahrscheinlich ändert die Shell beim Start aus irgendeinem Grund ihre effektive Benutzer-ID wieder in die echte Benutzer-ID zurück. Sie können dies überprüfen, indem Sie Folgendes hinzufügen:
/* needs _GNU_SOURCE; non-Linux users see setregid/setreuid instead */
uid_t euid = geteuid(), egid = getegid();
setresgid(egid, egid, egid);
setresuid(euid, euid, euid);
vor Ihrem system()
. (Eigentlich müssen Sie selbst unter Linux wahrscheinlich nur die echten festlegen; die gespeicherten sollten in Ordnung sein, um sie in Ruhe zu lassen. Dies ist nur rohe Gewalt zum Debuggen. Je nachdem, warum Sie eine Set-ID haben, müssen Sie dies möglicherweise tun um die echten IDs auch irgendwo zu speichern.)
[Außerdem, wenn dies nicht nur eine Übung ist, um zu lernen, wie setid funktioniert, dann gibt es viele Sicherheitsprobleme, über die man sich Sorgen machen muss, besonders wenn man eine Shell aufruft. Es gibt zum Beispiel viele Umgebungsvariablen, die das Verhalten der Shell beeinflussen. Bevorzugen Sie einen bereits bestehenden Ansatz wie sudo
wenn irgend möglich.]