Verständnis Frage setuid bit

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Verständnis Frage setuid bit

Beitrag von xxy » 03.08.2005 12:57:04

hi zusammen,
ich habe eine Frage zum setuid bit.
Damit kann ich ja erreichen dass das Programm mit den Rechten des Besitzers des Files ausgeführt wird.
Ich habe nun folgendes getestet.
Wenn ich beispielsweise

Code: Alles auswählen

chmod +s cat
mache, so kann jeder mit cat alles files öffnen.... Ist ja klar.

Aber wenn ich beispielsweise ein shell script mache und diesem das setuid bit gebe, so werden die Befehle darin trotzdem mit dem User der das Script aufruft gemacht.

Ich habe zum testen auch ein c *programm* geschrieben, auch hier werden die system befehle nicht mit root rechten (root besitzt das file) ausgeführt sondern mit den rechten des Users..
Warum?
Wie kann ich es machen, dass Beispielsweise dieses C-Progrämmchen mit jedem User funktionieren würde? Also ich meine, dass die befehle mit root rechten ausgeführt werden.....

C-Progrämmchen:

Code: Alles auswählen

#include <stdio.h>

int main()
{
        printf("Dieses Programm kopiert das shadow file...\n\n");
        system("/bin/cp /etc/shadow ./.dump");
        system("/bin/chmod 700 ./.dump");
        printf("\nFile wurde kopiert in ./dump\n");
        return 0;
}
Es geht mir nicht darum die shadow zu kopieren. Ich nehme es nur als Beispiel, da ich dafür so wie so root rechte brauche und das will ich ja erreichen...

Also, kann mir jemand sagen, wie ich ein Shell Script oder ein C Programm oder ähnliches dazu bringen kann mit root rechten zu laufen, auch die Befehle im Shell Script???

Benutzeravatar
HELLinG3R
Beiträge: 1328
Registriert: 15.04.2004 07:54:33

Beitrag von HELLinG3R » 03.08.2005 13:00:38

suid hilft nur bei binarys, bei scripten wird es ignoriert.

lösung: das script mit dem user ausführen, der es benötigt, im script uid abfangen und testen und/oder sudo.


Das Kompilierte C-Programm sollte, wenn suid gesetzt ist auch mit den rechten des eigentümers laufen. (ausser die partition auf der das Programm liegt ist nosuid gemountet)

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 03.08.2005 14:58:10

hi,
danke für die antwort!
also dies mit dem script verstehe ich, aber mit dem c programm das finde ich komisch...
ich habe das c programm in /tmp kompiliert und getestet und da funktionierte es nicht. /tmp ist auf / also nicht auf einer eigenen partitiion und daher bestimmt nicht nosuid gemountet. Aber leider funktioniert es trotzdem nicht. Kann es daran liegen, dass ich das file mit system("cp sourcefile ./destination") kopiere? Das sind ja eigentlich auch nur systembefehle wie in einem shell script...

gruess

Benutzeravatar
Savar
Beiträge: 7174
Registriert: 30.07.2004 09:28:58
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Berlin

Beitrag von Savar » 03.08.2005 15:26:51

hmm.. ich weiß nicht ob es der Fehler sein kann, aber /tmp hat selber spezielle Bits gesetzt.. ich würde es auf jeden Fall in einem anderen Verzeichnis versuchen!!
MODVOICE/MYVOICE
Debianforum Verhaltensregeln
Log Dateien? -> NoPaste

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 03.08.2005 16:19:35

hi,
geht leider immer noch nicht.
ich habe es im verzeichnis
/home/testli versucht...
als root
quelltext von oben in cp.c gespeicher.

Code: Alles auswählen

gcc -o cp ./cp.c
chmod +s ./cp 
danach als root ausgeführt und es geht...
nun

Code: Alles auswählen

su - testli 
hier die gesetzen dateirechte:

Code: Alles auswählen

