Hallo Leute, ich arbeite gerade an einem Problem, das ich mit suid loesen wollte. Ein selbst geschriebenes C-Programm , das ich als user wwwrun aufrufe, soll mit root-Rechten laufen. # chown root.uucp /sbin/boxprog # chmod 4750 /sbin/boxprog # usermod -G uucp wwwrun ~> /sbin/boxprog start das Programm legt seine PID in "/var/log/PID/" ab, dieses Verzeichnis hat die Rechte 775 root.root nun geschieht folgendes: - wenn ich das Programm als root aufrufe klapt alles - wenn ich das Programm als user wwwrun aufrufe, dann beendet sich das Programm wieder weil es seine PID nicht ablegen darf, also ein Rechte-Problem hat. sollte das Programm nicht mit vollen root-Rechten laufen ? Zuvor hatte ich das Problem mit sudo geloest, leider bin ich darauf angewiesen, dass die Eintraege mit einem script erfolgen muessen, damit Disketteninstallationen moeglich sind. Wenn ich dann eine vorgefertigte sudoers-Datei einfach auf einen Fremdrechner kopiere, dann besteht die Gefahr, dass sudo diese nicht akzeptiert, deshalb bin ich auf suid gekommen. hat jemand Rat Erich
* Erich Lindner schrieb am 27.Nov.2002:
ich arbeite gerade an einem Problem, das ich mit suid loesen wollte. Ein selbst geschriebenes C-Programm , das ich als user wwwrun aufrufe, soll mit root-Rechten laufen.
# chown root.uucp /sbin/boxprog # chmod 4750 /sbin/boxprog # usermod -G uucp wwwrun ~> /sbin/boxprog start
das Programm legt seine PID in "/var/log/PID/" ab, dieses Verzeichnis hat die Rechte 775 root.root nun geschieht folgendes: - wenn ich das Programm als root aufrufe klapt alles - wenn ich das Programm als user wwwrun aufrufe, dann beendet sich das Programm wieder weil es seine PID nicht ablegen darf, also ein Rechte-Problem hat.
sollte das Programm nicht mit vollen root-Rechten laufen ?
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest,
funktioniert es, aus den gleichen Gründen wie bei der shell direkt,
nicht. Siehe man system und da unter BUGS.
Leg Deine Datei mit fopen an, und beschreibe sie mit fprintf.
#include
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest, funktioniert es, aus den gleichen Gründen wie bei der shell direkt, nicht. Siehe man system und da unter BUGS.
Das Programm selbst wird ueber den Webserver mit system() aufgerufen. Das Programm ist ziehmlich komplex, und benoetigt auch fuer andere Aktionen root-Rechte, zB: das Oeffnen der Geraetedateien /dev/cub0 .. /dev/cub7 Es wird in diesem Programm auch ein Perl-script aufgerufen (aus Sicherheitsgruenden wird die Pruefsumme des Scrips ermittelt). Alles hatte wunderbar mit sudo geklappt. Nur wenn ich die sudoers-Datei von Rechner A auf Rechner B kopiere, dann weigert sich sudo diese Datei zu akzeptieren (ich hab keine Ahnung warum das so ist). Also dachte ich mir, ich kann die sudo-Funktionalitaet mit Vergabe von suid-Rechten ersetzen. Das ist aber anscheinend nicht der Fall. Ist es nicht doch Moeglich die sudoers -Datei irgendwie auf einen anderen Rechner zu uebernehmen, und "sudo" dazu zu bewegen das zu akzeptieren? Erich -- +++ GMX - Mail, Messaging & more http://www.gmx.net +++ NEU: Mit GMX ins Internet. Rund um die Uhr für 1 ct/ Min. surfen!
* Erich Lindner schrieb am 28.Nov.2002: Bitte Attributzeile stehen lassen, in dem der Vorredner, in diesem Fall ich, erwähnt wird.
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest, funktioniert es, aus den gleichen Gründen wie bei der shell direkt, nicht. Siehe man system und da unter BUGS.
Das Programm selbst wird ueber den Webserver mit system() aufgerufen.
Ja, und die man system sagt, daß das SUID-Bit aus Sicherheitsgründen nicht beachtet wird. Es wird empfohlen exec..() statt system() zu verwenden. Wenn man einen neuen Prozeß haben will, sollte man vorher ein fork() machen. system() ist sowieso ein Befehl, den man nicht verwenden sollte. Geht mit fork() und exec.. viel eleganter.
Das Programm ist ziehmlich komplex, und benoetigt auch fuer andere Aktionen root-Rechte,
Das habe ich schon verstanden. Dann darfst Du nicht system() verwenden. Braucht man auch nicht.
zB: das Oeffnen der Geraetedateien /dev/cub0 .. /dev/cub7 Es wird in diesem Programm auch ein Perl-script aufgerufen (aus Sicherheitsgruenden wird die Pruefsumme des Scrips ermittelt).
Na und? Kann man auch mit exec.. machen, etwa gleich mit dem Systemaufruf execve() benutzen sowieso alle anderen exec..s und auch system. Allerdings gibt es dann keine Wiederkehr. Daher sollte man vorher mit fork() einen neuen Prozeß starten. fork() macht eine exakte Kopie des aktuellen Prozesses. Einer bleibt so wie er ist, der andere erhält eine neue PID und die PID des anderen als PPID. Er wird somit zum Kindprozeß des anderen. Dem Elterprozeß gibt fork() die PID des Kindporzesses zurück und dem Kindprozeß gibt fork() 0 zurück. Dieser Prozeß kann dann execve() aufrufen und damit sich selber überschreiben. Das dritte Argument von execve() ist das gesamte Enviroment. Genauer ein Zeiger auf ein Array von Strings. Da kann man überprüfen, ob z.B der PATH stimmt, oder gleich einen eigenen mitgeben. Bei system() geht das nicht. Daher ist es unsicher. Auch benutzt es die shell, um einen Befehl auszuführen. Nicht nur, daß das reichlich umständlich ist, es ist auch unsicher. Bernd -- Bitte die Etikette beachten: http://www.suse-etikette.de.vu/etikette.html Bitte Realnamen angeben, kein Vollquoting, kein Html, PGP oder Visitenkarten benutzen. Signatur mit "-- " abtrennen, bei Antworten "Re: " voranstellen, sonst nichts. |Zufallssignatur 4
* Erich Lindner schrieb am 28.Nov.2002:
Bitte Attributzeile stehen lassen, in dem der Vorredner, in diesem Fall ich, erwähnt wird.
sorry, ich lass den oberen Bereich mal unveraendert, ich weiss nicht genau, ob ueber den gmx-Webmailer das korrekt uebermittelt wird, ich benutze normalerweise den pop/smtp-Zugang von gmx.
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest, funktioniert es, aus den gleichen Gründen wie bei der shell direkt,
^^^^^^^^^^^^^^
nicht. Siehe man system und da unter BUGS.
heisst das, dass der Programmaufruf als user "wwwrun" von der Kommandozeile das gleiche Problem verursacht, und wg. mangels Rechte die Ausfuehrung abgebrochen wird. also zuerst "su" root-Passwort und dann "su wwwrun" und dann "/sbin/boxprog start" diese Variante hatte ich auch probiert, allerdings ohne Erfolg Erich -- +++ GMX - Mail, Messaging & more http://www.gmx.net +++ NEU: Mit GMX ins Internet. Rund um die Uhr für 1 ct/ Min. surfen!
* Erich Lindner schrieb am 28.Nov.2002:
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest, funktioniert es, aus den gleichen Gründen wie bei der shell direkt,
^^^^^^^^^^^^^^
nicht. Siehe man system und da unter BUGS.
heisst das, dass der Programmaufruf als user "wwwrun" von der Kommandozeile das gleiche Problem verursacht, und wg. mangels Rechte die Ausfuehrung abgebrochen wird.
Du mußt Dein C-Programm umstricken. So wie Du es gemacht hast, also mit der Funktion system() funktioniert es nicht. Die Funktion system() nimmt das SUID-Bit weg. Genauso, wie es die bash tut, und mit genau der gleichen Begründung
also zuerst "su" root-Passwort und dann "su wwwrun"
Ob Du zuerst root warst oder nicht ist vollkommen schnurtz. Falls wwwrun ein Paßwort hat, kannst Du auch gleich su wwwrun wwwrun-Passwort eingeben. Macht wirklich keinen Unterschied.
und dann "/sbin/boxprog start"
/sbin/boxprog muß anders programmiert werden, ohne system() stattdessen mit fopen(), fclose() und fprintf() und gegebenenfalls auch mit execve() und fork() Bernd -- Bitte die Etikette beachten: http://www.suse-etikette.de.vu/etikette.html Bitte Realnamen angeben, kein Vollquoting, kein Html, PGP oder Visitenkarten benutzen. Signatur mit "-- " abtrennen, bei Antworten "Re: " voranstellen, sonst nichts. |Zufallssignatur 4
On Don, 28 Nov 2002 at 19:39 (+0100), Bernd Brodesser wrote:
* Erich Lindner schrieb am 28.Nov.2002:
Wie legst Du denn die Datei an? Wenn Du z.B system verwendest, funktioniert es, aus den gleichen Gründen wie bei der shell direkt,
^^^^^^^^^^^^^^
nicht. Siehe man system und da unter BUGS.
heisst das, dass der Programmaufruf als user "wwwrun" von der Kommandozeile das gleiche Problem verursacht, und wg. mangels Rechte die Ausfuehrung abgebrochen wird.
Du mußt Dein C-Programm umstricken. So wie Du es gemacht hast, also mit der Funktion system() funktioniert es nicht. Die Funktion system() nimmt das SUID-Bit weg. Genauso, wie es die bash tut, und mit genau der gleichen Begründung
Nein, das stimmt nicht. Die Ursache liegt im fehlenden setuid(0) Aufruf innerhalb des Programms. Siehe unten. [...]
/sbin/boxprog muß anders programmiert werden, ohne system() stattdessen mit fopen(), fclose() und fprintf() und gegebenenfalls auch mit execve() und fork()
Auch hier wieder: Nein. Der Weg über fork() und execve() ist sicher
der sauberere, aber es funktioniert auch so - man muss eben nur die
effektive UserID auch tatsächlich wechseln:
jan@k500:~/tmp> cat sid.c
#include
* Jan Trippler schrieb am 28.Nov.2002:
On Don, 28 Nov 2002 at 19:39 (+0100), Bernd Brodesser wrote:
/sbin/boxprog muß anders programmiert werden, ohne system() stattdessen mit fopen(), fclose() und fprintf() und gegebenenfalls auch mit execve() und fork()
Auch hier wieder: Nein. Der Weg über fork() und execve() ist sicher der sauberere, aber es funktioniert auch so - man muss eben nur die effektive UserID auch tatsächlich wechseln:
$ man system ... BUGS ... Do not use system() from a program with suid or sgid priv ileges, because strange values for some environment vari ables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with suid or sgid privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.) Ohne system funktioniert es bei mir genauso wie es soll. Bernd -- Was ist quoten? Quoten ist das Zitieren aus einer mail, der man antwortet. Und wie macht man es richtig? Zitate werden mit "> " gekennzeichnet. Nicht mehr als nötig zitieren. Vor den Abschnitten das Zitat, auf das man sich bezieht, mit einer Zeile Abstand oben und unten. |Zufallssignatur 12
Jan Trippler wrote:
On Don, 28 Nov 2002 at 19:39 (+0100), Bernd Brodesser wrote:
Du mußt Dein C-Programm umstricken. So wie Du es gemacht hast, also mit der Funktion system() funktioniert es nicht. Die Funktion system() nimmt das SUID-Bit weg. Genauso, wie es die bash tut, und mit genau der gleichen Begründung
Ich hab mich eventuell nicht korrekt ausgedrueckt. Das Programm selbst macht keinen "system()" -Aufruf sondern dieses wird ueber einen System() -Aufruf gestartet ( durch ein CGI-Script ). Allerdings wird in diesem Programm ein anderes Programm mit popen() kontaktiert ,und mit Kommandos gefuettert, und dieses ueber eine Pipe verbundene Programm erzeugt dann den Fehler.
Nein, das stimmt nicht. Die Ursache liegt im fehlenden setuid(0) Aufruf innerhalb des Programms. Siehe unten.
if (setuid (0) == -1) { printf ("Fehler bei setuid() (%d): %s\n", errno, strerror (errno)); return (0); }
das wars :-) ich hab dies im Programm aufgenommen und neu uebersetzt, und es funktioniert tatsaechlich. danke fuer eure Hilfe Erich
On Don, 28 Nov 2002 at 01:56 (+0100), Bernd Brodesser wrote:
* Erich Lindner schrieb am 27.Nov.2002:
ich arbeite gerade an einem Problem, das ich mit suid loesen wollte. Ein selbst geschriebenes C-Programm , das ich als user wwwrun aufrufe, soll mit root-Rechten laufen.
# chown root.uucp /sbin/boxprog # chmod 4750 /sbin/boxprog # usermod -G uucp wwwrun ~> /sbin/boxprog start
das Programm legt seine PID in "/var/log/PID/" ab, dieses Verzeichnis hat die Rechte 775 root.root nun geschieht folgendes: - wenn ich das Programm als root aufrufe klapt alles - wenn ich das Programm als user wwwrun aufrufe, dann beendet sich das Programm wieder weil es seine PID nicht ablegen darf, also ein Rechte-Problem hat.
sollte das Programm nicht mit vollen root-Rechten laufen ? [...]
Ich habe die Originalmail nicht mehr, deshalb hier: Das Set-UID-Bit der Programmdatei verleiht dem Programm nur das _Recht_, die effektive UID zu der des Eigentümers der Datei zu ändern und damit mit seinen Rechten zu laufen, das Programm muss es aber explizit tun (dazu hatte ich vor ein paar Wochen schon mal ausführlich was geschrieben im Thread *cdbakeoven*). Du musst also, bevor Du Aktionen ausführst, die Root-Rechte erfordern, erst die ID wechseln mit dem Call setuid(0) - dann klappts auch mit dem Nachbarn. Siehe dazu: man 2 setuid Noch ein Hinweis: Nach dem Anlegen der Datei solltest Du die effektive User-ID sofort wieder auf die des Benutzer (vor dem setuid() Aufruf mit getuid() zu ermitteln) zurücksetzen, um Sicherheitsrisiken möglichst gering zu halten. Jan
Hallo Jan, * Jan Trippler schrieb am 28.Nov.2002:
Das Set-UID-Bit der Programmdatei verleiht dem Programm nur das _Recht_, die effektive UID zu der des Eigentümers der Datei zu ändern und damit mit seinen Rechten zu laufen, das Programm muss es aber explizit tun (dazu hatte ich vor ein paar Wochen schon mal ausführlich was geschrieben im Thread *cdbakeoven*).
Du musst also, bevor Du Aktionen ausführst, die Root-Rechte erfordern, erst die ID wechseln mit dem Call setuid(0) - dann klappts auch mit dem Nachbarn. Siehe dazu: man 2 setuid
Nein. Das kann gar nicht sein. Es wird das effektive Recht überrüft,
nicht das reale. Wenn das effektive Recht stimmt, dann darf man.
Ich habe es doch auch mit fopen versucht, und es funktioniert.
---------------------------------------------------------------
#include
On Don, 28 Nov 2002 at 21:41 (+0100), Bernd Brodesser wrote:
* Jan Trippler schrieb am 28.Nov.2002:
Das Set-UID-Bit der Programmdatei verleiht dem Programm nur das _Recht_, die effektive UID zu der des Eigentümers der Datei zu ändern und damit mit seinen Rechten zu laufen, das Programm muss es aber explizit tun (dazu hatte ich vor ein paar Wochen schon mal ausführlich was geschrieben im Thread *cdbakeoven*).
Du musst also, bevor Du Aktionen ausführst, die Root-Rechte erfordern, erst die ID wechseln mit dem Call setuid(0) - dann klappts auch mit dem Nachbarn. Siehe dazu: man 2 setuid
Nein. Das kann gar nicht sein. Es wird das effektive Recht überrüft, nicht das reale. Wenn das effektive Recht stimmt, dann darf man.
Hmm, jetzt müsste man IMHO mal tiefer in die System-Calls einsteigen. Dein fopen() klappt ohne setuid() (auch in /var/run), der system() klappt nur mit setuid() - siehe meine andere Mail. Andere Funktionen (wie z. B. ein stat("/etc/shadow", R_OK) - das hatte ich vor ein paar Wochen mal in einem anderen Thread benutzt) klappen auch nur _mit_ setuid(). man setuid() sagt auch aus, dass hier die _effektive_ User-ID gesetzt wird. [Programm]
Dieses Progrämmchen übersetzt. Den Owner root.root geben und das SUID-Bit setzen. Anschließend ausführen. Falls die Datei suid.out noch nicht existiert, wird sie angelegt und hat die Rechte root.root.
root:user bei mir (es ist ja nur das SUID-Bit gesetzt). Mir stellt sich jetzt die Frage, warum fopen() klappt - das widerspricht meiner Weltanschauung ;-) Jan
* Jan Trippler schrieb am 28.Nov.2002:
Hmm, jetzt müsste man IMHO mal tiefer in die System-Calls einsteigen. Dein fopen() klappt ohne setuid() (auch in /var/run), der system() klappt nur mit setuid() - siehe meine andere Mail. Andere Funktionen (wie z. B. ein stat("/etc/shadow", R_OK) - das hatte ich vor ein paar Wochen mal in einem anderen Thread benutzt) klappen auch nur _mit_ setuid().
man setuid() sagt auch aus, dass hier die _effektive_ User-ID gesetzt wird.
Ich habe mir das ganze mal angetan, und mal Manpages gelesen und ein
wenig rumprobiert. Schon alles etwas gaga.
Insgesamt gibt es vier verschiedene UIDs. GIDs habe ich nicht
untersucht, wird wohl so ähnlich sein, höchstens noch etwas
komplizierter, weil es neben der primäre Gruppe noch andere Gruppen
geben kann.
Die /etc/passwd wird bei allen Systemaufrufen nicht berücksichtigt.
Es ist vollkommen ohne Belang, ob es den jeweiligen UID in der
/etc/passwd gibt, oder nicht.
Die vier UIDs sind:
Der reale UID kurz ruid.
Der effektive UID, kurz euid.
Der abgesicherte UID, kurz suid. Hat direkt nichts mit dem SUID-Bit
zu tun, wird aber leider allgemein so bezeichnet, für savedUID. Ich
habe es so belassen. Den Namen sollte man nicht allzuviel Bedeutung
bemessen.
Der fsuid, was immer das heißen mag.
Der Prozeß hat Superuserprivilegien, sobald der euid gleich 0 ist.
Die Rechte einer Datei werden anhand des fsuid ausgewertet. Hier
nützt die 0 im euid nichts, hier zählt nur der fsuid.
Wenn ein Prozeß gestartet wird, dann werden alle vier UIDs
beibehalten. Wenn das SUID-Bit gesetzt ist, so wird nur der ruid
beibehlaten. euid, suid und fsuid bekommen den UID der Datei, die
ausgeführt wird. Wenn diese Datei root gehört, so werden sie somit
auf 0 gesetzt. Insbesondere auch der euid.
Zur Veränderung der UIDs gibt es folgende Systemaufrufe:
setuid
seteuid
setresuid
setfsuid
setreuid
Zur Anzeige die folgende:
getuid
geteuid
getresuid
getuid und geteuid haben keine Argumente und geben den ruid, bzw.
den euid aus. getresuid bekommt als Argument drei Zeiger, in dem
ersten wird der ruid, im zweiten der euid und im dritten der suid
abgelegt.
*** Erich Lindner (E-Lindner@gmx.de) schrieb in suse-linux am Nov 27, 2002:
[...] ich arbeite gerade an einem Problem, das ich mit suid loesen wollte. Ein selbst geschriebenes C-Programm , das ich als user wwwrun aufrufe, soll mit root-Rechten laufen. [...]
das Programm legt seine PID in "/var/log/PID/" ab,
Bitte halte Dich an die Konvention und lege sowas unter "/var/run/" ab.
dieses Verzeichnis hat die Rechte 775 root.root nun geschieht folgendes: - wenn ich das Programm als root aufrufe klapt alles - wenn ich das Programm als user wwwrun aufrufe, dann beendet sich das Programm wieder weil es seine PID nicht ablegen darf, also ein Rechte-Problem hat.
Dann hast Du einen Fehler gemacht, wie zum Beispiel die Rechte doch falsch gesetzt oder Dein Programm gibt Rechte ab, bevor es seine PID schreibt. Wenn es tatsächlich ein kompiliertes Programm ist und die Rechte richtig gesetzt sind, läuft entweder auch Dein Programm oder _kein_ Programm per suid.
sollte das Programm nicht mit vollen root-Rechten laufen ?
Sollte es.
[...]
-- Intel Outside ;-)
Hallo Erich, hallo Leute, ich hab zwar vom Programmieren unter Linux sehr wenig Ahnung, aber vielleicht kann ich Dir doch helfen. -> man Archiv ;-) Am Mittwoch, 27. November 2002 23:17 schrieb Erich Lindner:
ich arbeite gerade an einem Problem, das ich mit suid loesen wollte. Ein selbst geschriebenes C-Programm , das ich als user wwwrun aufrufe, soll mit root-Rechten laufen.
# chown root.uucp /sbin/boxprog # chmod 4750 /sbin/boxprog # usermod -G uucp wwwrun ~> /sbin/boxprog start
das Programm legt seine PID in "/var/log/PID/" ab, dieses Verzeichnis hat die Rechte 775 root.root nun geschieht folgendes: - wenn ich das Programm als root aufrufe klapt alles - wenn ich das Programm als user wwwrun aufrufe, dann beendet sich das Programm wieder weil es seine PID nicht ablegen darf, also ein Rechte-Problem hat.
sollte das Programm nicht mit vollen root-Rechten laufen ?
Wenn ich es richtig verstanden habe: Jein ;-) Aus einer Mail von Jan Trippler auf suse-programming (23.11.2002) Message-ID: <20021123020336.E6746@P75.privat.jan> | Hast Du per setuid(0) die effektive User-ID nach root gewechselt? | Die Set-ID Bits des Programms geben dem Programm nur das Recht, die | ID zu wechseln, das Programm muss selbst dafür sorgen. Siehe | man setuid | man setgid Wenn ich es richtig verstehe, hat Dein Programm durch das chmod das Recht erhalten, seine UID zu wechseln... Und solange es dieses Recht nicht nutzt, läuft es IMHO weiterhin unter wwwrun. Gruß Christian Boltz -- ah verstehe! Das wird ins RAM geschrieben und wenn das voll ist, wird auf Platte geswapt bis zum geht nicht mehr, der host fällt aus, der Herzschlag steigt, failover greift, drbd synchronisiert noch schnell mit dem Rechenzentrum in Atlantic-City und zu guter letzt schreibt round ro- bin seine Info auf Diskette. Alles klar ;) [Andreas Meyer in suse-linux]
participants (6)
-
B.Brodesser@t-online.de
-
Christian Boltz
-
Erich Lindner
-
Erich Lindner
-
Henning Hucke
-
Jan.Trippler@t-online.de