Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Czy takie zabezpieczenia są wystarczające ?
Forum PHP.pl > Forum > PHP
sheriff
Jako iż to mój pierwszy post, witam wszystkich serdecznie smile.gif

Napisałem prosty skrypt do rejestracji użytkownika. Chcę się dowiedzieć jakie błędy popełniłem i czy takie zabezpieczenia są wystarczające.
Z góry dziękuję winksmiley.jpg

  1. <?php
  2. $error = ' ';
  3. $fail = 0;
  4.  
  5. if (!isset($_POST['login'])){
  6. echo '
  7. <form method="post" action="register.php">
  8. <input type="text" name="login" /><br><br>
  9. <input type="password" name="password"/><br>
  10. <input type="password" name="rpassword"/><br><br>
  11. <input type="submit" value="Gotowe"/>
  12. </form>
  13. ';
  14. $fail = 1;
  15. }
  16. else{
  17. $login = $_POST['login'];
  18. $pass = $_POST['password'];
  19. $rpass = $_POST['rpassword'];
  20. $passmd5 = md5($pass);
  21. mysql_connect('localhost', 'root', 'krasnal') or die('MySql fatal error.');
  22. mysql_select_db('sheriffengine') or die('MySql fatal error.');
  23.  
  24. if (strlen($login) < 4)$error .= '<br>- login musi składać się z conajmniej 5 znaków';
  25.  
  26. if (strlen($pass) < 5)$error .= '<br>- hasło musi składać się z conajmniej 6 znaków';
  27.  
  28. if ($pass !== $rpass)$error .= '<br>- podane hasła muszą być takie same';
  29.  
  30.  
  31. if (preg_match("/[^A-z0-9_-]/", $login)==1)$error .= '<br>- login może składać się wyłącznie z liter i cyfr';
  32.  
  33.  
  34. if (preg_match("/[^A-z0-9_-]/", $pass)==1 || preg_match("/[^A-z0-9_-]/", $rpass)==1 )$error .= '<br>- hasło może składać się wyłącznie z liter i cyfr';
  35.  
  36. if(mysql_num_rows(mysql_query("select * from users where user_login='".htmlspecialchars($login."'")))) $error .= '- użytkownik o podanym loginie istnieje, wybierz inny login';
  37.  
  38. if ($error !== ' '){
  39. echo '<br>Rejestracja się nie powiodła. Zastosuj się do poniższych wskazówek:';
  40. $fail = 1;
  41. }
  42.  
  43. echo $error;
  44.  
  45. }
  46.  
  47. if ($fail == 0){
  48. mysql_query("insert into users values(NULL, '".htmlspecialchars($login)."', '".$passmd5."')");
  49. echo 'Witaj '.$login.'! Rejestracja przebiegła pomyślnie.';
  50. }
  51.  
  52. ?>
  53.  


l0ud
W pierwszym zapytaniu ' znajduje się w htmlspecialchars(). To błąd, który pokazuje przy okazji, że to zabezpieczenie w obecnej formie jest do... niczego winksmiley.jpg

Bo skoro zapytanie działa mimo tego, oznacza to, że pojedyncze cudzysłowy ' nie są zamieniane przez htmlspecialchars(). A skoro nie są no to mamy dziurę winksmiley.jpg

Rady:
- nie polecam używania htmlspecialchars() przed wrzucaniem czegokolwiek do bazy. Funkcję tą stosuj najlepiej tuż przed wyświetleniem czegoś wprowadzonego przez użytkownika (najlepiej bezpośrednio w echo '') - aby zapobiec XSS.
- zamiast htmlspecialchars() do zapytań w bazie użyj mysql_real_escape_string aby zabezpieczyć się przed SQL Injection
- skoro ładnie łączysz ciągi za pomocą . (zamiast wstawiać zmienne bezpośrednio w nich - pomiędzy " ") zacznij używać pojedynczych cudzysłowów ' ' zamiast podwójnych " ". W zapytaniach SQL natomiast ciągi opakuj " " zamiast w ' '. Słowem - zamień miejscami ' i " w zapytaniach.


Powinno wyglądać to np. tak:

  1. #
  2. if(mysql_num_rows(mysql_query('select * from users where user_login="'.mysql_real_escape_string($login).'"'))) $error .= '- użytkownik o podanym loginie istnieje, wybierz inny login';


A... i md5() jest już do niczego winksmiley.jpg. Zamiast tego użyj przynajmniej sha1. Można jeszcze dodać tzw. sól do hasła - poszukaj.
haahh
1. Ładniej będzie sprawdzać błędy tak: (wtedy niepotrzebna jest zmienna $fail)

  1. if(empty($error)){
  2.  
  3. //dodajemy do bazy danych
  4.  
  5. }
  6. else{
  7. echo '<br>Rejestracja się nie powiodła. Zastosuj się do poniższych wskazówek:';
  8. echo $error;
  9. }

2. W preg_match możesz już sprawdzać, czy ma dobrą długość np. tak (ale to jak chcesz):

  1. preg_match('/^[A-Z \'.-]{2,20}$/i', $login) // od 2 do 20 znaków

3. Wystarczy:
  1. if(preg_match("/[^A-z0-9_-]/", $login))
  2.  
  3. zamiast
  4.  
  5. if(preg_match("/[^A-z0-9_-]/", $login)==1)

4. Osobiście wszystkie dane od użytkownika najpierw trimuje, później mysql_real_escape_string i ewentualnie strip_tags (ale tutaj masz wyrażenia regularne).
  1. $trimmed = array_map('trim', $_POST); // jest łatwiej bo zamiast trim($_POST['first_name']) piszesz:
  2. $trimmed['first_name'];

5. Hasło najlepiej zabezpieczyć jakąś solą/ziarnem/czy jak to inaczej nazywają indywidualnym dla każdego usera (sporo o tym na forum)
6. Ja bym dał formularz na dół oddzielony od kodu php, tak by się wyświetlał jeżeli będą jakieś błędy. Kiedy wszystko jest ok używać exit();, ale to znowu zależy od gustu.
Fifi209
Odsyłam do tematu: Temat: Bezpieczenstwo skryptow PHP

btw. wyrażenia masz źle napisane, możesz tutaj użyć odpowiedniego ctyle_ zamiast ich.
tehaha
- przede wszystkim wszelkie dane otrzymane od użytkownika i użyte w zapytaniu wkładaj do mysql_real_escape_string()
- nie wiem po co używasz htmlspecialchars() skoro chcesz zezwalać tylko na litery i cyfry..może sprawdź najpierw w manualu co robi ta funkcja
- czy to preg_match() na pewno działa? bo coś mi nie gra w tych wzorcach
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.