Skocz do zawartości

zetLogin [1.20.4]


Rekomendowane odpowiedzi

Witajcie!

Chciałbym Wam przedstawić zaawansowany skrypt na system logowania.

Wiem, że tego typu skryptów jest dużo, jednak większość jest zwykłą maszynką do kradzieży haseł.

Zawiera on doszczętne szyfrowanie haseł i nie wyświetlanie ich w konsoli.

Oto, jak działa:

/register <hasło> - Rejestruje gracza, tworząc nowy plik YML z jego hasłem. Hasło ma dodatkowy ciąg znaków "xyz01" a następnie jest hashowane poprzez SHA-256.

/login <hasło> - Loguje gracza, sprawdzając czy argument 1 z dodatkowym ciągiem znaków + zaszyfrowany = wartość w pliku YML. Jeśli tak, hasło jest poprawne. W przeciwnym razie nie jest. Po 3 niepoprawnie wprowadzonych hasłach gracz jest kickowany z serwera. Za czwartym to samo, a za piątym jest tymczasowo banowany. (Domyślnie 10 minut)

/changepassword <stare hasło> <nowe hasło> - Nadpisuje wartość ,,Password" w YMLu nowym zaszyfrowanym hasłem.

/forgotpassword - Daje wiadomość z kontaktem do właściciela, jeśli gracz zapomniał hasła.

================================================================

/unregister <gracz> - Wyrejestrowuje gracza, usuwając jego plik YML. (Tylko dla administracji)

/hashedpassword <gracz> - Pokazuje zahashowane hasło gracza. (Tylko dla administracji)

================================================================

Download:

v1.0 - *kliknij*

Jeśli zauważyliście jakieś błędy, lub chcecie coś zmienić/dodać, możecie o tym napisać.

Z góry dzięki!

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/
Udostępnij na innych stronach

@TeZetYT

Kod jest schludnie napisany, choć zauważyłem dwa podobne fragmenty, które skłaniają do rozważenia stworzenia dla nich funkcji. Mowa o podobieństwie w warunkach komend /register i /changepassword sprawdzających spełnienie wymagań ustawianego hasła.

Skoro skrypt operuje na plikach .yml, co nie jest możliwe w samym Skript'cie. Warto byłoby wspomnieć o tym jakie dodatki są wymagane.

