Beide system() und execve() kann verwendet werden, zum ausführen einer anderen Befehl innerhalb eines Programms. Warum in ein set-UID Programme system() ist gefährlich, während execve() sicher ist ?
system wird die shell aufrufen (sh) zum ausführen der gesendete Befehl als argument. Das problem mit system da die shell-Verhalten ist abhängig von der Benutzer, der den Befehl ausführen. Ein kleines Beispiel:
Erstellen Sie eine Datei test.c:
#include <stdio.h>
int main(void) {
if (system ("ls") != 0)
printf("Error!");
return 0;
}
Dann:
$ gcc test.c -o test
$ sudo chown root:root test
$ sudo chmod +s test
$ ls -l test
-rwsr-sr-x 1 root root 6900 Dec 12 17:53 test
Erstellen ein Skript namens ls im aktuellen Verzeichnis:
execve nicht, rufen Sie eine shell. Es wird ausgeführt, das Programm, das übergeben Sie als erstes argument. Das Programm muss eine binäre ausführbare Datei oder ein Skript starten mit shebang Linie.
Nicht sagen system() ist aber ohne Probleme wäre das nicht das oben gelöst werden, indem Sie die absoluten Pfade in die binäre ausführbare Datei?
Nein, Sie würde zumindest klar, die ganze Umgebung, geben vernünftige Standardwerte vor ein paar envvars (PFAD, HOME...), wenn nötig erhalten, env vars nach Hygienisierung (BEGRIFF, DARSTELLUNG, LANG...) stellen Sie sicher, fds 0, 1, 2 sind offen... im Grunde tun, was sudo macht. Selbst dann wäre ich nicht dorthin gehen. Nicht rufen Sie eine shell, in der privilege-escalation-Kontext wenn das vermieden werden kann. Beachten Sie, dass ls können fancy Dinge mit Ihrer Umgebung, also auch ohne system() sind, sollten Sie vielleicht desinfizieren Sie die Umgebung. Bei der Verwendung von setuids Sie minimieren wollen, was getan wird, als root ein (in der Regel nicht Befehle ausführen).
Nein, Sie haben noch Probleme, auch wenn Sie mit einem vollständigen Pfad. Wenn Sie /bin/ls kann der Benutzer hinzufügen / zu $IFS, wodurch die shell-split /bin/ls zu bin und ls. Jetzt eine ausführbare Datei namens bin im aktuellen Verzeichnis können tun die gleiche Sache wie ls in meiner Antwort.
Danke Euch beiden. Dies war eigentlich eine ziemlich interessante Antwort.
system() und execve() arbeiten auf unterschiedliche Weise. system() immer berufen sich auf die Schale und diese Schale wird den Befehl ausführen als separater Prozess (dies ist, warum Sie können Platzhalter verwenden und andere shell-Einrichtungen in der Befehlszeile bei der Verwendung system()).
execve() (und die anderen Funktionen in der exec() Familie) ersetzt den aktuellen Prozess, mit dem man hervorgebracht wird direkt (die execve() Funktion nicht zurückzukehren, außer im Falle des Scheiterns). In der Tat system() Umsetzung soll mit einer Sequenz von fork(), execve() und wait() ruft, um seine Funktion auszuführen.
Natürlich sind beide gefährlich, je nachdem, was wird ausgeführt, wenn der Prozess mit root-Privilegien. system(), obwohl, bringt einige zusätzliche Gefahren durch die zusätzliche shell - "Schicht", die es verwendet, öffnet sich Raum Sicherheitsverletzungen, wie es ruft eine root-shell wie im Fall der Frage (D. H., der Prozess hat das suid-bit).
Also, wenn die Verwendung execve () .., die Sie erwähnen, es ersetzt den aktuellen Prozess .. würde den Prozess weiterhin setuid ?
Ja. Der "neue" Prozess-initiiert von execve erbt eine Reihe von Eigenschaften des einen ersetzt wird, wie filedescriptors, Steckdosen, etc. und die effektive uid ist einer von Ihnen, aber es gibt Situationen, in denen der uid änderungen bei der Ausführung von execve, wie wenn die ausführbare Datei hingewiesen, die von der Execute-parameter hat das suid-bit gesetzt. In diesem Fall die uid geändert wird, um den Eigentümer der Datei, wie es definiert ist, in das Dateisystem.
Abgesehen von der metioned Probleme mit der Sicherheit system(), der erzeugte Prozess erbt die wichtigsten Programm-Umgebung. Dies kann sehr problematisch sein, wenn mit suid zum Beispiel, wenn der aufrufende Prozess setzt LD_LIBRARY_PATH-Umgebungsvariable.
Mit der exec()-Familie das aufrufende Programm können die Umwelt genau das, was gebraucht wird (und sicher) für das aufgerufene Programm vor dem Aufruf exec().
Und natürlich die shell aufgerufen system() können die Sicherheitsprobleme haben sich.
Die Umgebungsvariable LD_LIBRARY_PATH wird ignoriert, wenn setuid-Programm ist die von nicht-root-Benutzer, außer, wenn die Reale uid ist auch 0.
system wird die shell aufrufen (sh) zum ausführen der gesendete Befehl als argument. Das problem mit
system
da die shell-Verhalten ist abhängig von der Benutzer, der den Befehl ausführen. Ein kleines Beispiel:Erstellen Sie eine Datei
test.c
:Dann:
Erstellen ein Skript namens
ls
im aktuellen Verzeichnis:Nun:
Oops, du hast eine shell mit root-Privilegien.
execve nicht, rufen Sie eine shell. Es wird ausgeführt, das Programm, das übergeben Sie als erstes argument. Das Programm muss eine binäre ausführbare Datei oder ein Skript starten mit shebang Linie.
system()
ist aber ohne Probleme wäre das nicht das oben gelöst werden, indem Sie die absoluten Pfade in die binäre ausführbare Datei?ls
können fancy Dinge mit Ihrer Umgebung, also auch ohnesystem()
sind, sollten Sie vielleicht desinfizieren Sie die Umgebung. Bei der Verwendung von setuids Sie minimieren wollen, was getan wird, als root ein (in der Regel nicht Befehle ausführen)./bin/ls
kann der Benutzer hinzufügen/
zu$IFS
, wodurch die shell-split/bin/ls
zubin
undls
. Jetzt eine ausführbare Datei namensbin
im aktuellen Verzeichnis können tun die gleiche Sache wiels
in meiner Antwort.system()
undexecve()
arbeiten auf unterschiedliche Weise.system()
immer berufen sich auf die Schale und diese Schale wird den Befehl ausführen als separater Prozess (dies ist, warum Sie können Platzhalter verwenden und andere shell-Einrichtungen in der Befehlszeile bei der Verwendungsystem()
).execve()
(und die anderen Funktionen in derexec()
Familie) ersetzt den aktuellen Prozess, mit dem man hervorgebracht wird direkt (dieexecve()
Funktion nicht zurückzukehren, außer im Falle des Scheiterns). In der Tatsystem()
Umsetzung soll mit einer Sequenz vonfork()
,execve()
undwait()
ruft, um seine Funktion auszuführen.Natürlich sind beide gefährlich, je nachdem, was wird ausgeführt, wenn der Prozess mit root-Privilegien.
system()
, obwohl, bringt einige zusätzliche Gefahren durch die zusätzliche shell - "Schicht", die es verwendet, öffnet sich Raum Sicherheitsverletzungen, wie es ruft eine root-shell wie im Fall der Frage (D. H., der Prozess hat das suid-bit).Abgesehen von der metioned Probleme mit der Sicherheit
system()
, der erzeugte Prozess erbt die wichtigsten Programm-Umgebung. Dies kann sehr problematisch sein, wenn mitsuid
zum Beispiel, wenn der aufrufende Prozess setztLD_LIBRARY_PATH
-Umgebungsvariable.Mit der
exec()
-Familie das aufrufende Programm können die Umwelt genau das, was gebraucht wird (und sicher) für das aufgerufene Programm vor dem Aufrufexec()
.Und natürlich die shell aufgerufen
system()
können die Sicherheitsprobleme haben sich.