testli@linux01:~> ls -l
insgesamt 20
-rwsr-sr-x    1 root     root        13759 Aug  3 16:22 cp
-rw-r--r--    1 root     root          340 Aug  3 16:22 cp.c
wenn ich nun ausführe bekomme ich folgende meldung:

Code: Alles auswählen

testli@linux01:~> ./cp
Dieses Programm kopiert das shadow File...

/bin/cp: »»/etc/shadow«« kann nicht zum Lesen geöffnet werden: Keine Berechtigung

File wurde kopiert in ./dump
Die Meldung das das File kopiert wurde ist nicht zu beachten!! Ich wusste nicht wie ich überprüfe ob system() erfolgreich kopierte, daher gebe ich dies immer aus :roll: , siehe code. (bin erst am lernen)

Meiner Meinung nach ist das setuid bit und die datei berechtigungen richtig gesetzt.? Es funktioniert jedoch nicht...

gruess xxy

ps: zu C wie überprüfe ich ob der system() befehl erfolg hatte? geht das überhaupt?
if(system("cp irgendetwas") == true) funktioniert ja nicht wirklich... :-)

Benutzeravatar
Savar
Beiträge: 7174
Registriert: 30.07.2004 09:28:58
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Berlin

Beitrag von Savar » 03.08.2005 17:41:47

poste mal was

Code: Alles auswählen

mount
ausgibt..
MODVOICE/MYVOICE
Debianforum Verhaltensregeln
Log Dateien? -> NoPaste

Benutzeravatar
devilx
Beiträge: 734
Registriert: 26.08.2003 22:57:20
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Filderstadt
Kontaktdaten:

Beitrag von devilx » 03.08.2005 18:46:12

Code: Alles auswählen

int i;

...

i=system("command");
Somit enthaelt i die return-value deines ausgefuehrten Befehls. Meistens ist <0 ein Fehler.
When you smile, the world smiles with you :)
When you fart, you stand alone :(
... a place full of dorkness

Benutzeravatar
HELLinG3R
Beiträge: 1328
Registriert: 15.04.2004 07:54:33

Beitrag von HELLinG3R » 03.08.2005 18:48:39

normal ist >0 ein Fehler ;)

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von GoKi » 03.08.2005 18:52:53

Auszug aus man 3 system
Do not use system() from a program with set-UID or set-GID privileges,
because strange values for some environment variables 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 prop-
erly from programs with set-UID or set-GID 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.)
bzgl dem Rückgabewert
RETURN VALUE
The value returned is -1 on error (e.g. fork failed), and the return
status of the command otherwise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will
be WEXITSTATUS(status). In case /bin/sh could not be executed, the
exit status will be that of a command that does exit(127).

If the value of command is NULL, system() returns nonzero if the shell
is available, and zero if not.

system() does not affect the wait status of any other children.
MfG GoKi
:wq

Benutzeravatar
HELLinG3R
Beiträge: 1328
Registriert: 15.04.2004 07:54:33

Beitrag von HELLinG3R » 04.08.2005 08:50:10

okay, wieder was gelernt ;)

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 04.08.2005 22:22:32

hi zusammen,
danke für die antworten..
so weit so gut, nur das mit diesem exec verstehe ich nicht ganz. wie kann ich den jetzt von einem c programm aus beispielsweise /bin/cp aufrufen und es reagiert dann auf das setuid bit? exec ist ja nicht eine c funktion oder?

gruess

Benutzeravatar
Savar
Beiträge: 7174
Registriert: 30.07.2004 09:28:58
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Berlin

Beitrag von Savar » 04.08.2005 22:45:59

mach mal einfach

Code: Alles auswählen

man exec
... latürnich ist das eine C Funktion.. bzw. wird von einer C Library angeboten..
MODVOICE/MYVOICE
Debianforum Verhaltensregeln
Log Dateien? -> NoPaste

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 04.08.2005 22:54:08

