Dostęp do uprawnień administratora w świecie IT jest kluczowy. W przypadku PowerShella weryfikacja czy dany skrypt, polecenie czy samo okno konsoli zostało uruchomione z odpowiednimi uprawnieniami, jest niezwykle przydatne, ponieważ pozwala uniknąć wielu niebezpiecznych sytuacji. W tym artykule przedstawię kilka prostych metod, które pomogą zweryfikować obecny status.
Dlaczego warto?
Zanim zaczniemy zagłębiać się w konkretne przykłady warto najpierw rozważyć, dlaczego warto zaprzątać sobie głowę tym tematem. Sprawdzenie, czy skrypt posiada uprawnienia administratora, ma kluczowe znaczenie z kilku istotnych powodów:
Wykonywanie zadań wymagających uprawnień administratora: Wiele zadań w systemie operacyjnym Windows wymaga uprawnień administratora. Do podstawowych należy instalacja i aktualizacja aplikacji, zarządzanie usługami systemowymi, modyfikacja konfiguracji systemu czy chociażby zmiana hasła użytkownika. Wiedza czy dany skrypt należy uruchomić podniesionymi uprawnieniami, czy nie jest w tym wypadku bezcenna.
Uniknięcie błędów i problemów: Próba wykonania zadań wymagających specyficznych uprawnień bez posiadania tych uprawnień zwykle prowadzi do błędów i problemów. W niektórych szczególnych przypadkach wykonanie części skryptu narobi więcej szkód, niż przyniesie pożytku.
Bezpieczeństwo systemu: Sprawdzanie, czy skrypt faktycznie wymaga uprawnień administratora, pomaga zapobiec nadmiernemu nadawaniu uprawnień i potencjalnym atakom.
Zgodność z zasadami bezpieczeństwa: W środowiskach korporacyjnych istnieją zazwyczaj zasady bezpieczeństwa, których zadaniem jest monitorowanie wszystkich działań administratora. Sprawdzenie uprawnień skryptów pomaga zachować zgodność z tymi zasadami.
Jak widzisz sprawdzanie, czy skrypty i polecenia PowerShell są uruchamiane z uprawnieniami administratora to kluczowy krok w dbaniu o bezpieczeństwo, stabilność i skuteczność wykonywanych działań w organizacji. Przejdźmy zatem do kilku prostych metod, które ułatwią to zadanie.
Okno konsoli PowerShell
Pierwszym i najprostszym sposobem jest spojrzenie na okno PowerShella (o ile oczywiście skrypt/polecenie wykonuje się przy w otwartym oknie). W większości przypadków, gdy PowerShell posiada podniesione uprawnienia, na pasku tytułu zobaczysz napis Administrator.
Klasa .NET WindowsIdentity
Ponieważ PowerShell sam w sobie nie posiada konkretnego cmdletu, który rozwiązywałby nasz problem, niedogodność tę należy ominąć stosując specjalną klasę WindowsIdentity. Klasa ta umożliwia wykonanie szeregu różnych inspekcji. Dla nas najistotniejszy jest token zalogowanego konta Windows i sprawdzenie, do jakich grup przypisana jest uruchomiona instacja PowerShell.
W najprostszej formie wygląda to następująco:
PS C:\Users\Admin> [Security.Principal.WindowsIdentity]::GetCurrent().Groups
BinaryLength AccountDomainSid Value
------------ ---------------- -----
12 S-1-1-0
16 S-1-5-32-545
12 S-1-5-4
12 S-1-2-1
12 S-1-5-11
12 S-1-5-15
52 S-1-11-96-3623454863-58364-18864-2661722203-1597581903-1886212171-3126173085-891278134-3015806222-3609238202
12 S-1-5-113
12 S-1-2-0
16 S-1-5-64-36
W wyniku działania otrzymujemy różne wartości, które na pierwszy rzut oka nic nam nie mówią. To są tzw. SIDy (Security Identifier), czyli unikalne identyfikatory bezpieczeństwa przypisane do każdego obiektu w systemie Windows (obiektem może być użytkownik, grupa użytkowników, komputer lub domena). Jest to ciąg liczbowy, który jednoznacznie identyfikuje obiekt w systemie. SID służy do kontroli dostępu i autoryzacji w systemach operacyjnych Windows.
No dobrze, ale co nam to daje? Otóż jeżeli znamy konkretnego SIDa to możemy wykonać coś takiego:
PS C:\Users\Admin> [Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544'
False
Wynik False
oznacza, że dany SID 'S-1-5-32-544
’ nie został odnaleziony.
No ok wszystko fajnie, tylko dalej nie wiadomo, o co chodzi.
Spokojnie już wyjaśniam SID 'S-1-5-32-544'
należy do grupy tzw. Well know SID czyli identyfikatorów dobrze znanych. W tym konkretnym wypadku jest to SID wbudowanej grupy administratorów na komputerze lokalnym. Jeżeli komputer dołączy do domeny to grupa Administratorzy Domeny również stanie się częścią grupy Administratorzy. Kiedy komputer zostanie kontrolerem domeny to grupa Enterprise Administrator również zostanie dodana do grupy Administratorzy.
Reasumując, jeżeli SID 'S-1-5-32-544'
znajdzie się w wykazie grup, które nam się wyświetlą to PowerShell został uruchomiony z uprawnieniami Administratora.
Sprawdźmy to. Teraz ponownie wylistuję grupy tym razem w konsoli z uprawnieniami Administratora:
PS C:\Windows\system32> [Security.Principal.WindowsIdentity]::GetCurrent().Groups
BinaryLength AccountDomainSid Value
------------ ---------------- -----
12 S-1-1-0
12 S-1-5-114
16 S-1-5-32-544
16 S-1-5-32-545
12 S-1-5-4
12 S-1-2-1
12 S-1-5-11
12 S-1-5-15
52 S-1-11-96-3623454863-58364-18864-2661722203-1597581903-1886212171-3126173085-891278134...
12 S-1-5-113
12 S-1-2-0
16 S-1-5-64-36
Jak widzisz pojawiła się nowa grupa z naszym SIDem. Teraz czas na drugie polecenie
PS C:\Windows\system32> [Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544'
True
W wyniku wartość True
, zatem w tym wypadku PowerShell posiada podwyższone uprawnienia.
Nieco innym podejściem może być sprawdzenie konkretnej roli zamiast SIDa:
PS C:\Windows\system32> ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
True
Generalnie całość działania jest bardzo podobna.
Sprawdzenie w skrypcie
Teraz w celu małej automatyzacji zastosuję omówiąną metodę w celu spadzenia z jakimi uprawnieniami został uruchomiony skrypt. Zadanie to można oczywiście wykonać na wiele sposobów, a jednym z nich jest zastosowanie prostej instrukcji warunkowej. Oto jak może to wyglądać:
$principal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
if ($principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "PowerShell został uruchomiony z uprawnieniami administratora."
} else {
Write-Host "PowerShell nie został uruchomiony z uprawnieniami administratora."
}
Przedstawiona metoda umożliwia weryfikację uprawnień, która może być przydatna w złożonych scenariuszach.
Samodzielny skrypt
Może się jednak zdarzyć, że dany skrypt chcąc nie chcąc musi działać z podniesionymi uprawnieniami. W tym wypadku warto zastosować coś takiego:
# Sprawdź czy PowerShell został uruchomiony jako administrator
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
# Uruchom skrypt ponownie jako administrator
Start-Process powershell.exe -NoProfile -ExecutionPolicy Bypass -File '"$PSCommandPath"' -Verb RunAs
# Zakończ bieżącą sesję PowerShell
Exit
}
# Kod skryptu, który zostanie wykonany tylko jeśli PowerShell został uruchomiony z uprawnieniami administratora
Write-Host "Ten skrypt został uruchomiony jako administrator."
Jest to szczególnie przydatne, gdy nie masz otwartej sesji z uprawnieniami administracyjnymi lub gdy chcesz wykonać skrypt na zdalnym komputerze z uprawnieniami administracyjnymi (ewentualnie ludzie, z którymi pracujesz nie wiedzą jakie skrypty jak należyuruchamiać, ale mam nadzieję, że to nie to)
Jak to działa?
W pierwszym kroku sprawdzamy, czy uruchomiona instancja PowerShell posiada podniesione uprawnienia. W tym celu możemy zastosować instrukcję warunkową If z negacją 'if (-not (warunek))’. Jeżeli sprawdzenie zwróci wartość False wykona się instrukcja w nawiasach klamrowych. Dla jasności rozbiję ją na części:
Start-Process powershell.exe – uruchamia nowy proces, w tym wypadku nową instancję PowerShell (powershell.exe świadczy, że będzie do Windows PowerShell)
-No Profile – przy uruchomieniu PowerShella profil użytkownika nie załąduje się. (O profilach będziesz mógł poczytać tu – za jakiś czas).
-ExecutionPolicy Bypass – ominięcie polityki bezpieczeństwa dotyczącej uruchamiania skryptów. (Z tym szczególna ostrożność. Coś więcej o politykach znajdziesz tu – za jakiś czas)
-File '”$PSCommandPath”’ – reprezentuję ścieżkę do pliku (w tym wypadku skryptu), który ma zostać wykonany przez PowerShella.
-Verb RunAs – służy do uruchomienia polecenia lub skryptu z podwyższonymi uprawnieniami administracyjnymi.
Jeżeli wszystko zadziałało pomyślnie to nowo uruchomiona konsola posiada już podniesione uprawnienia.
#Request -RunAsAdministrator
Kolejna metoda to wykorzystanie specjalnej dyrektywy #Request -RunAsAdministrator
. Co prawda możliwość ta dostępna jest od PowerShell w wersji 4.0 jednak wydaje mi się, że obecnie nie stanowi to już żadnej przeszkody. Całość prezentuję się następująco:
#requires -version 4.0
#requires -RunAsAdministrator
Write-Host "PowerShell został uruchomiony jako administrator" -ForegroundColor Green
Dyrektywę umieść na początku skryptu. Więcej na ten temat znajdziesz -> tutaj
Uruchamiamy skrypt i patrzymy co się dzieje. W przypadku braku odpowiednich uprawnień pojawi się błąd i informacja, która podpowie, jak uruchomić PowerShell z uprawnieniami administratora.
W przypadku gdy skrypt uruchomi się z odpowiednimi uprawnieniami w konsoli pojawi się zielony napis.
Dla chętnych
Dodatkowo w ramach małego bonusu dla chętnych pokażę, jak można sprawdzić, które procesy posiadają podwyższone uprawnienia. W tym wypadku pomocny będzie cmdlet Get-Process oraz Add-Member, co ciekawe w tym przypadku nie musisz mieć podniesionych uprawnień.
Get-Process | Add-Member -Name Elevated -MemberType ScriptProperty -Value `
{if ($this.Name -in @('Idle','System')) {$null} `
else {-not $this.Path -and -not $this.Handle} } -PassThru | Where-Object Elevated -eq 'True'
Podsumowanie
Przedstawione wyżej metody pozwolą sprawdzić, czy też zapewnić, że skrypt wykonuję się z odpowiednimi uprawnieniami. Pamiętaj jednak, że nie zawsze jest to konieczne. Stosuj to tylko w uzasadnionych okolicznościach.
Źródła:
https://megamorf.gitlab.io/2020/05/26/check-if-powershell-is-running-as-administrator/
https://petri.com/how-to-check-a-powershell-script-is-running-with-admin-privileges/