Meinhard Schneider wrote:
Mein Problem: Ich will ein CGI mit suid-root ausführen. Notfalls kann auch das CGI ein anderes Programm mit suid-root aufrufen. Ihr habt mir gesagt, ich soll in C einen Wrapper schreiben (warum, weiss ich nicht ;-)).
Bei einem SUID-Programm sind reale und effektive User-ID unterschiedlich. Bei einem Shell- oder Perl-Skript setzt der Interpreter (bash bzw. perl) in so einem Fall die effektive User-ID wieder zurueck, so dass der Effekt dahin ist.
Nun, dass hab ich gemacht. Ich weiss nur nicht, wie man in C eine if-Abfrage macht ;-)).
Die Syntax ist weitgehend mit der von Perl identisch, allerdings sind String-Vergleiche nicht ganz so einfach (siehe unten).
Hier man Programm: --<SCHNIPP>-- #include <stdio.h> main(ac, av) char **av; { execv("/bin/uname"); } --<SCHNAPP>-- Leider führt das Programm uname nicht aus ;-))
Der execv()-Aufruf stimmt auch nicht ganz. Zusaeztlich zum Pfad des auszufuehrenden Programms ist auch eine Argumentliste zu uebergeben. Dabei ist das erste Argument (argv[0]) in der Regel noch einmal der Programmname. Naeheres siehe `man execv`.
Ich schreibe mal das selbe in perl. vielleich ist jemand so nett und kann es mir in C/C++ übersetzen?! --<SCHNIPP>-- #!/usr/bin/perl -w
if($ARGV[0] eq '--runq') { system("/etc/skripts/runq"); }; if($ARGV[0] eq '--popmail') { system("/etc/skripts/poll"); }; ... --<SCHNAPP>-- Kann jemand mir das übersetzen? many THX!!!!!
Ich bin mal nicht so ;-) #include <stdio.h> /* fuer fprintf(), perror() */ #include <string.h> /* fuer strcmp() */ #include <unistd.h> /* fuer System-Calls */ int main (int argc, char* argv[]) { const char* prog; /* Abbrechen, wenn argc ungleich 2 (eigener Programmname + Option) */ if (argc != 2) { fprintf (stderr, "%s: Wrong number of arguments.\n", argv[0]); return 2; } /* Option auswerten: Wenn bekannt, entsprechenden Programmpfad in * prog merken. * * strcmp(s1, s2) == 0 <=> die Strings s1 und s2 sind gleich */ if (strcmp (argv[1], "--runq") == 0) { prog = "/etc/skripts/runq"; } else if (strcmp (argv[1], "--popmail") == 0) { prog = "/etc/skripts/poll"; /* ... beliebig fortsetzbar ... */ } else { /* Bei unbekannter Option Programm abbrechen */ fprintf (stderr, "%s: Unknown option.\n", argv[0]); return 2; } /* Soweit ist alles in Ordnung, jetzt wird dafuer gesorgt, dass * die reale UID auf den Wert der effektiven UID gesetzt wird. */ if (setreuid (geteuid(), geteuid()) == -1) { /* Sicherheitshalber Abbruch bei Fehler vorsehen, aber eigentlich * duerfte hier nichts schiefgehen. */ perror ("setreuid"); return 1; } /* Alles bereit. Jetzt wird das Programm ausgefuehrt und bekommt * als erstes Element seiner Argumentliste, wie's ueblich ist, * seinen eigenen Namen. Am einfachsten (ohne per Hand ein Array * zusammenzubauen) geht das mit execl(). */ execl (prog, prog, NULL); /* Falls execl() zurueckkehrt, ist was schiefgegangen. */ perror (prog); return 1; } Sollte eigentlich soweit verstaendlich sein. Details zu den Funktionen sind wie immer in den entsprechenden man-Pages nachzulesen. Je nach Anwendung kann es sinnvoll sein, in so einem Wrapper noch zusaetzliche Schutzmassnahmen zu ergreifen, z.B. das Environment zu bereinigen (sicherstellen, dass keine boesen Pfade gesetzt sind etc.). In jedem Fall solltest Du ueberlegen, ob Du wirklich einen selbstgestrickten Wrapper brauchst, oder ob es nicht auch einer der vorhandenen (z.B. su1 oder sudo) tut, bei denen sich schon etliche Leute Gedanken ueber die Sicherheit der Implementierung gemacht haben. Wenn es einfach nur darum geht, ein Skript mit root-Rechten laufen zu lassen, ist letzteres die sinnvollere Wahl. Ein eigener Wrapper macht dann Sinn, wenn noch Einzelfallabhaengige Ueberpruefungen o.ae. darin untergebracht werden sollen.
Wenn ich nun mein compiletes Programm, habe, soll ich darauf suid-root setzen und es dann aus meinem CGI heraus aufrufen? Funktioniert das?
Ja. Wenn Du allerdings ein Skript aufrufen willst, muss der Trick mit dem Setzen der realen UID gemacht werden, sonst hast Du nichts gewonnen.
Oder soll ich aus dem C-Programm ein anderes Programm/Skript aufrufen, was suid-root ist??
Dann koenntest Du es auch gleich direkt aufrufen. Wie gesagt, bei einem bash- oder Perl-Skript wird SUID vom Interpreter aus Sicherheitsgruenden ignoriert (bzw. unwirksam gemacht), genau deshalb ist dafuer ein Wrapper noetig. Fuer perl gibt es alternativ ein spezielles suidperl, das SUID-Skripte auch direkt ermoeglicht. Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org - eilert@linuxfreak.com http://www.informatik.uni-bremen.de/~eilert/ --------------------------------------------------------------------- To unsubscribe, e-mail: suse-linux-unsubscribe@suse.com For additional commands, e-mail: suse-linux-help@suse.com
participants (1)
-
eilert@Informatik.Uni-Bremen.DE