Co do samej logiki skryptu, mam kilka uwag i pytań.

  1. Sekcja konfiguracyjna jest spora i pozwala na dostosowanie niemalże każdej wiadomości, to się ceni. Nie rozumiem jednak dlaczego wszystkie wymogi stawiane ustawiane hasłom, ilość prób, itd. są literałami, a nie stałymi w sekcji 'options'. Taki zabieg upiększyłby kod i również ułatwiłby jego rozwój w przyszłości. Jeśli martwisz się możliwością nieumyślnej ich zmiany przez osoby pobierające ten skrypt, nic nie stoi na przeszkodzie aby stworzyć na samym końcu kodu kolejną sekcję 'options' przeznaczoną tylko dla tych stałych, których wartości nie powinno się modyfikować.
  2. Dlaczego skrypt zapisuje dane logowania graczy w indywidualnych plikach .yml? Jaką to ma przewagę nad zapisem w zmiennych globalnych w Skript? Zakładam, że te wartości YAML nie są cache'owane w pamięci RAM, więc skrypt przy każdym pobieraniu wartości musi otworzyć plik (co jest wymagającą operacją w porównaniu do odczytu jednej wartości) aby wyjąć z niego jedną wartość i odrzucić resztę. Jak widać, nie jest to szczególnie wydajne podejście. Jeśli faktycznie chcemy korzystać z plików .yml nie ważne co, warto się pochylić nad dodatkiem skript-yaml, który pozwala na poprawną obsługę plików - to znaczy ładowanie ich do pamięci RAM i dalsze operowanie na nich w tej pamięci.
  3. Zauważyłem w kilku miejscach poniższą linijkę i zastanawiam się czy ona rzeczywiście działa:
    set yaml value "log" from file "spigot.yml" to false

    Wiem jakie jest jej zadanie - wyłączenie loggingu komend w konsoli i plikach .log serwera, co definitywnie zwiększa bezpieczeństwo haseł użytkowników. Niemniej jednak, w pliku spigot.yml ten węzeł nazywa się 'commands.log', więc podejrzewam, że może to nie działać. Co więcej, wątpię czy serwer na bieżąco śledzi zmiany w pliku spigot.yml, nie wiem czy skrypt był pod tym kątem testowany. Jedyne znane mi metody przeładowania pliku konfiguracyjnego Spigota to restart serwera (oczywiście jest to najlepsza metoda) lub użycie komendy /spigot reload.
    Tak jeszcze dodam, że jeśli ta linijka rzeczywiście działa, warto byłoby ustawiać przy wyłączeniu skryptu jej wartość na true, nie na false. Ponadto, przy loggingu komend myślę, że lepiej będzie usunąć prefix, jest to zbędne.

  4. W wiadomościach w sekcji konfiguracyjnej czytelniejsze byłoby użycie placeholderów takich jak {player}, {admin}, {hashedPassword}. {0} czy {1} niewiele mówią i wymuszają na użytkowniku szukanie ich znaczenia w kodzie skryptu.

  5. Z kryptologicznego punktu widzenia, dodawanie ciągu znaków "xyz01" przed hashowaniem hasła (nie szyfrowaniem!, to są dwie różne rzeczy, bo wszystko można odszyfrować przy znajomości szyfru; hashowanie jest operacją jednokierunkową) nie przyczynia się do zwiększenia bezpieczeństwa haseł. Jedyne z czym mi się to kojarzy to próbą implementacji dodawania soli do haseł. Sól jednak powinna być losowym ciągiem znaków, indywidualnym dla każdego gracza, najlepiej o długości takiej jak ilość bitów hashów danego algorytmu.
    W przypadku SHA-256 jest to rzecz jasna 256 bitów, czyli 32 bajty. Przy zapisie w systemie szesnastkowym, każdy bajt jest reprezentowany przez dwa znaki (256 dostępnych znaków to 16 * 16 - dwa znaki), więc z SHA-256 otrzymujemy ciągi znaków o długości 64.
    Warto dodawać sól do haseł przy hashowaniu, ale niestety, bez zewnętrznej biblioteki nie jest to możliwe, ponieważ skript-reflect ma bug niepozwalający na poprawne korzystanie z klasy SecureRandom. Dlatego nie przejmowałbym się tym, chciałem tylko naprostować parę spraw, wyprowadzić z błędu.

EDIT: W ramach lektury polecam ten artykuł opisujący sposoby poprawnego użycia algorytmów hashowania.

Pozdrawiam.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346010
Udostępnij na innych stronach

1 godzinę temu, Kormic napisał:

@TeZetYT

Kod jest schludnie napisany, choć zauważyłem dwa podobne fragmenty, które skłaniają do rozważenia stworzenia dla nich funkcji. Mowa o podobieństwie w warunkach komend /register i /changepassword sprawdzających spełnienie wymagań ustawianego hasła.

Skoro skrypt operuje na plikach .yml, co nie jest możliwe w samym Skript'cie. Warto byłoby wspomnieć o tym jakie dodatki są wymagane.

