Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Zabezpieczenie skryptu PHP
Baku12345
post
Post #1





Grupa: Zarejestrowani
Postów: 46
Pomógł: 1
Dołączył: 23.04.2011

Ostrzeżenie: (0%)
-----


Witam
Mam skrypt co do którego mam zastrzeżenia jeśli chodzi o bezpieczeństwo. Nie wrzucę go ze względu na to, że jest zbyt długi. Wrzucę natomiast jego uproszczoną wersję by odnieść się do problemu. A wygląda on tak
  1. <?php
  2.  
  3. $now = time();
  4. $session_data = "";
  5.  
  6. $pdo = new PDO('mysql:host=localhost; port=3306; dbname=test', 'root', '');
  7.  
  8. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  9. $pdo->exec("SET NAMES 'utf8'");
  10.  
  11. if (isset($_POST['login']) && isset($_POST['password']))
  12. {
  13. if (!empty($_POST['login']) && !empty($_POST['password']))
  14. {
  15. $login = addslashes(strip_tags($_POST['login']));
  16. $password = hash_hmac('sha256', $_POST['password'], '2NYbH5qS8J');
  17.  
  18. $stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login && password = :password");
  19. $stmt -> execute(array(':login' => $login, ':password' => $password));
  20.  
  21. if ($row = $stmt->fetch(PDO::FETCH_ASSOC))
  22. {
  23. $_SESSION[$session_data] = array('id' => $row['id'], 'time' => $now, 'user' => $row['name']);
  24. }
  25. else
  26. {
  27. echo "Podałeś błędny login lub hasło";
  28. }
  29. }
  30. else
  31. {
  32. echo "Nie wprowadziłeś wszystkich danych";
  33. }
  34. }
  35.  
  36. $max_idle_time = 900;
  37. if (isset($_SESSION[$session_data]) && !empty($_SESSION[$session_data]))
  38. {
  39. if ($now - $_SESSION[$session_data]['time'] < $max_idle_time)
  40. {
  41. $_SESSION[$session_data]['time'] = $now;
  42. echo "Jesteś zalogowany";
  43. // tu następuje pobranie z bazy danych danych przeznaczonych dla użytkownika o danym id a następnie ich wyświetlenie
  44. }
  45. else
  46. {
  47. echo "Przekroczono czas bezczynności";
  48. }
  49. }
  50. else
  51. {
  52. echo '<h1>Panel Użytkownika</h1>
  53. <form method="post" action="">
  54. <div>
  55. <input type="text" name="login" placeholder="Twój login" value="">
  56. </div>
  57. <div>
  58. <input type="password" name="password" placeholder="Twoje hasło" value="">
  59. </div>
  60. <button type="submit">Zaloguj się</button>
  61. </form>';
  62. }
  63. ?>


Skrypt działa dobrze. Przy pierwszym wejściu na stronę przechodzimy na koniec kodu do formularza, ponieważ zmienna login, password i session nie istnieją.
Jeżeli wyślemy login, hasło i skrypt sprawdzi, że nie są puste to jest porównywany hash z tym znajdującym się w bazie. Dalej jeśli się zgadzają jest tworzona zmienna sesyjna, w której jest id, czas i nazwa użytkownika. W drugiej części skrypt sprawdza, że istnieje sesja między innymi z id użytkownika i wyświetla dane przeznaczone tylko dla niego.

Problem w tym, że jeżeli nie znam loginu ani hasła użytkownika to też mogę się dostać do danych przeznaczonych tylko dla danego użytkownika. Wystarczy, że w sposób "sztuczny" utworzę zmienną sesyjną z id i zmieniając tylko id mogę sobie skakać z konta na konto.

Pytanie jak zabezpieczyć taki skrypt?

PS: Trafiłem przypadkiem na ten błąd robiąc kopię tego skryptu, ale z podpiętą inną bazą innym loginem i hasłem. Odpaliłem jeden skrypt podałem login i hasło, a potem nie zamykając przeglądarki odpaliłem drugi skrypt z całkiem inną bazą loginem i hasłem w niej (tylko id użytkownika się zgadzało) i byłem zalogowany na obu skryptach. Mogłem sobie zmieniać id użytkownika w jednym skrypcie, a w drugim byłem zalogowany na tym użytkowniku o danym id. Wnioskuję więc, że każdy mógłby wysłać zmienną sesyjną z id i by został wpuszczony i by mu się wyświetliły dane tego użytkownika.

PS2: Po linii 39 następuje sprawdzenie czy została utworzona zmienna sesyjna między innymi z id użytkownika, a w linii 46 jest select który pobiera dane przeznaczone dla użytkownika o tym id. I właśnie tu jest luka, którą nie wiem jak załatać, jedyne co mi przychodzi do głowy to ponowne sprawdzenie czy nazwa użytkownika i hasło się zgadzają, ale wtedy jaki sens ma kod przed linią 39? Mam nadzieję, że jasno to opisałem (IMG:style_emoticons/default/smile.gif) W skrócie macie 2 kopie tego skryptu logujecie się na jednej to w drugiej jesteście zalogowani mimo, że hasła użytkownika w bazie podpiętej do drugiego skrypcie nie znacie. Prościej nie umiem (IMG:style_emoticons/default/smile.gif)

Ten post edytował Baku12345 4.03.2017, 21:40:30
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
viking
post
Post #2





Grupa: Zarejestrowani
Postów: 6 381
Pomógł: 1116
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


A teraz się zastanów ile jest możliwych kombinacji przy tej ilości znaków nazwy sesji.
Oczywiście mógłby dojść do powtórzenia ale szanse na to nikłe.
Po co to addslashes? Raczej fitruj poprzez sprawdzanie dopuszczalnych znaków.
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 10.10.2025 - 12:52