2010-02-16 17 views
11

Próbuję zrobić coś bezpiecznego i mieć program, który musi działać jako root, aby zrzucić jego uprawnienia, gdy ich nie potrzebuje. Działa to dobrze, jeśli mój kod binarny jest ustawiony na bit SUID i sprawi, że będzie on należał do katalogu głównego, ponieważ teraz mam UID = pewien użytkownik, a EUID = root, więc mogę użyć odpowiednio seteuid(0) i seteuid(getuid()), aby podnieść i zrzucić uprawnienia administratora.Jak korzystać z setuid() z katalogu głównego, aby stać się użytkownikiem, z możliwością późniejszego odzyskania uprawnień administratora?

Ale jeśli użyję sudo zamiast ustawiania SUID, to UID == EUID == 0, a więc wywołanie seteuid(getuid()) nie będzie miało żadnego efektu. I nie mogę po prostu zmienić UID na jakąś wartość od jakiegoś losowego użytkownika, ponieważ strona man setuid() wyraźnie stwierdza, że ​​jeśli zostanie wywołana z programu działającego jako root, stracimy przywileje na dobre, bez nadziei na odzyskanie ich.

Co zrobić, aby mój program stracił czasowo swoje uprawnienia podczas uruchamiania z użyciem sudo?

+0

Czy musisz powrócić do UID użytkownika, który uruchomił 'sudo', czy tylko do przypadkowego, mniej uprzywilejowanego użytkownika? –

+0

Będę zadowolić się "nikim". ale jeśli znasz prosty sposób na uzyskanie rozmówcy sudo, jestem zainteresowany. – Florian

+3

meh, to proste, wystarczy 'getenv (" SUDO_UID ")'. – Florian

Odpowiedz

10

seteuid(some random uid) do upuszczania przywilejów, seteuid(0), aby je odzyskać, działając pod numerem root.

+3

Oczywiście - to pozostawia problem z uzyskaniem oryginalnego UID użytkownika, który nazwał 'sudo' - czy OP musi wrócić do tego użytkownika? –

+0

Oczywiście istnieje szansa, że ​​losowy UID, do którego się przełączysz, będzie przypadkiem identyfikatorem UID sysadmin. – immibis

+0

sudo tworzy zmienne środowiskowe zawierające identyfikator UID i GID użytkownika wywołującego. Możesz przełączyć na "nobody" odczytać zmienną i przejść do tego użytkownika. Nie polecam odczytywania zmiennych środowiskowych jako root. "nobody" to ograniczone konto obecne w większości systemów uniksowych. – wheredidthatnamecomefrom

6

Wydaje się seteuid (x) powinien pracować do spadku i ponownie podnieść privs ...

$ cat > t12.c 
#include <stdio.h> 
#include <unistd.h> 

void p(void) { printf("euid=%4d uid=%4d\n", geteuid(), getuid()); } 

int main(void) { p(); seteuid(100); p(); seteuid(0); p(); return 0; } 
$ cc -Wall t12.c 
$ sudo chown root a.out && sudo chmod 4555 a.out 
$ sudo ./a.out 
euid= 0 uid= 0 
euid= 100 uid= 0 
euid= 0 uid= 0 
$ ./a.out 
euid= 0 uid= 501 
euid= 100 uid= 501 
euid= 0 uid= 501 
$ 
+0

Jak upewnić się, że uid = 100 nie jest w grupie sudoers? – dashesy

+0

To ma znaczenie tylko dla samego sudo. Jedynym specjalnym przywilejem, jaki zapewnia grupa sudoers, jest możliwość użycia polecenia sudo. Nie powoduje to, że identyfikator użytkownika ma uprawnienia roota. – wheredidthatnamecomefrom

1

fork(), zanim spadnie przywileje. Zaczekaj w zadaniu nadrzędnym, dopóki nie zostanie wykonane dziecko o ograniczonych uprawnieniach, a następnie powróć do rodzica z rootem.

seteuid nie jest przenośny dla wszystkich abonentów i ma również inne wady.