Co do samej logiki skryptu, mam kilka uwag i pytań.

  1. Sekcja konfiguracyjna jest spora i pozwala na dostosowanie niemalże każdej wiadomości, to się ceni. Nie rozumiem jednak dlaczego wszystkie wymogi stawiane ustawiane hasłom, ilość prób, itd. są literałami, a nie stałymi w sekcji 'options'. Taki zabieg upiększyłby kod i również ułatwiłby jego rozwój w przyszłości. Jeśli martwisz się możliwością nieumyślnej ich zmiany przez osoby pobierające ten skrypt, nic nie stoi na przeszkodzie aby stworzyć na samym końcu kodu kolejną sekcję 'options' przeznaczoną tylko dla tych stałych, których wartości nie powinno się modyfikować.
  2. Dlaczego skrypt zapisuje dane logowania graczy w indywidualnych plikach .yml? Jaką to ma przewagę nad zapisem w zmiennych globalnych w Skript? Zakładam, że te wartości YAML nie są cache'owane w pamięci RAM, więc skrypt przy każdym pobieraniu wartości musi otworzyć plik (co jest wymagającą operacją w porównaniu do odczytu jednej wartości) aby wyjąć z niego jedną wartość i odrzucić resztę. Jak widać, nie jest to szczególnie wydajne podejście. Jeśli faktycznie chcemy korzystać z plików .yml nie ważne co, warto się pochylić nad dodatkiem skript-yaml, który pozwala na poprawną obsługę plików - to znaczy ładowanie ich do pamięci RAM i dalsze operowanie na nich w tej pamięci.
  3. Zauważyłem w kilku miejscach poniższą linijkę i zastanawiam się czy ona rzeczywiście działa:
    set yaml value "log" from file "spigot.yml" to false

    Wiem jakie jest jej zadanie - wyłączenie loggingu komend w konsoli i plikach .log serwera, co definitywnie zwiększa bezpieczeństwo haseł użytkowników. Niemniej jednak, w pliku spigot.yml ten węzeł nazywa się 'commands.log', więc podejrzewam, że może to nie działać. Co więcej, wątpię czy serwer na bieżąco śledzi zmiany w pliku spigot.yml, nie wiem czy skrypt był pod tym kątem testowany. Jedyne znane mi metody przeładowania pliku konfiguracyjnego Spigota to restart serwera (oczywiście jest to najlepsza metoda) lub użycie komendy /spigot reload.
    Tak jeszcze dodam, że jeśli ta linijka rzeczywiście działa, warto byłoby ustawiać przy wyłączeniu skryptu jej wartość na true, nie na false. Ponadto, przy loggingu komend myślę, że lepiej będzie usunąć prefix, jest to zbędne.

  4. W wiadomościach w sekcji konfiguracyjnej czytelniejsze byłoby użycie placeholderów takich jak {player}, {admin}, {hashedPassword}. {0} czy {1} niewiele mówią i wymuszają na użytkowniku szukanie ich znaczenia w kodzie skryptu.

  5. Z kryptologicznego punktu widzenia, dodawanie ciągu znaków "xyz01" przed hashowaniem hasła (nie szyfrowaniem!, to są dwie różne rzeczy, bo wszystko można odszyfrować przy znajomości szyfru; hashowanie jest operacją jednokierunkową) nie przyczynia się do zwiększenia bezpieczeństwa haseł. Jedyne z czym mi się to kojarzy to próbą implementacji dodawania soli do haseł. Sól jednak powinna być losowym ciągiem znaków, indywidualnym dla każdego gracza, najlepiej o długości takiej jak ilość bitów hashów danego algorytmu.
    W przypadku SHA-256 jest to rzecz jasna 256 bitów, czyli 32 bajty. Przy zapisie w systemie szesnastkowym, każdy bajt jest reprezentowany przez dwa znaki (256 dostępnych znaków to 16 * 16 - dwa znaki), więc z SHA-256 otrzymujemy ciągi znaków o długości 64.
    Warto dodawać sól do haseł przy hashowaniu, ale niestety, bez zewnętrznej biblioteki nie jest to możliwe, ponieważ skript-reflect ma bug nie pozwalający na poprawne korzystanie z klasy SecureRandom. Dlatego nie przejmowałbym się tym, chciałem tylko naprostować parę spraw, wyprowadzić z błędu.

EDIT: W ramach lektury polecam ten artykuł opisujący sposoby poprawnego użycia algorytmów hashowania.

Pozdrawiam.

Dziękuję za opinie.

1. Ma Pan rację, dodam taką możliwość.

2. Wolę zapisywać hasła w pliku a nie w zmiennej z uwagi na to, że u mnie czasem tak się zdarzało że zmienne zostały po prostu wyczyszczone przy restarcie serwera. Trzymanie ich we WŁASNYM pliku jest najbezpieczniejszą opcją w mojej opinii.

3. Faktycznie nie testowałem tego i zapomniałem, że trzeba przeładowywać, a z tego co mi wiadomo komenda /spigot reload jest podobna do zwykłego reloada więc chyba jednak bez sensu to będzie troche, natomiast u mnie nie ma command.log tylko po prostu log, dlatego tak dałem również tu.

