Upuść uprawnienia do procesu

12

Mam proces, który zaczyna się od damona działającego jako root, teraz chcę „obniżyć” uprawnienia tego procesu do uprawnień przeciętnego użytkownika. czy to możliwe? Jeśli tak jak?

PS: Uruchamianie unixa na komputerze Mac

Samantha Catania
źródło

Odpowiedzi:

5

Sam proces musi wywoływać setuid (2). Powinieneś także zbadać uruchomienie go w chroot (8), jeśli jeszcze tego nie zrobiłeś. O ile mi wiadomo, root nie może zmienić UID innego procesu.

Jeśli powodem, dla którego uruchamiasz go jako root, jest powiązanie portów, sugerowałbym uruchomienie go jako normalnego użytkownika na wyższym porcie i użycie ipfw (8) w OS X do przekazania portu 80/443 / etc na wyższy port:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx

wielomian
źródło
W moim programie uruchamiam setuid (UID), który działa jako root, ale muszę go uruchamiać jako zwykły użytkownik i nic się nie dzieje, tj. Nadal działa jako root
Samantha Catania,
Prawdopodobnie musisz wtedy wychwycić z niego błędy (być może dostajesz EINVAL dla UID). Jego nieprawdopodobna setuid jest uszkodzona na twoim komputerze, który możesz zweryfikować, sprawdzając, czy apache działa jako _www. Dokumentacja programisty
wielomian
masz rację, daje błąd składniowy z UID, nawet jeśli jest poprawny. czy to jest właściwy format setuid (500)?
Samantha Catania
znalazłem problem: Próbowałem uruchomić polecenie przez system (), ale po prostu uruchomiłem polecenie, które zadziałało i rozwiązałem problem; dziękuję za pomoc
Samantha Catania
Nie. To nie jest dobra rada: setuid()samo dzwonienie absolutnie nie wystarczy.
Nicholas Wilson
13

sudo tcpdump -Z używa initgroups (3), setgid (2) i setuid (2), aby usunąć uprawnienia root'a do własnego procesu.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}
phron
źródło
2
Poprawny. initgroups, setgid, setuid(Wreszcie!) Jest właśnie prawo paradygmat UNIX, i zawsze powinny być przestrzegane. Ponadto odpowiedzialna funkcja „droproot” sprawdza, czy jej identyfikator uid i gid rzeczywiście zostały ustawione, nawet jeśli wszystkie trzy podstawowe funkcje zwróciły sukces.
Nicholas Wilson
3

Możesz uruchamiać polecenia tak, jak inni użytkownicy, używając su:

 su USERNAME -c COMMAND

Będzie działać COMMANDz upuszczonymi uprawnieniami USER.


Zauważ, że domyślnie sudo interpretacji polecenia użyje interpretera powłoki docelowego użytkownika. Natomiast domyślnym zachowaniem sudojest traktowanie programu COMMANDjako samodzielnego programu, czyli bieżącego środowiska. Oczywiście te domyślne zachowania można zmienić za pomocą różnych przełączników i zmiennych środowiskowych.

rozcietrzewiacz
źródło
Wygląda na to, suże nie działa, jeśli USERNAME nie ma zdefiniowanej powłoki (lub /bin/false), podczas gdy sudo działa.
Aif
1
@Aif Jeśli użytkownik nie może uruchamiać interaktywnych poleceń, to zachowanie domyślnesu to odzwierciedli. Jednak zawsze można to zmienić za pomocą -sprzełącznika. Zauważ, że celem sujest naśladowanie zachowania danego użytkownika - na co zwykle ma wpływ jego / jej powłoka. Z drugiej strony sudo(domyślnie) zignoruje ustawienie powłoki docelowego użytkownika.
rozcietrzewiacz
Nie, nie uruchamiaj rzeczy przy użyciu powłoki, aby po prostu zrzucić uprawnienia. To pozostawia zbyt dużą kontrolę nad atakującym, czytając w różnych plikach konfiguracyjnych, których nie chcesz dotykać.
Nicholas Wilson
2

Aby upuścić uprawnienia, musisz mieć uprawnienia użytkownika innego niż root. Następnie wystarczy przejść do tego użytkownika:

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

Zauważ, że odbywa się to w samym programie , a nie w skrypcie opakowania. Wiele programów wymaga uprawnień roota do określonego celu (np. Do połączenia z portem o niskim numerze), ale potem nie potrzebuje roota. Programy te będą więc uruchamiać się jako root, a następnie upuszczać uprawnienia, gdy nie będą już potrzebne.

Jeśli w ogóle nie potrzebujesz uprawnień roota, po prostu nie uruchamiaj go jako root. Na przykład:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
tylerl
źródło
1
Pamiętaj, że pozwala to procesowi odzyskać uprawnienia, jeśli chce! setuidFunkcja ustawia tylko efektywne UID, a nie rzeczywisty UID. Powinieneś użyć, setreuidjeśli nie chcesz, aby proces mógł odzyskać uprawnienia. (A powyższy kod nie dotyczy również dodatkowych uprawnień grupowych. Jest odpowiedni tylko do uruchamiania najbardziej zaufanego kodu.)
David Schwartz
Kod Davida Schwartza został celowo uproszczony, aby pokazać zastosowany mechanizm.
tylerl
Jeśli masz zamiar uprościć zabezpieczeń krytycznych kod, trzeba zrobić to bardzo oczywiste, że to co robisz. I powinieneś powiedzieć rzeczy takie jak „to tylko kwestia”, kiedy tak nie jest.
David Schwartz,
2
@David Właściwie setuid()ustawia rzeczywiste i zapisane identyfikatory użytkownika; możesz myśleć seteuid(). Nie wszystkie systemy mają setreuid(), więc nie można go używać wszędzie. Dokładna semantyka setuid()jest skomplikowana, ale jeśli masz euid 0, będziesz w stanie porzucić wszystkie tradycyjne uprawnienia identyfikatora użytkownika setuid(). Największym pominięcie w tej odpowiedzi jest to, że initgroupsalbo setgroupsmusi zostać wywołana, jak setgidi setuid, i że bardziej wnikliwe twierdzenia powinny być wykonywane na końcu.
Nicholas Wilson
0

Jeśli wykonujesz inny plik wykonywalny, np. Wywołujesz execvelub inną execrodzinę funkcji, być może pośrednio przez funkcję taką jak systemlub popen, a proces potomny powinien działać bez uprawnień od samego początku, najprostszym sposobem jest uzyskanie zaangażowana powłoka i zadzwoń su. Oto przegląd tego, jak może wyglądać kod w Perlu, wraz z cytowaniem potrzebnym do:

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

Jeśli proces potomny musi zostać uruchomiony jako root, ale później upuść uprawnienia, zapoznaj się z kodem w tej odpowiedzi , który ilustruje sposób obniżenia uprawnień w procesie.

Gilles „SO- przestań być zły”
źródło