Scenariusz:
W skrypcie bash muszę sprawdzić, czy hasło podane przez użytkownika jest prawidłowym hasłem użytkownika.
Przypuszczam, że mam użytkownika A z hasłem PA. W skrypcie poprosiłem użytkownika A o podanie hasła, więc jak sprawdzić, czy wprowadzony ciąg jest naprawdę jego hasłem? ...
expect
at stackoverflow.com/a/1503831/320594 .Odpowiedzi:
Ponieważ chcesz to zrobić w skrypcie powłoki, kilka uwag w Jak sprawdzić hasło w systemie Linux? (na Unix.SE , sugerowany przez AB ) są szczególnie istotne:
/etc/shadow
daje część rozwiązania.mkpasswd
Obecnie poleceń w Debianie i Ubuntu ().Aby ręcznie sprawdzić, czy ciąg znaków jest naprawdę hasłem użytkownika, należy go zaszyfrować przy użyciu tego samego algorytmu skrótu, jak we wpisie cienia użytkownika, z taką samą solą jak we wpisie cienia użytkownika. Następnie można go porównać z hasłem przechowywanym w nim.
Napisałem kompletny, działający skrypt pokazujący, jak to zrobić.
chkpass
, możesz uruchomić, a on przeczyta wiersz ze standardowego wejścia i sprawdzi, czy to hasło.chkpass user
user
mkpasswd
narzędzie, od którego zależy ten skrypt.Uwagi bezpieczeństwa
To może nie być właściwe podejście.
To, czy takie podejście należy uznać za bezpieczne i w inny sposób odpowiednie, zależy od szczegółowych informacji na temat przypadku użycia, którego nie podałeś (od tego momentu).
Nie został poddany audytowi.
Chociaż starałem się zachować ostrożność podczas pisania tego skryptu, nie został on odpowiednio sprawdzony pod kątem luk w zabezpieczeniach . Ma to służyć jako demonstracja i byłoby oprogramowaniem „alfa”, gdyby zostało wydane w ramach projektu. Ponadto...
Inny użytkownik, który „ogląda”, może odkryć sól użytkownika .
Ze względu na ograniczenia w sposobie
mkpasswd
akceptowania danych o soli, ten skrypt zawiera znaną lukę w zabezpieczeniach , którą możesz, lub nie, zaakceptować w zależności od przypadku użycia. Domyślnie użytkownicy Ubuntu i większości innych systemów GNU / Linux mogą przeglądać informacje o procesach uruchamianych przez innych użytkowników (w tym root), w tym argumenty wiersza poleceń. Ani dane wejściowe użytkownika, ani przechowywany skrót hasła nie są przekazywane jako argument wiersza polecenia do żadnego zewnętrznego narzędzia. Ale sól wyodrębniona zshadow
bazy danych jest podawana jako argument wiersza poleceniamkpasswd
, ponieważ jest to jedyny sposób, w jaki narzędzie przyjmuje sól jako dane wejściowe.Gdyby
www-data
) uruchomienia kodu, lub/proc
)jest w stanie sprawdzić argumenty wiersza poleceń
mkpasswd
uruchamiane przez ten skrypt, a następnie uzyskać kopię soli użytkownika zshadow
bazy danych. Być może będą musieli zgadnąć, kiedy to polecenie zostanie uruchomione, ale czasami jest to możliwe.Atakujący twoją solą nie jest tak zły jak atakujący twoją solą i haszem , ale nie jest idealny. Sól nie zapewnia wystarczającej ilości informacji, aby ktoś mógł odkryć twoje hasło. Ale pozwala komuś generować tęczowe tabele lub wstępnie obliczone skróty słownika właściwe dla tego użytkownika w tym systemie. Jest to początkowo bezwartościowe, ale jeśli twoje bezpieczeństwo zostanie później naruszone i zostanie uzyskany pełny skrót, można go później złamać, aby uzyskać hasło użytkownika, zanim będzie on miał szansę go zmienić.
Tak więc ta luka w zabezpieczeniach jest czynnikiem pogarszającym bardziej złożony scenariusz ataku, a nie w pełni podatną na atak luką. I możesz uznać, że powyższa sytuacja jest zbyt daleko posunięta. Ale niechętnie zalecam jakąkolwiek metodę do ogólnego, rzeczywistego użytkowania, która przecieka wszelkie niepubliczne dane
/etc/shadow
do użytkownika innego niż root.Możesz całkowicie uniknąć tego problemu poprzez:
Uważaj, jak wywołać ten skrypt.
Jeśli zezwalasz niezaufanemu użytkownikowi na uruchomienie tego skryptu jako root lub na uruchomienie dowolnego procesu jako root, który wywołuje ten skrypt, bądź ostrożny . Zmieniając środowisko, mogą sprawić, że ten skrypt - lub dowolny skrypt uruchamiany jako root - zrobi wszystko . O ile nie można temu zapobiec, nie wolno zezwalać użytkownikom na podniesienie uprawnień do uruchamiania skryptów powłoki.
Zobacz 10.4. Shell Scripting Languages (pochodne sh i csh) w David A. Wheeler Secure Programming for Linux and Unix HOWTO, aby uzyskać więcej informacji na ten temat. Podczas gdy jego prezentacja koncentruje się na skryptach setuid, inne mechanizmy mogą paść ofiarą tych samych problemów, jeśli nie zdezynfekują środowiska w odpowiedni sposób.
Inne notatki
Obsługuje odczytywanie skrótów tylko z
shadow
bazy danych.Aby skrypt działał, hasła muszą być ukryte (tzn. Ich skróty powinny znajdować się w osobnym
/etc/shadow
pliku, który tylko root może czytać, a nie w nim/etc/passwd
).Tak powinno być zawsze w Ubuntu. W każdym razie, w razie potrzeby, skrypt można w prosty sposób rozszerzyć o odczyt skrótów haseł,
passwd
jak równieżshadow
.Pamiętaj
IFS
o modyfikowaniu tego skryptu.Ustawiłem
IFS=$
na początku, ponieważ trzy dane w polu mieszającym wpisu cienia są oddzielone$
.$
, dlatego typ hash i sól są"${ent[1]}"
i"${ent[2]}"
zamiast"${ent[0]}"
i"${ent[1]}"
, odpowiednio.Jedynymi miejscami w tym skrypcie, w których
$IFS
określa się, jak powłoka dzieli lub łączy słowagdy dane te zostaną podzielone na tablicę, inicjując je z niecytowanego
$(
)
podstawienia polecenia w:gdy tablica jest odtwarzana w ciąg znaków w celu porównania z pełnym polem
shadow
,"${ent[*]}"
wyrażenie w:Jeśli zmodyfikujesz skrypt i sprawisz, że będzie on dzielił słowa (lub łączy słowa) w innych sytuacjach, musisz ustawić
IFS
różne wartości dla różnych poleceń lub różnych części skryptu.Jeśli nie będziesz o tym pamiętać i zakładasz, że
$IFS
ustawiono zwykłą białą spację ($' \t\n'
), możesz spowodować, że skrypt będzie zachowywał się w dziwny sposób.źródło
Możesz nadużyć
sudo
do tego.sudo
ma-l
opcję do testowania uprawnień sudo, które posiada użytkownik, oraz-S
do wczytywania hasła ze standardowego wejścia. Jednak bez względu na poziom uprawnień użytkownika, jeśli zostanie pomyślnie uwierzytelniony,sudo
powraca ze statusem wyjścia 0. Możesz więc przyjąć dowolny inny status wyjścia jako wskazówkę, że uwierzytelnianie nie działa (zakładającsudo
, że sam nie ma żadnych problemów, takich jak błędy uprawnień lub nieprawidłowasudoers
konfiguracja).Coś jak:
Ten skrypt zależy w dużej mierze od
sudoers
konfiguracji. Przyjąłem domyślną konfigurację. Rzeczy, które mogą spowodować awarię:targetpw
lubrunaspw
jest ustawionylistpw
jestnever
Inne problemy to (dzięki Eliah):
/var/log/auth.log
sudo
należy uruchomić jako użytkownik, dla którego się uwierzytelniasz. Chyba że maszsudo
uprawnienia do uruchamianiasudo -u foo sudo -lS
, oznacza to, że będziesz musiał uruchomić skrypt jako użytkownik docelowy.Powodem, dla którego użyłem tutaj dokumentów, jest utrudnienie podsłuchu. Zmienna jest stosowany jako część linii poleceń jest łatwiej ujawnił za pomocą
top
lubps
lub innych narzędzi do kontroli procesów.źródło
sudo
konfiguracjami (jak to mówisz) i bałaganem/var/log/auth.log
z zapisami każdej próby, jest to szybkie, proste i wykorzystuje istniejące narzędzie, zamiast wymyślać koło na nowo (że tak powiem). Proponuję ustawienieIFS=
naread
, aby uniknąć fałszywych sukcesów dla spacją wyściełane wprowadzanych przez użytkownika i nie wyściełane haseł, a także fałszywe awarie dla spacją wyściełane miękkimi wejścia użytkownika i haseł. (Moje rozwiązanie miało podobny błąd.) Możesz także wyjaśnić, jak należy go uruchomić jako użytkownik, którego hasło jest sprawdzane.sudo -l
powoduje, że wpis jest zapisywany za pomocą „COMMAND=list
”. Btw (niepowiązane), chociaż nie jest to obiektywnie lepsze, użycie ciągu tutaj zamiast dokumentu tutaj osiąga ten sam cel bezpieczeństwa i jest bardziej zwarty. Ponieważ skrypt korzysta już z bashism,read -s
a&>
używanieif sudo -lS &>/dev/null <<<"$PASSWD"; then
jest nie mniej przenośne. Nie sugeruję, że powinieneś zmienić to, co masz (w porządku). Raczej wspominam o tym, aby czytelnicy wiedzieli, że mają również tę opcję.sudo -l
coś wyłączyłem - być może raportowanie, gdy użytkownik próbuje uruchomić polecenie, którego nie wolno.Inna metoda (prawdopodobnie bardziej interesująca ze względu na treść teoretyczną niż praktyczne zastosowania).
Hasła użytkownika są przechowywane w
/etc/shadow
.Hasła przechowywane tutaj są szyfrowane, w najnowszych wydaniach Ubuntu za pomocą
SHA-512
.W szczególności, po utworzeniu hasła, hasło w postaci zwykłego tekstu jest solone i szyfrowane
SHA-512
.Jednym z rozwiązań byłoby następnie zaszyfrowanie / zaszyfrowanie podanego hasła i dopasowanie go do hasła zaszyfrowanego użytkownika zapisanego we
/etc/shadow
wpisie danego użytkownika .Aby szybko przedstawić sposób przechowywania haseł w każdym
/etc/shadow
wpisie użytkownika , oto przykładowy/etc/shadow
wpis dla użytkownikafoo
z hasłembar
:foo
: Nazwa Użytkownika6
: typ szyfrowania hasłalWS1oJnmDlaXrx1F
: sól szyfrująca hasłoh4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/
:SHA-512
solone / szyfrowane hasłoAby dopasować podane hasło
bar
dla danego użytkownikafoo
, pierwszą rzeczą do zrobienia jest zdobycie soli:Następnie należy uzyskać pełne solone / zaszyfrowane hasło:
Następnie podane hasło może być solone / szyfrowane i dopasowane do hasła użytkownika solonego / szyfrowanego zapisanego w
/etc/shadow
:Pasują! Wszystko umieszczone w
bash
skrypcie:Wynik:
źródło
sudo getent shadow
>>sudo grep ...
. W przeciwnym razie miło. O tym myślałem pierwotnie, a potem stałem się zbyt leniwy.getent
+grep
+cut
>grep
+cut
getent
mogę cię wyszukać. Pozwoliłem sobie na edycję.mkpasswd
generowałem skrót z danych wprowadzanych przez użytkownika i istniejącej soli (i zawierałem dodatkowe funkcje i diagnostykę), zamiast tego kodowałeś prosty program Python implementującymkpasswd
najważniejszą funkcjonalność i wykorzystałeś to. Zalecam ustawienieIFS=
podczas czytania hasła i cytowanie za${password}
pomocą"
, aby próby podania hasła za pomocą białych znaków nie spowodowały uszkodzenia skryptu.