4. Racja, może zmienię, natomiast użytkownik raczej z łatwością by się odnalazł. Dlaczego? Ponieważ jeśli mamy np. ,,Odrejestrowano gracza {0}" to wiadomo, że chodzi o gracza.

5. Ta sól była ewentualnie po to, żeby w przypadku włamania do bazy danych z zaszyfrowanymi hasłami haker nie mógł odgadnąć tak łatwo hasła, jeśli np. wiedziałby że hasło LUBIEPLACKI1234! to jest np. csf792yfsa23erd21.....1weqfdr3fds to wtedy hash wyglądałby inaczej z tym xyz01 więc chciałem żeby tak to działało.

Nie wiem ja dopiero niedawno zacząłem się interesować jak działa to szyfrowanie i ogólnie cyberbezpieczeństwem więc jeśli coś źle mówię to przepraszam ale to mój pierwszy taki skrypt związany z tym (to znaczy jak jeszcze byłem niedoświadczony to zapisywałem hasła plaintextem ale już nie wnikajmy w to XD) Ale mam nadzieje że jak na pierwszy taki to nie jest źle. Pozdrawiam. 

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346011
Udostępnij na innych stronach

@TeZetYT

2. Hmm... dziwne. Trochę czasu już pracuję w Skript'cie i miałem okazję rozmawiać z wieloma osobami również korzystającymi z niego. Nigdy jednak nie słyszałem o tym, aby komuś zmienne znikały bez powodu. Mnie to wygląda na jakiś błąd w kodzie lub problem z konfiguracją serwera. Zalecam przejść na zwykłe zmienne, dzięki temu kod będzie wydajniejszy, a też nie będą potrzebne żadne dodatki do poprawnego działania skryptu.

3. W wersji 1.20.4 (wnioskuję po tytule, że jej użyłeś do testów) opcja 'log' była częścią węzła 'commands'. Tak samo jest w wersji 1.21.4.

commands:
  tab-complete: 0
  send-namespaced: true
  silent-commandblock-console: false
  log: false
  spam-exclusions:
  - /skill
  replace-commands:
  - setblock
  - summon
  - testforblock
  - tellraw

Odniesienie się do samego klucza "log" nic nie da, wyrażenie niczego nie zwróci. Należy odnieść się do "commands.log".

4. Warto to zmienić, bo placeholdery powinny samą swoją nazwą tłumaczyć do czego służą, niezależnie od tego czy kontekst ma sens logiczny, czy nie.

5. Każdy kiedyś zaczynał naukę, doskonale to rozumiem.
Co do użycia tej samej soli dla każdego gracza, należy zwrócić na to uwagę, że jeśli mówimy o zapewnieniu bezpieczeństwa haseł, które jest ostatnią linią obrony, osoba włamująca się na pewno już będzie miała dostęp do skryptu i zauważy, że do wszystkich haseł przed hashowaniem należy dodać ciąg znaków "xyz01". To samo tyczy się jednorazowego wygenerowania soli i używania jej dla wszystkich, ponieważ też trzeba będzie gdzieś ją zapisać, a więc można już uznać w tej sytuacji sól za nietajną i tym samym całkowicie nieefektywną. Właśnie z tego powodu sól powinna być losowa dla każdego gracza. Tylko wtedy ona ma sens, bo gwarantuje unikalny hash dla każdego hasła (nawet jeśli wielu użytkowników używa tego samego; te same hasło u różnych użytkowników ze stałą solą nadal po przepuszczeniu przez algorytm daje ten sam hash), co zapobiega chociażby atakom słownikowym.

Pozdrawiam.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346012
Udostępnij na innych stronach

W dniu 4.02.2025 o 17:30, TeZetYT napisał:

 

2. Wolę zapisywać hasła w pliku a nie w zmiennej z uwagi na to, że u mnie czasem tak się zdarzało że zmienne zostały po prostu wyczyszczone przy restarcie serwera. Trzymanie ich we WŁASNYM pliku jest najbezpieczniejszą opcją w mojej opinii.

