
Ich versuche, das in C++ kompilierte Programm als Root auszuführen, während ich ein anderer Benutzer bin.
Das Programm wird erfolgreich ausgeführt, allerdings als normaler Benutzer, nicht als Root.
Im Internet heißt es jedoch, chmod u+s
dass der Befehl es als Eigentümer (in meinem Fall Root) ausführen lässt.
Ein Programm ist eine einfache system(argv[1])
Zeile, die alles innerhalb des Befehlszeilenarguments ausführt.
Beispiel: Die Ausgabe gibt whoami
meinen Benutzer zurück, nicht den Root.
Auch der Versuch, den Inhalt aufzulisten, /root
endet mit „Zugriff verweigert“.
Berechtigungen der Datei -
-rwsr-xr-x 1 root root 16608 Aug 25 15:20 test
In diesem Moment habe ich versucht, Berechtigungen für die Datei zu erteilen 4755
(ohne Erfolg).
Auch das Verschieben der Datei /root
war kein Glücksfall.
Antwort1
Der Aufruf system() verwendet den execl()
Systemaufruf, um einen neuen Shell-Prozess zu erstellen. Der Systemaufruf ignoriert jedoch die effektive Benutzer-ID und gibt den EPERM-Fehler (Zugriff verweigert) zurück.
Dies liegt daran, dass Linux-Shells das Seteuid-Bit nicht erben. Warum? Nun, weil es echte Bedenken gibt, ein Skript mit der effektiven Benutzer-ID als Root auszuführen. Weitere Informationen zu diesem Thema finden Sie unterHier.
Es ist möglich, eine Shell auszuführen, die auf die effektive UID einwirkt, indem der -p
Parameter übergeben wird. Aus der sh
Manpage:
-p priv Versuchen Sie nicht, die effektive UID zurückzusetzen, wenn sie nicht mit der UID übereinstimmt. Dies ist standardmäßig nicht eingestellt, um eine falsche Verwendung durch Setuid-Root-Programme über system(3) oder popen(3) zu vermeiden.
Die Einschränkung gilt natürlich nicht für Systemaufrufe. Als Demo versucht dieses C-Programm, /root mithilfe von aufzulisten system()
und macht dann dasselbe mithilfe der Systemaufrufe opendir()
und .readdir()
Wenn die Binärdatei dem Root-Benutzer mit der festgelegten Benutzer-ID gehört, führt die Ausführung des Programms durch einen Nicht-Root-Benutzer dazu, dass die erste /root-Auflistung fehlschlägt, die zweite (mithilfe von) display_dir()
funktioniert.
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<dirent.h>
#include<errno.h>
int display_dir(const char *dirname)
{
DIR *dp = opendir(dirname);
struct dirent *sd=NULL;
if (!dp) return(errno);
while ((sd = readdir(dp)) != NULL)
{
printf("%s\n", sd->d_name);
}
closedir(dp);
return 0;
}
int main()
{
system("ls /root");
printf("Display returned %d\n", display_dir("/root"));
}