Czy program może powiedzieć, że jest uruchamiany pod sudo?


27

Mam program, który powinien zachowywać się inaczej, jeśli jest uruchamiany pod „sudo”. Czy istnieje sposób, aby dowiedzieć się, czy został uruchomiony pod sudo?

Aktualizacja: Ktoś zapytał, dlaczego miałbym to zrobić. W tym przypadku na komputerze Mac korzystającym z MacPorts jest wyjście, które każe ci wyciąć i wkleić określone polecenie. Jeśli polecenie MacPorts zostało uruchomione z „sudo”, powinno ono zawierać sudo w przykładowym poleceniu:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)

Jestem ciekawy: czy możesz wyjaśnić, jak powinien on zachowywać się inaczej?
sciurus

1
@ sciurus zwykle częstym przypadkiem użycia jest skrypt instalacyjny, który wymaga uprawnień roota; jeśli ich nie masz, po prostu umrzyj natychmiast.
Nick T


Niejasno pamiętam jakieś polecenie, wiedząc, że jest uruchamiane jako root, czy nie ... Myślę, że odpowiedź brzmi „tak”
Rolf

Odpowiedzi:


48

Tak, są ustawione 4 zmienne środowiskowe, gdy program działa pod sudo:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

Pamiętaj, że można je sfałszować, po prostu je ustawiając. Nie ufaj im za nic krytycznego.

Na przykład: W tym programie musimy powiedzieć użytkownikowi, aby uruchomił jakiś inny program. Jeśli bieżący był uruchamiany z sudo, drugi też będzie.

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

Zauważ, że testuje zmienną SUDO_ * tylko wtedy, gdy może najpierw udowodnić, że działa jako root. Nawet wtedy używa go tylko do zmiany pomocnego tekstu.


2
Czego miałbym użyć do „czegoś krytycznego?”
Kevin - Przywróć Monikę

3
@Kevin, jeśli ktoś wkręca się w swoje otoczenie, by udawać, że ma podwyższone uprawnienia, to mam nadzieję, że wie, co robi i zaakceptuje konsekwencje.
Nick T

Odebrane, ponieważ każda odpowiedź, która musi zostać zakwalifikowana przez „nie ufaj im za coś krytycznego”, wcale nie jest odpowiedzią, ale brzydkim hackem.
Stephen C

Jest to całkowicie akceptowalna odpowiedź na zadane pytanie. Ostrzeżenie musi być dostępne dla osób, które mogą próbować zapobiec używaniu sudo, a nie tylko je wykryć . Zapobieganie powinno odbywać się za pomocą aliasów poleceń sudo, aby ograniczyć liczbę poleceń, które użytkownik może uruchamiać.
dwurf

11

To nie odpowiada bezpośrednio na pytanie, ale nie sądzę, aby zadawano tutaj właściwe pytanie. Wydaje mi się, że pytający chce programu, który prawdopodobnie będzie działał inaczej, jeśli ma pewne uprawnienia, ale nie twierdzę, że sprawdzanie sudo nie jest na to sposobem. Po pierwsze, wiele systemów może nie implementować „sudo”, nie jest to w żadnym wypadku wymagane w Linuksie lub wielu systemach uniksowych.

Na przykład użytkownik może być już zalogowany jako root, co powoduje, że sudo nie ma sensu, a może system ma użytkowników innych niż root, którzy nadal mają możliwości wykonywania zadań administracyjnych, które program może chcieć wykonać. Wreszcie być może system nie ma roota ani sudo i zamiast tego używa obowiązkowego systemu kontroli dostępu o różnych możliwościach i bez przechwytywania wszystkich superużytkowników do sudo. Albo użytkownik może zostać sudo, ale ze względów bezpieczeństwa na konto, które ma uprawnienia bez własnego konta (często uruchamiam niezaufany kod z tymczasowym nieuprzywilejowanym użytkownikiem, który może pisać tylko na ramdyskach, aby upuścić, a nie podnosić moje uprawnienia ). Ogólnie złym pomysłem jest zakładanie określonego modelu uprawnień, takiego jak sudo lub istnienie roota, lub zakładanie, że sudoedowany użytkownik ma jakieś szczególne uprawnienia.

Jeśli chcesz dowiedzieć się, czy masz uprawnienia do wykonania operacji, najlepszym sposobem jest zazwyczaj po prostu próba zrobienia tego, a następnie sprawdź, czy errno nie ma problemów z uprawnieniami, jeśli się nie powiedzie lub jeśli jest to operacja wieloetapowa, która musi zakończyć się niepowodzeniem lub powodzeniem możesz sprawdzić, czy operacja będzie działać z funkcjami takimi jak funkcja dostępu POSIX (strzeż się tutaj możliwych warunków wyścigu, jeśli uprawnienia są aktywnie zmieniane)

Jeśli dodatkowo musisz znać prawdziwego użytkownika za sudo, możesz użyć funkcji getlogin, która powinna działać dla każdej interaktywnej sesji z bazowym terminalem i pozwoli ci na przykład dowiedzieć się, kto „naprawdę” uruchamia polecenie do kontroli lub znaleźć katalog domowy prawdziwego użytkownika do zapisywania dzienników.

Wreszcie, jeśli naprawdę chcesz dowiedzieć się, czy użytkownik ma dostęp do roota (wciąż zły pomysł, ale mniej specyficzny dla implementacji), możesz użyć getuid, aby sprawdzić identyfikator użytkownika 0, a tym samym root.


7