Co do punktu drugiego Twojej wypowiedzi, to obstawiam, że robisz skrypty na serwerze lokalnym (localhost), i zamiast zatrzymywać serwer komendą /stop, zatrzymujesz go "z buta" co prowadzi do niepoprawnego zapisu danych.

Pozdrawiam.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346044
Udostępnij na innych stronach

W dniu 4.02.2025 o 17:30, TeZetYT napisał:

2. Wolę zapisywać hasła w pliku a nie w zmiennej z uwagi na to, że u mnie czasem tak się zdarzało że zmienne zostały po prostu wyczyszczone przy restarcie serwera. Trzymanie ich we WŁASNYM pliku jest najbezpieczniejszą opcją w mojej opinii.

Trzymanie takich rzeczy w plikach już samo w sobie nie jest bezpieczne.

Po drugie, dla każdego gracza jest osobny plik.

Serwer będzie się ładować bardzo długo w sytuacji gdy będzie dużo plików graczy.

 

Po drugie zapis odbywa się dla nicku, nie dla uuid. Gracz premium po zmianie nicku musi tworzyć konto na nowo.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346047
Udostępnij na innych stronach

@Hiri12

Słuszna uwaga, ale tutaj była mowa o wyczyszczaniu wszystkich zmiennych, więc zachodziła utrata już zapisanych na dysku zmiennych. Wyłączenie serwera poprzez zwolnienie zasobów (dla niewtajemniczonych, przycisk z symbolem "x") w Skript poskutkuje utratą co najwyżej 999 zmian, ponieważ rozmiar kolejki operacji na zmiennych wynosi 1000 może poskutkować utratą nieograniczonej ilości buforowanych operacji zapisu zmiennych, ponieważ, owszem, rozmiar kolejki wynosi 1000, ale trzeba również pamiętać o tym, że opróżnianie jej odbywa się co 5 minut.

@kerpson

Odpowiadając na uwagę do bezpieczeństwa, racja. Dość dziwnym będzie chociażby tworzenie backupów w sytuacji, gdzie każdy gracz ma wydzielony dla siebie plik.

Co do czasu uruchamiania serwera, on się nie zmieni w jakkolwiek zauważalnym stopniu, ponieważ te pliki z danymi nie są w ogóle ładowane do pamięci.

Jeszcze odnosząc się do zapisu dla nazwy gracza, w przypadku serwera w trybie offline (a zakładam, że właśnie z takim mamy do czynienia) nie ma to absolutnie żadnego znaczenia. Warto jednak zauważyć, że gdyby dwóch graczy zamieniło się nazwami, mogą de facto wymienić się całym postępem na serwerze, co jest niewątpliwie największym zagrożeniem tego trybu pracy.

Pozdrawiam.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346050
Udostępnij na innych stronach

6 godzin temu, Hiri12 napisał:

Co do punktu drugiego Twojej wypowiedzi, to obstawiam, że robisz skrypty na serwerze lokalnym (localhost), i zamiast zatrzymywać serwer komendą /stop, zatrzymujesz go "z buta" co prowadzi do niepoprawnego zapisu danych.

Pozdrawiam.

zatrzymuję serwer komendą stop zawsze. dawno kiedy jeszcze nie wiedziałem o istnieniu skripta to faktycznie wyłączałem serwer za pomocą X'a, ale zacząłem komendą /stop jeszcze przed poznaniem skripta, głównie dlatego że postęp się nie zapisywał

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346055
Udostępnij na innych stronach

5 godzin temu, kerpson napisał:

Trzymanie takich rzeczy w plikach już samo w sobie nie jest bezpieczne.

Po drugie, dla każdego gracza jest osobny plik.

Serwer będzie się ładować bardzo długo w sytuacji gdy będzie dużo plików graczy.

 

Po drugie zapis odbywa się dla nicku, nie dla uuid. Gracz premium po zmianie nicku musi tworzyć konto na nowo.

1. Ufam, ale mógłbyś powiedzieć dlaczego?

2. Faktycznie, można w jednym zrobić. Zmienię to w następnej aktualizacji.

 

3. Też słuszna uwaga, zmienię na UUID.

Odnośnik do komentarza
https://skript.pl/temat/58466-zetlogin-1204/#findComment-346056
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Nieaktywny
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...