Linux ignoruje bit setuid¹ na wszystkich interpretowanych plikach wykonywalnych (tj. Plikach rozpoczynających się od #!
linii). Comp.unix.questions FAQ wyjaśnia problemy bezpieczeństwa z setuid skryptów powłoki. Problemy te są dwojakiego rodzaju: związane z shebangiem i związane z powłoką; Więcej szczegółów poniżej.
Jeśli nie dbasz o bezpieczeństwo i chcesz zezwolić na skrypty setuid, pod Linuksem musisz załatać jądro. Jeśli chodzi o jądra 3.x, myślę, że musisz dodać wywołanie install_exec_creds
w load_script
funkcji przed wywołaniem do open_exec
, ale nie testowałem.
Setuid shebang
Występuje warunek wyścigu nieodłącznie związany ze sposobem, w jaki shebang ( #!
) jest zwykle implementowany:
- Jądro otwiera plik wykonywalny i stwierdza, że zaczyna się od
#!
.
- Jądro zamyka plik wykonywalny i zamiast tego otwiera interpreter.
- Jądro wstawia ścieżkę do skryptu na listę argumentów (as
argv[1]
) i wykonuje interpreter.
Jeśli w tej implementacji dozwolone są skrypty setuid, osoba atakująca może wywołać dowolny skrypt, tworząc dowiązanie symboliczne do istniejącego skryptu setuid, wykonując go i organizując zmianę łącza po wykonaniu kroku 1 przez jądro i zanim interpreter przejdzie do otwierając swój pierwszy argument. Z tego powodu większość jednorożców ignoruje bit setuid, gdy wykrywa shebang.
Jednym ze sposobów zabezpieczenia tej implementacji byłoby zablokowanie pliku skryptu przez jądro, dopóki interpreter go nie otworzy (pamiętaj, że musi to zapobiegać nie tylko odłączeniu lub zastąpieniu pliku, ale także zmianie nazwy dowolnego katalogu na ścieżce). Ale systemy uniksowe zwykle unikają obowiązkowych blokad, a dowiązania symboliczne sprawiłyby, że poprawna funkcja blokady byłaby szczególnie trudna i inwazyjna. Nie sądzę, żeby ktokolwiek to robił w ten sposób.
Kilka systemów uniksowych (głównie OpenBSD, NetBSD i Mac OS X, z których wszystkie wymagają włączenia ustawienia jądra) implementuje bezpieczny shebang setuid za pomocą dodatkowej funkcji: ścieżka odnosi się do pliku już otwartego w deskryptorze pliku N (więc otwieranie jest z grubsza odpowiada ). Wiele systemów uniksowych (w tym Linux) ma skrypty setuid./dev/fd/N
/dev/fd/N
dup(N)
/dev/fd
- Jądro otwiera plik wykonywalny i stwierdza, że zaczyna się od
#!
. Powiedzmy, że deskryptorem pliku dla pliku wykonywalnego jest 3.
- Jądro otwiera interpreter.
- Jądro wstawia
/dev/fd/3
listę argumentów (as argv[1]
) i wykonuje interpreter.
Strona shebang Svena Maschecka zawiera wiele informacji na temat shebang u jednorożców, w tym wsparcie setuid .
Tłumacze Setuid
Załóżmy, że udało Ci się uruchomić program jako root, albo dlatego, że twój system obsługuje setuid shebang, albo dlatego, że użyłeś natywnego binarnego opakowania (takiego jak sudo
). Czy otworzyłeś lukę bezpieczeństwa? Może . Tutaj nie chodzi o programy interpretowane a skompilowane. Problem polega na tym, czy system wykonawczy zachowuje się bezpiecznie, jeśli jest wykonywany z uprawnieniami.
Każdy dynamicznie połączony natywny binarny plik wykonywalny jest w sposób interpretowany przez program ładujący dynamiczny (np. /lib/ld.so
), Który ładuje biblioteki dynamiczne wymagane przez program. W wielu jednostkach unikalnych można skonfigurować ścieżkę wyszukiwania bibliotek dynamicznych za pośrednictwem środowiska ( LD_LIBRARY_PATH
jest to wspólna nazwa zmiennej środowiskowej), a nawet załadować dodatkowe biblioteki do wszystkich wykonywanych plików binarnych ( LD_PRELOAD
). Wywołującego programu można wykonać dowolny kod w kontekście tego programu poprzez umieszczenie specjalnie spreparowane libc.so
w $LD_LIBRARY_PATH
(między innymi taktyki). Wszystkie zdrowe systemy ignorują LD_*
zmienne w plikach wykonywalnych setuid.
W powłokach, takich jak sh, csh i pochodne, zmienne środowiskowe automatycznie stają się parametrami powłoki. Poprzez parametrów takich jak PATH
, IFS
i wiele więcej, wywołującego skrypt ma wiele szans na wykonanie dowolnego kodu w kontekście skryptów powłoki. Niektóre powłoki ustawiają te zmienne na rozsądne wartości domyślne, jeśli wykryją, że skrypt został wywołany z uprawnieniami, ale nie wiem, czy istnieje jakaś konkretna implementacja, której mógłbym zaufać.
Większość środowisk wykonawczych (macierzystych, kodu bajtowego lub interpretowanych) ma podobne funkcje. Niewielu zachowuje szczególne środki ostrożności w plikach wykonywalnych setuid, chociaż te, które uruchamiają natywny kod, często nie robią nic bardziej wymyślnego niż dynamiczne łączenie (które podejmuje środki ostrożności).
Perl jest godnym uwagi wyjątkiem. To wyraźnie obsługuje skryptów setuid w bezpieczny sposób. W rzeczywistości skrypt może uruchamiać setuid, nawet jeśli system operacyjny zignorował bit setuid w skryptach. Wynika to z faktu, że Perl jest dostarczany z pomocnikiem setuid root, który wykonuje niezbędne kontrole i ponownie wywołuje interpreter na pożądanych skryptach z pożądanymi uprawnieniami. Jest to wyjaśnione w podręczniku perlsec . Kiedyś potrzebne były #!/usr/bin/suidperl -wT
zamiast tego skrypty pertu z setuid #!/usr/bin/perl -wT
, ale w większości nowoczesnych systemów #!/usr/bin/perl -wT
są wystarczające.
Zauważ, że użycie natywnego opakowania binarnego samo w sobie nie zapobiega tym problemom . W rzeczywistości może to pogorszyć sytuację , ponieważ może uniemożliwić środowisku wykonawczemu wykrycie, że jest wywoływane z uprawnieniami i pominięcie jego konfigurowalności.
Natywne opakowanie binarne może uczynić skrypt powłoki bezpiecznym, jeśli opakowanie dezynfekuje środowisko . Skrypt musi uważać, aby nie przyjmować zbyt wielu założeń (np. Dotyczących bieżącego katalogu), ale tak jest. Możesz użyć do tego sudo, pod warunkiem, że jest skonfigurowany do odkażania środowiska. Zmienne na czarnej liście są podatne na błędy, dlatego zawsze należy do białej listy. W sudo upewnij się, że env_reset
opcja jest włączona, że setenv
jest wyłączona env_file
i env_keep
zawiera tylko nieszkodliwe zmienne.
TL, DR:
- Setuid shebang jest niepewny, ale zwykle jest ignorowany.
- Jeśli uruchamiasz program z uprawnieniami (przez sudo lub setuid), napisz kod natywny lub perl lub uruchom program z opakowania, które dezynfekuje środowisko (takie jak sudo z
env_reset
opcją).
¹ Dyskusja ta ma zastosowanie również w przypadku zastąpienia słowa „setgid” słowem „setuid”; oba są ignorowane przez jądro Linuksa w skryptach
suidperl
rzeczy były przestarzałe i oznaczone do usunięcia przez lata (ale nadal są dostępne)suidperl
został usunięty od wersji Perla 5.11 (stabilny 5.12): perl5110delta:> „suidperl” został usunięty. Kiedyś zapewniał mechanizm emulacji bitów uprawnień setuid w systemach, które nie obsługują go poprawnie. perl5120delta:> „suidperl” nie jest już częścią Perla. Kiedyś zapewniał mechanizm emulacji bitów uprawnień setuid w systemach, które nie obsługują go poprawnie.Jednym ze sposobów rozwiązania tego problemu jest wywołanie skryptu powłoki z programu, który może używać bitu setuid.
to coś w stylu sudo. Na przykład oto, jak można to osiągnąć w programie C:
Zapisz go jako setuid-test2.c.
kompiluj
Teraz wykonaj setuid na tym programie binarnym:
Teraz powinieneś być w stanie go uruchomić, a zobaczysz, że twój skrypt jest wykonywany bez żadnych uprawnień.
Ale tutaj musisz albo zakodować ścieżkę skryptu, albo przekazać ją jako argument linii poleceń powyżej exe.
źródło
PATH
iLD_LIBRARY_PATH
są oczywistymi wektorami. Niektóre muszle wykonać$ENV
lub$BASHENV
lub~/.zshenv
jeszcze przed rozpoczęciem właściwego wykonywania skryptu, więc nie może chronić od nich w ogóle od wewnątrz skryptu. Jedynym bezpiecznym sposobem na wywołanie skryptu powłoki z uprawnieniami jest oczyszczenie środowiska . Sudo wie, jak to zrobić bezpiecznie. Więc nie pisz własnego opakowania, użyj sudo .LD_LIBRARY_PATH
między innymi, gdy napotka bit setuid.system
korzystać z jednej zexec
rodziny może być łatwiej (i wydajniej) - najprawdopodobniejexecve
. W ten sposób nie tworzysz nowego procesu ani nie uruchamiasz powłoki i możesz przekazywać argumenty (zakładając, że twój uprzywilejowany skrypt może bezpiecznie obsługiwać argumenty).Prefiksuję kilka skryptów znajdujących się w tej łodzi w ten sposób:
Zauważ, że to nie używa,
setuid
ale po prostu wykonuje bieżący plik za pomocąsudo
.źródło
sudo
monit. (Dla mnie sedno setuida polega na tym, że pozwala, aby rzeczy działały jako root bez potrzeby sudo.)Jeśli chcesz uniknąć dzwonienia
sudo some_script
, możesz po prostu:Programy SETUID należy projektować z najwyższą starannością, ponieważ działają z uprawnieniami roota, a użytkownicy mają nad nimi dużą kontrolę. Muszą wszystko sprawdzić zdrowo. Nie możesz tego zrobić za pomocą skryptów, ponieważ:
sed
,awk
itp. również musiałyby zostać sprawdzonePamiętaj, że
sudo
zapewnia pewne sprawdzanie poprawności, ale nie jest wystarczające - sprawdź każdą linię w swoim własnym kodzie.Ostatnia uwaga: rozważ użycie możliwości. Pozwalają one nadać procesowi działającemu jako użytkownik specjalne uprawnienia, które normalnie wymagałyby uprawnień administratora. Jednak na przykład, chociaż
ping
trzeba manipulować siecią, nie musi ona mieć dostępu do plików. Nie jestem jednak pewien, czy są one dziedziczone.źródło
/ust/bin/env
powinno być/usr/bin/env
.Możesz utworzyć alias dla sudo + nazwę skryptu. Oczywiście, jest to jeszcze więcej pracy, aby skonfigurować, ponieważ musisz także ustawić alias, ale to oszczędza ci konieczności wpisywania sudo.
Ale jeśli nie masz nic przeciwko strasznym zagrożeniom bezpieczeństwa, użyj powłoki setuid jako interpretera skryptu powłoki. Nie wiem, czy to zadziała dla ciebie, ale myślę, że może.
Chciałbym jednak powiedzieć, że odradzam to robić. Wspominam o tym w celach edukacyjnych ;-)
źródło
rm -rf /
(i inne polecenia z serii DON'T DO IT AT HOME ).komenda super [-r reqpath] [args]
Super pozwala określonym użytkownikom na wykonywanie skryptów (lub innych poleceń) tak, jakby byli rootami; lub może ustawić UID, GID i / lub dodatkowe grupy dla poszczególnych poleceń przed wykonaniem polecenia. Ma to stanowić bezpieczną alternatywę dla ustawiania skryptów jako root. Super umożliwia także zwykłym użytkownikom dostarczanie poleceń do wykonania przez innych; są one wykonywane z identyfikatorami UID, GID i grupami użytkowników oferujących polecenie.
Super sprawdza plik `` super.tab '', aby sprawdzić, czy użytkownik może wykonać żądane polecenie. Jeśli zezwolenie zostanie udzielone, super wykona pgm [args], gdzie pgm jest programem powiązanym z tym poleceniem. (Rootowanie jest domyślnie dozwolone, ale nadal można odmówić, jeśli reguła wyklucza rootowanie. Zwykłym użytkownikom domyślnie nie zezwala się na wykonywanie.)
Jeśli polecenie jest dowiązaniem symbolicznym (lub też linkiem twardym) do super programu, wówczas wpisanie% polecenie args jest równoważne z wpisaniem% super polecenia args (polecenie nie może być super, lub super nie rozpozna, że jest wywoływane przez połączyć.)
http://www.ucolick.org/~will/RUE/super/README
http://manpages.ubuntu.com/manpages/utopic/en/man1/super.1.html
źródło
Jeśli z jakiegoś powodu
sudo
nie jest dostępny, możesz napisać cienki skrypt opakowania w C:I po kompilacji to ustawić go jako
setuid
zchmod 4511 wrapper_script
.Jest to podobne do innej opublikowanej odpowiedzi, ale uruchamia skrypt w czystym środowisku i jawnie używa
/bin/bash
zamiast powłoki wywoływanej przezsystem()
, a zatem zamyka niektóre potencjalne luki w zabezpieczeniach.Pamiętaj, że całkowicie usuwa środowisko. Jeśli chcesz użyć niektórych zmiennych środowiskowych bez ujawniania luk, naprawdę musisz po prostu użyć
sudo
.Oczywiście chcesz się upewnić, że sam skrypt jest zapisywalny tylko przez root.
źródło
Po raz pierwszy znalazłem to pytanie, nieprzekonujące wszystkimi odpowiedziami, tutaj jest o wiele lepsze, które pozwala również całkowicie zaciemnić skrypt bash, jeśli jesteś tak skłonny!
Powinno to być oczywiste.
Potem biegniesz
źródło