Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: logowanie nie do złamania ;-)
Forum PHP.pl > Forum > PHP
michalkkk
Witam. Ostatanio zastanawiam sie nad stworzeniem bezpiecznego formularza logowania(bez wykorzystania ssl poniewaz trzeba kupowac certyfikaty aby nie pojawiały sie ostrzeżenia przegladarek). Pomimo tytułu uważam że skrypt jest do zlamania(tak myśle, nie próbowałem), ale chciałem poznać Wasze rady, wskazówki. Może z Waszą pomocą uda mi(nam) się napisać w miarę bezpieczny formularz logowania-taki szablon ktory bedzie kazdy mogl zastosowac u siebie. Starałem się wykorzystac Wasze wskazówki, które pisaliście w innych postach. Wykorzystałem chyba troche rzadko stosowana metode z szyfrowaniem(md5-http://pajhome.org.uk/crypt/md5) niektorych przesyłanych danych w javascript po stronie klienta. Cały czas myśle co by mozna jeszcze udoskonalić, także licze na Waszą pomoc. Z góry dzięki.

Chce jak najbardziej utrudnić możliwość zalogowania przez podsłuchanie danych(brak ssl), dlatego szyfruje ip,referer,idsesji. Moze np. odczytac za pomoca JavaScript(aby nie przesyłać danych z serwera do klienta) wersje przegladarki, zaszyfrowac md5(w js) a potem odczytac za pomoca php(ale chyba przy odczycie wersji przez php tez jest przesyłana informacja) i porównac. Nie znam sie za bardzo na tym, ale czy mozna zasymulowac lub podstawić id sesji aby oszukac skrypt? Ip,referer chyba tak.

Sciezka do pliku powinna byc taka jak wpisana w poniższym pliku(oczywiscie trzeba wpisac wlasny adres)-http://jakasstrona.pl/log.php

  1. <?
  2. $ip=gethostbyaddr(getenv (&#092;"REMOTE_ADDR\"));
  3. $ref=$_SERVER['HTTP_REFERER'];
  4. $ua=$_SERVER['HTTP_USER_AGENT'];
  5.  
  6. $zak_ip=md5($ip);
  7. $zak_ref=md5($ref);
  8. $zak_ua=md5($ua);
  9.  
  10. session_register(&#092;"ses_losowa\");
  11. session_register(&#092;"nie_zmieniaj_losowej\");
  12.  
  13.  
  14. if ($_SESSION['nie_zmieniaj_losowej']!='tak')
  15. {
  16. $losowa=mt_rand(); //losuje kilkucyfrowa liczbe
  17. $_SESSION['ses_losowa']=$losowa;
  18. }
  19.  
  20. $_SESSION['nie_zmieniaj_losowej']='tak';
  21.  
  22.  
  23. //po kliknieciu w przycisk Loguj nastepuje
  24. //wywolanie funkcji w javascript md5 - po stronie uzytkownika,
  25. //która zestepuje wpisane przez uzytkownika haslo w zakodowany md5 ciag znaków
  26. //do hasla przed zakodowaniem w javascript dodawane sa dodatkowe zmienne
  27. //i to wszystko razem jest kodowane md5(w javascript) i wysylane do serwera
  28. //niezaszyfrowane haslo nie jest wysyłane
  29.  
  30. ?>
  31. <script src=\"md5.js\" type=\"text/javascript\"></script>
  32.  
  33. <FORM METHOD=POST>
  34. Login: <input type=\"text\" name=\"login\" value=\"\">
  35. Haslo: <input type=\"text\" name=\"_haslo\" value=\"\">
  36. <input type=\"hidden\" name=\"se\" value=\"<?echo session_id();?>\">
  37. <input type=\"hidden\" name=\"haslo\" value=\"\">
  38. <input type=\"submit\" value=\"LOGUJ\" onclick=\"haslo.value = hex_md5(_haslo.value+'<?echo $zak_ip.$zak_ref.$_SESSION['ses_losowa'].$zak_ua?>'); _haslo.value = ''\">
  39. </FORM>
  40.  
  41. <?
  42. //////poprawny login i haslo(normalnie bedzie odczytywane z bazy danych)
  43. $poprawny_login='michal';
  44. $poprawne_haslo='test123';
  45. //////poprawny login i haslo(normalnie bedzie odczytywane z bazy danych)
  46.  
  47. /////sprawdzanie czy poprawne dane
  48. if ($_POST['login'] || $_POST['haslo'])
  49. {
  50. $kod_poprawny=md5($poprawne_haslo.md5($ip).md5($ref).$_SESSION['ses_losowa'].md5($ua));
  51.  
  52.  
  53.  if ($_POST['haslo']==$kod_poprawny && $_SERVER[&#092;"HTTP_REFERER\"]=='http://jakasstrona.pl/log.php' && $_POST['se']==session_id())
  54.  {
  55.  echo 'Zostales zalogowany!';
  56.  }
  57.  else
  58.  {
  59.  echo 'Niepoprawne dane';
  60.  exit;
  61.  }
  62. }
  63. /////sprawdzanie czy poprawne dane
  64. ?>
Speedy
Wg mnie hasła, niezależnie od tego czy znajdują się w bazie , czy też w samym skrypcie powinny być również zaszyfrowane, ponieważ taka chyba jest idea algorytmów szyfrujących winksmiley.jpg . Jeśli potencjalny włamywacz dostałby się jakoś do bazy , to zaszyfrowane hasła są kolejnym problemem dla niego smile.gif .
Skrypt powinien szyfrować wpisane dane , a następnie sprawdzać , czy zgadzają się one z podanym ciągiem znaków, który już będzie podany w postaci zaszyfrowanej. Nie powinno się podawać nigdzie niezaszyfrowanej wersji hasła.

Czyli zamiast np. :

  1. <?php
  2.  
  3. $poprawny_login='michal';
  4. $poprawne_haslo='test123';
  5. $podany_login='$login';
  6. $podane_haslo='$haslo';
  7.  
  8. $podany_login_hash=md5($login);
  9. $podane_haslo_hash=md5($haslo);
  10.  
  11. $poprawny_login_hash=md5($poprawny_login);
  12. $poprawne_haslo_hash=md5($poprawne_haslo);
  13.  
  14. if ($poprawny_login_hash==$podany_login_hash) {
  15. if ($poprawne_haslo_hash==$podane_haslo_hash) {
  16.  
  17. print 'poprawne dane';
  18.  }
  19. } else {
  20. print 'niepoprawne dane';
  21. }
  22.  
  23. ?>


Powinno być mniej więcej coś takiego :

  1. <?php
  2.  
  3. $poprawny_login='06b2af75179fb94be097af182a442a4a';
  4. $poprawne_haslo='cc03e747a6afbbcbf8be7668acfebee5';
  5. $podany_login='$login';
  6. $podane_haslo='$haslo';
  7.  
  8. $podany_login_hash=md5($login);
  9. $podane_haslo_hash=md5($haslo);
  10.  
  11. if ($poprawny_login==$podany_login_hash) {
  12. if ($poprawne_haslo==$podane_haslo_hash) {
  13.  
  14. print 'poprawne dane';
  15.  }
  16. } else {
  17. print 'niepoprawne dane';
  18. }
  19.  
  20. ?>



Napisałem to tak "na oko" , ale mam nadzieję, że uchwycisz ideę winksmiley.jpg .
PS.

06b2af75179fb94be097af182a442a4a == md5(michal);
cc03e747a6afbbcbf8be7668acfebee5 == md5(test123);

Pozdrawiam smile.gif .
bregovic
Generalnie haszowanie hasła przed wysłaniem go dna serwer to bardzo dobry pomysł. Jedyny problem pojawia sie jesli user ma wylaczony javascript (a tacy sa).
Zresztą wystarczy odpalić jakikolwiek sniffer w sieci lokalnej aby wyłąpać masę haseł.
Kiedyś myślałem nad takim bezpiecznym formularzem - trzeba w nim przekazać jak najwięcej danych o użytkowniku, więc patrzymy sobie w phpinfo" title="Zobacz w manualu PHP" target="_manual i wyciągamy jak największą ilość ciekawych żeczy:
  1. <?php
  2. $_SERVER[&#092;"HTTP_USER_AGENT\"];
  3. $_SERVER[&#092;"HTTP_ACCEPT_LANGUAGE\"];
  4. $_SERVER[&#092;"HTTP_ACCEPT_CHARSET\"];
  5. ?>

Za to nie radzę używać HTTP_REFERER - nie jest przecierz powiedziane że user nie wszedł bezpośrednio na strone...

No i powinieeś jednak użyć sha1" title="Zobacz w manualu PHP" target="_manual - jest bezpieczniejszy, i można goteż sciągnąć dla javascriptu - z podanej przez ciebie strony.

Dobrym pomysłem, imo, jest też sprawdzanie tych wartości za każdym startem sesji.
Speedy
Wystarczy nieco przerobić ten skrypt i można w ogóle wyzbyć się w nim javascript'u . Sprawdzanie poprawności hasła można dokonać za pomocą funkcji dostępnych w php smile.gif .

http://pl2.php.net/manual/pl/function.md5.php

http://pl2.php.net/manual/pl/function.sha1.php

Można jeszcze skorzystać z autoryzacji dostępnej w php .

Przy okazji polecam lekturę :

http://www.maciaszek.pl/phpcon/download/autoryzacja.pdf

Pozdrawiam .

guitar.gif
dooshek
Cytat(bregovic @ 2004-12-11 18:09:28)
Generalnie haszowanie hasła przed wysłaniem go dna serwer to bardzo dobry pomysł. Jedyny problem pojawia sie jesli user ma wylaczony javascript (a tacy sa).
Zresztą wystarczy odpalić jakikolwiek sniffer w sieci lokalnej aby wyłąpać masę haseł.
Kiedyś myślałem nad takim bezpiecznym formularzem - trzeba w nim przekazać jak najwięcej danych o użytkowniku, więc patrzymy sobie w phpinfo" target="_blank - jest bezpieczniejszy, i można goteż sciągnąć dla javascriptu - z podanej przez ciebie strony.

Dobrym pomysłem, imo, jest też sprawdzanie tych wartości za każdym startem sesji.

No generalnie panowie bardzo fajnie tylko co jesli ktos przechwyci ten md5 (za pomoca sniffera zaden problem) i po prostu wysle do serwera ten MD5 ktory podal uzytkownik? Wtedy nie musi znac nazwy uzytkownika ani hasla - przesyla do serwera te md5tki, sha1cze czy co tam jeszcze i i tak sie np. zaloguje...
Speedy
Cytat(dooshek @ 2004-12-11 17:52:40)
Cytat(bregovic @ 2004-12-11 18:09:28)
Generalnie haszowanie hasła przed wysłaniem go dna serwer to bardzo dobry pomysł. Jedyny problem pojawia sie jesli user ma wylaczony javascript (a tacy sa).
Zresztą wystarczy odpalić jakikolwiek sniffer w sieci lokalnej aby wyłąpać masę haseł.
Kiedyś myślałem nad takim bezpiecznym formularzem - trzeba w nim przekazać jak najwięcej danych o użytkowniku, więc patrzymy sobie w phpinfo" target="_blank - jest bezpieczniejszy, i można goteż sciągnąć dla javascriptu - z podanej przez ciebie strony.

Dobrym pomysłem, imo, jest też sprawdzanie tych wartości za każdym startem sesji.

No generalnie panowie bardzo fajnie tylko co jesli ktos przechwyci ten md5 (za pomoca sniffera zaden problem) i po prostu wysle do serwera ten MD5 ktory podal uzytkownik? Wtedy nie musi znac nazwy uzytkownika ani hasla - przesyla do serwera te md5tki, sha1cze czy co tam jeszcze i i tak sie np. zaloguje...

W moim pomyśle ta opcja odpada ponieważ podajesz skryptowi jakąś frazę, a on ją szyfruje i sprawdza czy zgadza się z zaszyfrowanym wcześniej ciągiem , który jest w jakiejś bazie. md5 da się rozszyfrować, ale ciężko, więc sam zaszyfrowany ciąg takiemu "hackerowi" na niewiele się zda. Jeśli podasz skryptowi ciąg zaszyfrowany, to on go zaszyfruje i sprawdzi , czy "podwójnie zaszyfrowane" hasło zgadza się prawidłowym hashem. Oczywiście nie będzie się zgadzać smile.gif . Problem pojawia się jeżeli zostanie przechwycone niezaszyfrowane hasło. Ale i tak sprawa sniffer'ów dotyczy tylko sieci i tą sprawę należy rozpatrywać inaczej. Jeśli ktoś łączy się z internetem w inny sposób - problem znika smile.gif .
bregovic
Szyfrowanie po stronie przeglądarki jest potrzebne - żeby zaciemnić hasło i dane które razem z nim wysyłamy jako klucz. Wysyłamy zahaszowane wartości jak najbliższe pełnoprawnemu userowi, jak HTTP_USER_AGENT. Dodatkowo w jakimś polu hidden wysyłamy randomową liczbę oznaczającą jakiś string na serwerze (np id pola w tabeli mysql) który doklejamy do hasza - to jesteśmy w domu.

Czyli konkludując wracamy do tego co michalkkk napisał w swoim pierwszym poście.

--- EDIT ---

Speedy, próbowałe kiedykolwiek włączyć jakikolwiek sniffer w sieci lokalnej? To na prawde powiększa perspektywę znaczenia słowa 'bezpieczeństwo'...
michalkkk
Dziekuje za Wasze wskazówki, jeszcze troche postaram sie udoskonalić skrypt. Oczywiście umieszcze go tutaj. Pozdrawiam, Michal
hawk
Tak sobie czytam i zastanawiam się, co rozumiecie przez "bezpieczne logowanie". Bo ja w sumie nie wiem, a bezpieczeństwo nie polega wcale na jednym formularzu logowania.

Nie wiem, czy to jest do złamania, czy nie, ale to nieistotne. Po co się męczyć? Posiadacz snifferka poczeka, aż się zalogujesz, potem wyśle ci pakiet zamykający połączenie TCP, a do serwera wyśle co mu się żywnie podoba. Koniec.

SSL nie wymyślili tylko dlatego, że nie lubili javascriptu.
Imperior
@hawk:
No cóż... tutaj jest przedstawiony sposób na bezpieczeństwo logowania, co jest najłatwiej zrobić, a bezpieczeństwo sesji to już jest inna para kaloszy i wyższa szkoła jazdy (bez SSL oczywiście).
Jabol
A pozatym co za problem, jeżeli przechwyce hasło zahaszowane w md5? Po prostu zrobie małą zmianę np. w kopii lokalnej formularza z serwera i podam zamiast hasła wersję już zahaszowaną.
Tzn. wpiszę w pole hasło już zahaszowaną wersję hasła i zrobię taki bajerek, że js już nie będzie tego chciał znowu haszować.
Jeżeli jeszcze napiszę sobie programik, który będzie wysyłał dowolne nagłówki do serwera to już system logowania można uznać za złamany.
A jeżeli już chcecie czarną wizję:
hawk, co Ci da ssl, jeżeli zatruje ARP, zamiast do serwera podłączysz się do mnie, u mnie wszystkie dane będą odszyfrowane, odczytane i przekierowane do serwera docelowego. Ale ja będę znał całą tranzakcję.
No, chyba, że już się bawimy w SSL na poważnie, czyli z certyfikatami po obu stronach i takie tam. Wtedy zaczyna być bezpiecznie.
hawk
@Imperior: bezpieczeństwo logowania samo w sobie jest kompletnie bez znaczenia. Liczy się bezpieczeństwo aplikacji. Nie warto inwestować w poprawę bezpieczeństwa w jednym miejscu, gdy obok mamy poważną dziurę. Trzeba pamiętać, czemu skrypt logowania ma służyć.

@Jabol: mówisz o typowym man-in-the-middle dla SSL? Wtedy potrzebny jest jakiś legalny certyfikat, żeby klient łączył się z tobą przez SSL. Trochę pomaga dziura w MSIE... czy podany przez ciebie ARP spoofing omija to?

Coś ciężko mi się dzisiaj myśli, idę znaleźć trochę glukozy smile.gif
Imperior
@hawk: Doskonale zdaję sobie z tego sprawę. Dręczy mnie właśnie jak zabezpieczyć sesję na możliwie jak najwyższym poziomie i w miarę komfortowej pracy. IMHO to jest największa słabość w użyciu HTTP w połączeniu z przeglądarką bez użycia SSL (W przypadku własnych programów to co innego, bo tam za każdym wywołaniem można przesyłać dane).
hawk
BTW, SSL != bezpieczeństwo sesji. Użycie SSL nie załatwia problemu, i nie uniemożliwia ataków typu session fixation.
Imperior
Rzecz jasna, że SSL nie załatwia sprawy, ale chyba zgodzisz się, że SSL drastycznie poprawia bezpieczeństwo?

Jeżeli sesje oparte są tylko na sid, to jest możliwość, że ktoś przejmie sesję, ale przynajmniej w dużym stopniu możemy wykluczyć podsłuchanie komunikacji. Przecież samym php nie zdziałamy cudów... Użytkownik też musi dbać o bezpieczeństwo.
dooshek
Cytat(Speedy @ 2004-12-11 20:29:48)
W moim pomyśle ta opcja odpada ponieważ podajesz skryptowi jakąś frazę, a on ją szyfruje i sprawdza czy zgadza się z zaszyfrowanym wcześniej ciągiem , który jest w jakiejś bazie. md5 da się rozszyfrować, ale ciężko, więc sam zaszyfrowany ciąg takiemu "hackerowi" na niewiele się zda. Jeśli podasz skryptowi ciąg zaszyfrowany, to on go zaszyfruje i sprawdzi , czy "podwójnie zaszyfrowane" hasło zgadza się prawidłowym hashem. Oczywiście nie będzie się zgadzać smile.gif . Problem pojawia się jeżeli zostanie przechwycone niezaszyfrowane hasło. Ale i tak sprawa sniffer'ów dotyczy tylko sieci i tą sprawę należy rozpatrywać inaczej. Jeśli ktoś łączy się z internetem w inny sposób - problem znika smile.gif .

Nie rozumiesz - nic nie musisz "rozszyfrowywac" - wystarczy przechwycic Twoj czy tez md5 snifferem i zapodac do Twojego skryptu ktory bedzie "myslal", ze pochodzi on od uzytkownika... W rzeczywistosci bedzie pochodzil od hackera ktory bez podawania hasla sie dostanie na stronke. Mozesz to szyfrowac i rozszyfrowywac miliony razy - to nic nie da dopoki transmisja nie bedzie bezpieczna.

Co do snifferow i braku problemu podsluchiwania to nie bylbym pewien czy "problem znika" - podejrzewam, ze da sie podsluchac Cie jak uzywasz modemu, neo czy tez innego "dostepu" - pakiety przechodza przez rozne miejsca wiec nie sadze, ze to nie jest problem a jesli rozpatrujesz "bezpieczne" logowanie to Twoje takie nie jest niestety sad.gif
Jabol
@hawk: tak, mówię o zwykłym man-in-the-middle dla SSL, z tym, że dla pierwszej sesji, kiedy użytkownik nie zna jeszcze certyfikatu drugiej strony. Oczywiście jeżeli ktoś sobie pójdzie do firmy i spisze na karteczce spisze figerprint to już na to nie zdziałam o ile nie mam ich certyfiaktu (conajmniej na moją wiedzę), a zatruwawnie ARP nic na to działa, to powoduje tylko, że zamiast do serwera pakiety płyną do mnie.
@dooshek: Jeżeli sobie zrobisz jakiś ładny tunel ssh to do bezpiecznego już miejsca (najlepiej do końca) to nic takie "niebezpieczne lokalizacje" nie zdziałają.
hawk
@Jabol: AFAIK problem z man-in-the-middle był taki, że trzeba przedstawić użytkownikowi jakiś certyfikat. Nawet jak nie sprawdzi, co jest wpisane w środku. I ten fałszywy certyfikat musi być wystawiony przez jakieś centrum certyfikacyjne, bo inaczej przeglądarka zgłosi błąd. No chyba że użytkownik klika OK na każdy komunikat o błędzie, lub wykorzystamy dziurę IE, który dość liberalnie traktuje zasady, komu wolno wystawiać certyfikaty.

Tak czy siak, wymaga to chyba zaniedbania/ignorancji ze strony użytkownika. A swoją drogą, certyfikaty dla obu stron transakcji byłyby fajne winksmiley.jpg. Podobno w Estonii chcą wprowadzić elektroniczne dowody osobiste z zestawem kluczy do podpisu cyfrowego. Może niedługo to będzie realne?
Imperior
Cytat(hawk @ 2004-12-14 08:12:24)
Podobno w Estonii chcą wprowadzić elektroniczne dowody osobiste z zestawem kluczy do podpisu cyfrowego. Może niedługo to będzie realne?

Nie zdziwiłbym się. Estionia ma bardzo rozbudowaną sieć informatyczną w organizacjach państowych. My jesteśmy lata świetlne do tyłu.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.