Zabezpieczenie skryptu PHP |
Zabezpieczenie skryptu PHP |
4.03.2017, 20:37:48
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
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 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 Ten post edytował Baku12345 4.03.2017, 21:40:30 |
|
|
4.03.2017, 22:30:02
Post
#2
|
|
Grupa: Zarejestrowani Postów: 2 355 Pomógł: 533 Dołączył: 15.01.2010 Skąd: Bydgoszcz Ostrzeżenie: (0%) |
Przypisuj cookie do konkretnej domeny, tyle. A jak masz separację pod tą samą domeną, to dodaj do cookie adres i sprawdzaj czy się zgadza. Zapewni to separacje pomiędzy projektami. Zwiększy jakoś tam bezpieczeństwo, że pomiędzy skryptami nie będzie można edytować sesji.
Ale oczywiście nikt nie może zmienić sobie ID, bo jest pobierane z bazy danych. Pytanie w stylu: "Mam hasło do mojej witryny i mogę się na nią włamać dzięki temu. Jak zabezpieczyć skrypt?" Ten post edytował Damonsson 4.03.2017, 22:34:14 |
|
|
4.03.2017, 22:38:09
Post
#3
|
|
Grupa: Zarejestrowani Postów: 96 Pomógł: 2 Dołączył: 13.07.2015 Ostrzeżenie: (0%) |
Co masz na myśli pisząc sztucznie? Ktoś musiałby się dobrać do Twojego kompa żeby ukraść to id (albo do konta użytkownika który korzysta z Twojej ulsugi i podrkaść wartość sesyjną). Może to zrobić np. korzystając z public network a jednym z użytkowników jest niegrzeczny Janusz który nasłuchuje na Twój traffic i kradnie info! evil bitch!
Jak się zabezpieczyć? Ciężko znaleść złoty środek ale możesz spróować poprzez sprwadzanie IP naprzykład. Takie masz sessions data? Wez sobie to md5 sformatuj lub crypt(), a później porównuj np: http://php.net/hash_equals Po drugie: Nie wszystko w jednym pliku. Trzymasz połączenie z bazą, logikę i prezentacje danych w jednym miejscu. Właśnie uśmierciłeś małęgo pingwinka. Tak naprawde wystarczy użyć empty() , bez isset() |
|
|
5.03.2017, 03:47:07
Post
#4
|
|
Grupa: Zarejestrowani Postów: 46 Pomógł: 1 Dołączył: 23.04.2011 Ostrzeżenie: (0%) |
W sumie faktycznie dodanie adresu ip lub domeny mogłoby trochę pomóc. Co do hashowania tej linii
to byłby to dobry pomysł, gdybym w linii 46 nie pobierał danych po id użytkownika
Tak więc muszę mieć tu czyste id bez hashowania. Co do pytania co mam na myśli pisząc sztucznie to mam na myśli stworzenie sesji przed wejściem na stronę. Wystarczy, że stworzę sobie plik atak.php i umieszczę w nim to
Jeśli go otworzę w przeglądarce, to stworzy się sesja z id użytkownika 1 i aktualnym czasem. Teraz jak otworzę plik index.php (ten co go pokazałem w pierwszym poście, to nawet się nie będę musiał logować na użytkownika o id 1. Będzie zalogowany bez podawania loginu i hasła I tu jest problem. Ten post edytował Baku12345 5.03.2017, 03:51:49 |
|
|
5.03.2017, 06:22:38
Post
#5
|
|
Grupa: Zarejestrowani Postów: 6 373 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. -------------------- |
|
|
5.03.2017, 10:25:47
Post
#6
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
Postaram się tutaj przedstawić to jakoś w miarę klarownie, bo na podstawie wielu postów na różnych forach widać jak na dłoni, że jak się ktoś czegoś uczy to jeszcze w starym stylu i pewnie też z jakichś beznadziejnych i niepraktycznych tutoriali PHP które są jeszcze w internecie.
Po pierwsze, podział kodu i podział odpowiedzialności, dla uproszczenia zakładam że wszystkie pliki PHP są w jednym katalogu projektu, lecę więc po kolei, od helperów, przez szablony aż po inne pliki. Uwaga, zakładam że liczą się duże i małe litery w nazwach plików z klasami. Klasa View.php odpowiedzialna za renderowanie szablonów:
Klasa Auth.php odpowiedzialna za logowanie i sprawdzanie czy użytkownik jest zalogowany:
plik config.php z danymi do połączenia z bazą i danymi do obsługi logowania:
główny layout, plik layout.php
szablon logowania login.php
no i ostatecznie index.php
Co też testowałem na jednej ze swoich baz MySQL na localhoście, nie wiem tylko czy ta funkcja reloadAsGet zadziała na wszystkich przeglądarkach. W tym przykładzie po ustawionym czasie bezczynności 1 minuty po zalogowaniu nastąpi po tym czasie przeładowanie strony nie jako POST ale GET ze sprawdzeniem czy użytkownik jest zalogowany, jeśli nie to się wyświetli ten formularz. Po drugie. Jest chyba dość cienka granica między bezpieczeństwem a paranoją. Tu zakładam że w każdym innym projekcie są różne te hash_key i zakładam że jest SHA256 i 64 znaków w polach z hasłem. Ten automatyczny reload to w pewnych przypadkach może pewnie nawet przeszkadzać niż pomagać, w szczególności może denerwować. I nie jakieś przypisywanie bezpośrednio do sesji a tutaj użyty jest klucz auth_user związany z tą właśnie obsługą logowania a ze względów praktycznych do tejże sesji zapisywany jest cały wiersz z bazy danych a nie tylko niektóre pola, nie muszę chyba tłumaczyć dlaczego. |
|
|
Wersja Lo-Fi | Aktualny czas: 22.09.2024 - 03:17 |