Dlaczego „sudo su” w skrypcie powłoki nie uruchamia reszty skryptu jako root?

36

Przykładowy skrypt może wyglądać jak poniżej:

#!/bin/bash
sudo su
ls /root

Jeśli używasz ./test.shjako zwykły użytkownik, zamiast tego uruchom lsjako superużytkownik i wyjdź, przełącza się na root; a kiedy się wylogowuję, działa ls /rootjak zwykły użytkownik.

Czy ktoś może mi powiedzieć o tym mechanizmie?

Hongxu Chen
źródło
13
sudo subolą mnie oczy.
gelraen
Jest używany, ponieważ ludzie nie znają wystarczająco dobrze sudo, dlatego potrzebują sposobu na uruchomienie su w systemach, w których root jest zabezpieczony celowo uszkodzonym hasłem. Ale tak, sudo „redunduje” użycie su.
Johan
1
Nie możesz po prostu użyć sudo -s?
Joe Z.
@Johan, często używam, sudo suponieważ jestem bardziej przyzwyczajony do opcji suniż z tych sudo. Znam opcje sudo wystarczająco dobrze, ale mogę pisać su szybciej. Ale tak, myślę, że to oznacza, że ​​nie znam wystarczająco dobrze sudo.
user606723,
1
Właśnie sprawdziłem stronę podręcznika sudo. Wydaje się, sudo -ijest zbliżona do su -natomiast sudo -sdziała podobnie su(bez myślnika)
Johan

Odpowiedzi:

49

Polecenia w skrypcie są wykonywane pojedynczo, niezależnie. Sam skrypt jako rodzic wszystkich poleceń w skrypcie jest kolejnym niezależnym procesem, a polecenie su nie zmienia i nie może zmienić go na root: polecenie su tworzy nowy proces z uprawnieniami roota.

Po zakończeniu tej komendy su proces nadrzędny, nadal uruchomiony jako ten sam użytkownik, wykona resztę skryptu.

Co chcesz zrobić, to napisać skrypt opakowania. Uprzywilejowane polecenia przechodzą na przykład do skryptu głównego~/main.sh

#!/bin/sh
ls /root

Skrypt otoki wywołuje skrypt główny z uprawnieniami administratora, podobnie jak ten

#!/bin/sh
su -c ~/main.sh root

Aby uruchomić ten proces, uruchom opakowanie, które z kolei uruchamia główny skrypt po przełączeniu użytkownika na użytkownika root.

Tej techniki otoki można użyć do przekształcenia skryptu w otokę wokół siebie. Zasadniczo sprawdź, czy działa jako root, jeśli nie, użyj „su”, aby ponownie się uruchomić.

$ 0 to przydatny sposób na odniesienie się do skryptu, a komenda whoami może powiedzieć nam, kim jesteśmy (czy jesteśmy rootami?)

Tak więc główny skrypt z wbudowanym otokiem staje się

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

Zwróć uwagę na użycie exec. Oznacza to „zamień ten program na”, co skutecznie kończy jego wykonywanie i uruchamia nowy program, uruchamiany przez su, z rootem, aby działał od góry. Instancja zastępująca to „root”, więc nie wykonuje prawej strony ||

Johan
źródło
1
fwiw, dodatek do tego punktu. Gdybym pisał taki skrypt, zrobiłbym na początku instrukcję if, która sprawdza $ EUID, a jeśli nie jest to zero sudo i wychodzi, w przeciwnym razie kontynuuję wykonywanie skryptu.
Bratchley,
Zgodziłem się i zaktualizuję odpowiedź, aby to wyjaśnić.
Johan
2
Być może jest to nieco archaiczne, ale uwielbiam bezwzględne ścieżki do każdego pliku wykonywalnego, więc ktoś nie może zmienić skryptu ~ / main.sh na coś nikczemnego. Atakowanie części skryptu UŻYTKOWNIKA
artifex
2
Możesz także chcieć uchwycić argumenty, które zostały mu przekazane,
dołączając
@JoelDavis Zawsze wpadam na ścianę „co jeśli w argumentach są spacje”. Nigdy nie znalazłem zadowalającego rozwiązania. Kiedyś napisałem skrypt, który umieszcza swoje argumenty w pliku tymczasowym, po jednym argumencie w wierszu, a następnie nazwał wszystko, czego potrzebował i przekazał temu końcowemu skryptowi argument, w jakim pliku czytać, aby znaleźć oryginalne argumenty.
Johan
20

Użyj skryptu.

sudo su <<HERE
ls /root
HERE

Kod między blokiem TUTAJ zostanie uruchomiony jako root.

Ankit
źródło
6
sudo suwywołuje dwa programy. Użyj sudo -s <<HEREDOClub su user <<HEREDOC... Głupi limit 5 minut.
Johan
6

Bez dalszych argumentów suuruchomi powłokę logowania dla roota. Tak właśnie robi pierwsza linia skryptu. Po wyjściu z tego, zamyka powłokę zgłoszeniową, powraca su i kontynuuje wykonywanie skryptu, to z drugiej linii: ls /root. Myślę, że możesz po prostu sudo ls /rootrobić, co chcesz.

Bananguin
źródło
Tak, wiem, że mogę to zrobić ls, ale to tylko próbka. W rzeczywistości muszę robić o wiele więcej rzeczy z uprawnieniami roota :-) Wolę więc odpowiedź @ Ankit.
Hongxu Chen,
1

Gdy uruchomisz sudo sunowy proces z userid (euid=EUID)rozwidleniem superużytkownika, stąd mamy nowy bash działający na innym identyfikatorze procesu (pid=PID)powiązanym z tym samym terminalem (tname=TTY).

Wyjaśnienie

Załóżmy, że po odpaleniu ps -A | grep bashmasz 21460 pts/2 00:00:00 bashjako wyjście. Teraz, gdy wykonasz ./test.shoba polecenia sudo sui ls /rootzostaniesz buforowany do PID 21460. Po wykonaniu, gdy rootjako aktywny użytkownik uderzysz ps -A | grep bashponownie, zauważysz, że działa nowa bash PID say, 21570. Wyjście z root bashspowoduje zabicie nowo rozwidlonego uderzenia, powracając do, user's basha zatem wykonuje polecenie buforowane ls /rootprzed zwolnieniem monitu.

niedziela
źródło
Jeśli użycie su lub sudo było „trwałe” w bash (lub gdziekolwiek indziej), stworzyłoby o wiele więcej problemów niż rozwiązane. Musisz zrobić minimum możliwego jako root dla bezpieczeństwa i ochrony. Głównym celem posiadania su i sudo (innego niż bezpieczeństwo!) Jest sprawienie, abyś dokładnie przemyślał, jakie uprawnienia do rootowania wymagają.
Joe