Istnieją dwa mechanizmy, których można użyć.

  • Sprawdzanie zmiennych środowiskowych można sfałszować w obu kierunkach, ale jest to najłatwiejsze. growisofsnie lubi działać pod SUDO, więc zmieniłem zmienne SUDO w skryptach, w których ich używam. Można go sfałszować w drugą stronę. (Zmienna SUDO jest również przenoszona do środowiska dla skryptów uruchamianych za pomocą komend at i batch).
  • Innym sposobem sprawdzenia, czy działasz pod sudo, jest przejście listy procesów od procesu nadrzędnego w poszukiwaniu sudo. Trudno byłoby ukryć, że biegałeś w ten sposób w sudo, ale jest bardziej złożony. Nadal można sfałszować, że korzystasz z sudo.

Częściej sprawdza się, czy działasz jako odpowiedni użytkownik. W tym idcelu można użyć polecenia. Skrypt TomOnTime korzysta z idpolecenia, aby ustalić, czy sudomoże być wymagane uruchomienie następnego polecenia.


1
> Trudno byłoby ukryć, że działasz w sudo w ten sposób. Czy nie możesz po prostu zmienić nazwy pliku sudobinarnego na coś innego? Lub wymienić inny plik wykonywalny, sudoaby sfałszować coś przeciwnego? Nie dlatego, że naprawdę spodziewałbym się, że ktoś przy zdrowych zmysłach to zrobi ...
Bob

@ Bob Musisz mieć rootdostęp do zmiany nazwy sudopliku wykonywalnego. Normalny użytkownik nie byłby w stanie tego zrobić. Zauważyłem, że możesz udawać, że biegniesz sudo. Działa zmiana nazwy istniejącego programu. Kod wymagany dla dedykowanego fałszywego sudoprogramu jest trywialny.
BillThor

możesz po prostu pobrać skądś plik binarny sudo i nadać mu odpowiednie uprawnienia ...
Jens Timmerman

@JensTimmerman Aby uzyskać odpowiednie uprawnienia, musisz mieć uprawnienia roota. Jeśli możesz po prostu zmienić jego nazwę lub na stałe połączyć. Nie musisz go pobierać. Jeśli zainstalujesz SUID na docelowym identyfikatorze użytkownika (jeśli zadziała w ten sposób), musisz już skompromitować docelowy identyfikator użytkownika.
BillThor

ah, racja, odmawia pracy bez setuida, mój zły ...
Jens Timmerman

2

Możesz porównać efektywny i rzeczywisty identyfikator użytkownika.

Nie oznacza to ściśle, że działa cofanie sudo (może być również ustawione jako setuid), ale oznacza, że ​​program ma więcej uprawnień, niż może się spodziewać użytkownik. (na przykład w programie, który jest normalnie uruchamiany bez takich uprawnień, ale musi zostać uruchomiony z nimi podczas instalacji lub w celu zainstalowania aktualizacji. Następnie możesz użyć tego, aby przekazać ostrzeżenie o tym).


2
Nie, sudoustawia zarówno efektywny, jak i rzeczywisty identyfikator. W przeciwieństwie do suid, który nie. Oto trywialny program C, którego możesz użyć do przetestowania (przepraszam, komentarz usunie nowe wiersze, musisz je dodać z powrotem):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert

... lub, alternatywnie,perl -E 'say $<, "\n", $>'
derobert

2

Możesz sprawdzić efektywną zmienną UID (EUID) w następujący sposób:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi

To nie odpowiada na pytanie. Kod daje takie same dane wyjściowe, gdy jest uruchamiany jako root, jak w przypadku uruchamiania jako sudo.
Stephen C

@StephenC - myślę, że dla celów PO nie ma różnicy. IMHO ich celem jest identyfikacja wykonania sudo lub wykonania z autentycznej powłoki roota bez rozróżnienia.
Eliran Malka

1
Myślę, że masz rację. Przybyłem tutaj, ponieważ nie rozumiem, dlaczego sudo echo $USERwypisuje nieuprzywilejowaną nazwę użytkownika (zmienna jest podstawiona PRZED sudo). Właściwie skończyłem z użyciem twojego kodu w moim skrypcie. Dziękuję Ci!
Stephen C

jak najbardziej mile widziane :)
Eliran Malka

-1

Możesz dotknąć pliku, /roota następnie if -ego. A jeśli -e jest prawdziwe, rm(sprawdzanie kodu błędu), to twój test zadziała następnym razem.

Sprawdzanie kodu błędu (lub kodu powrotu) po rm uniemożliwia komuś wygodne użycie mocy sudo do utworzenia pliku, aby zagrać z tobą.


4
Ta odpowiedź sprawdza, czy proces ma uprawnienia do zapisu /root(co niekoniecznie jest takie samo jak uruchamianie jako UID 0), ale nie sprawdza, czy uzyskał te uprawnienia przy użyciu sudo.
Ladadadada,

Tak, „tysiąc sposobów na skórowanie kota”; kiedy pisałem odpowiedź, pomyślałem o kolejnych 4 lub 5 rzeczach, więc ją podsumowałem.
Chris K

-2

Przekonałem się, że to działa dobrze w tym przypadku

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]

To nie działa, gdy wypróbuję to na FreeBSD, Centos7 lub MacOS X. Myślę, że masz na myśli „/ proc” zamiast „/ etc”. Ale nawet przy tej zmianie nie działa na żadnej z tych trzech. „USER” jest resetowany przez sudo. Miałeś na myśli $ SUDO_USER? Czy miałeś na myśli „[[” zamiast „[”?
TomOnTime,

1
naprawiłem przykład. w zasadzie sprawdzanie loginuid nie jest równe 0, ale użytkownik jest rootem.
ruckc
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.