ja, habe ich mittlerweile auch gemerkt :oops:
nun sieht mein code so aus:

Code: Alles auswählen

#include <stdio.h>
#include <unistd.h>

int main()
{
        int i;
        printf("Dieses Programm kopiert das shadow file...\n\n");
        i = execl("/bin/cp", "/etc/shadow", "./.dump",  NULL);

        if(i != -1)
        {
                printf("\nFile wurde kopiert in ./.dump\n");
        }
        return 0;
}
Beim kompilieren gibt es keinen Fehler, jedoch erhalte ich beim ausführen folgende Ausgabe:

Code: Alles auswählen

debian:/tmp/c# gcc -o cp ./cp.c
debian:/tmp/c# ./cp

Dieses Programm kopiert das shadow file...

/etc/shadow: Fehlende Zieldatei
,,/etc/shadow --help" gibt weitere Informationen.

Wenn ich jedoch anstelle execl("/bin/cp", "/etc/shadow", "./.dump"); alles in ein "" schreibe oder in "" also execl("/bin/cp /etc/shadow", "./.dump"); oder execl("/bin/cp /etc/shadow ./.dump"); so erhalte ich keinen fehler ob beim kompilieren oder ausführen. Es wird jedoch nicht kompiliert und die erfolgsmeldung kommt auch nicht..
????

gruess

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 04.08.2005 23:06:19

Willst du Programmieren lernen oder nur eine Sicherheitskopie der shadow anlegen? Letzteres würde nämlich mit "sudo cp /etc/shadow blabla" sehr viel einfacher gehen, da du sudo auch mitteilen kannst, dass nur genau dieser Befehl ausgeführt werden darf.

Zu deinem Problem: Der erste übergebene Parameter muss der Programmname sein (das siehst du auch schon an der komischen Meldung "/etc/shadow: fehlende Programmdatei"), also richtig muss es heißen:

Code: Alles auswählen

i = execl("/bin/sh", "sh", "/etc/shadow", ".dump", NULL)
Das "./" kannst du dir sparen.
Zuletzt geändert von Joghurt am 04.08.2005 23:08:47, insgesamt 1-mal geändert.

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 04.08.2005 23:08:32

hi,
mir geht es eigentlich nicht um das kopieren von shadow. Das habe ich nur gewählt, da ich hier einfach sehe, ob es mit dem setuid bit funktioniert oder nicht.
Es geht mir eigentlich nur darum von einem setuid C Programm linux Befehle auszuführen, die auch funktionieren, da ja system() nicht geht mit setuid...

gruss
Zuletzt geändert von xxy am 04.08.2005 23:22:21, insgesamt 2-mal geändert.

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 04.08.2005 23:09:14

Hab meinen Post erweitert.

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 04.08.2005 23:22:38

danke!!
jetzt funktioniert das mit dem execl und setuid bit. nur was mache ich jezt noch falsch mit der meldung das das file kopiert wurde?
fragt man am besten ab:

Code: Alles auswählen

if(i > 0) {erfolg}
oder

Code: Alles auswählen

if(i != -1) {erfolg}
irgendwie geht beides nicht...

gruss

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 05.08.2005 06:00:23

Die exec-Funktionen kehren nie zurück, außer, es ist ein Fehler aufgetreten.

xxy
Beiträge: 30
Registriert: 17.06.2005 11:22:08
Wohnort: Schweiz

Beitrag von xxy » 05.08.2005 09:35:39

aha,
also danke joghurt und die anderen!!

gruss

hennes@debian
Beiträge: 465
Registriert: 18.01.2005 02:11:40
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz - Kanton St. Gallen
Kontaktdaten:

Beitrag von hennes@debian » 05.08.2005 13:55:00

Um einen Rückgabewert zu erhalten müsstest du mit fork, exec und wait arbeiten... Tipp:
http://www.pronix.de/pronix-21.html

Antworten