Hash to nie wszystko - bezpieczne logowanie
21.02.2013 14:44
Czas iść za ciosem zatem i kolejny wpis o bezpieczeństwie już jest. Poprzedni wpis o hashowaniu haseł przekonał mnie iż muszę kontynuować moją misję informowania i edukowania społeczeństwa ;‑)
0. Hasło w bazie
wpis - Gdy zwykły hash to mało
1. SQL Injection
Zdecydowanie numer jeden wśród najczęstszych błędów programistów tworzących aplikacje/strony umożliwiające logowanie i rejestrowanie się. Złośliwy kod SQL przesyłany jest poprzez pola tekstowe na stronie, a jak atak wygląda w teorii możecie zobaczyć poniżej.
Gdy tylko napotkam w sieci stronę WWW, która nie wygląda zbyt nowocześnie(nie oznacza to, że ładna strona == bezpieczna strona) natychmiast sprawdzam podatność na atak SQL Injection.
[code=SQL]OR '1'='1'[/code]
i... jestę adminę ;‑) (oczywiście zaraz potem wysyłam maila administratorowi o luce)
Czemu tak łatwo się włamać?
Ponieważ programiści bardzo rzadko myślą jak "przeciętny Kowalski", a to właśnie Jan K. korzysta z tego co programiści stworzyli, więc trzeba to robić dla nich a nie dla siebie. Jest to bardzo częsty błąd, kiedy tworzymy coś "pod siebie" co nie zawsze jest takie proste i intuicyjne dla Kowalskiego. Widzę pole aby wpisać rok urodzenia no to wpisuje rok urodzenia - nic bardziej mylnego, pierwsze co to ciekawski użyszkodnik wpisze jakiś tekst albo i nawet złośliwy kod. Rozwiązanie: w polu "rok urodzenia" oczekujesz roku urodzenia, składa się on z 4 cyfr. Sprawdź czy wysłany przez użytkownika formularz z tym polem zawiera właśnie tylko i wyłączenie 4 znaki oraz czy są one cyframi. Proste i skuteczne. Należy tak postępować z różnymi rodzajami wysyłanych danych na serwer, jest to również bardzo ważne w przypadku wysyłania plików! Pamiętajmy, że rozszerzenie jest to tylko i wyłącznie umowne skojarzenie danego pliku z programem, a plik z końcówką JPEG może zawierać kod PHP czy inny złośliwy kod. Do wszystkich przesyłanych informacji podchodźmy z nastawieniem, że są one po to aby wyrządzić krzywdy. Filtrujmy wszystkie przychodzące dane, a do komunikacji z bazą danych w przypadku PHP korzystajmy z PDO.
2. Sesje
Kolejna popularna metoda to Session hijacking czyli przechwytywanie sesji. Są proste i skuteczne sposoby na poradzenie sobie z tym problem. Przy każdym wywołaniu strony poza
[code=PHP]if($_SESSION["zalogowany"]==1)[/code]
sprawdzajmy czy adres IP jest taki sam jak zapisany w sesji przy logowaniu, dodatkową warstwą ochronną może być sprawdzenie User Agent.
Identyfikator sesji - generujmy nowy za każdym razem.
[code=PHP]session_regenerate_id();[/code]
Większość z nas korzysta z hostingów współdzielonych, ich ulubioną cechą hakerów jest to iż bardzo często korzystają one z wspólnego katalogu do przechowywania sesji. Zmieńmy to choćby w samym kodzie PHP jak nie mamy możliwości zmian pliku php.in czy .htaccess
[code=PHP]ini_set('session.save_path', '/bezpieczna/lokalizacja/sesji');[/code]
W sesji nigdy nie zapisujemy haseł(broń cię Boże kiedy zapisujesz hasło jako plaintext), nawet hashy. Podobnie sytuacja wygląda z loginem/emailem, stosowanie hashy dla tych wartości również nie jest zalecane. Zatem jak rozpoznać danego użytkownika? np. unikalną wartością w bazie danych, a w sesji wartość tą trzymać jako hash.
O wadach i zaletach sesji można pisać naprawdę wiele. Jednak gdy zależy nam szczególnie na bezpieczeństwie i czujemy się na siłach, najlepszym rozwiązaniem jest stworzenie własnego mechanizmu sesji opartego na bazie danych.
3. Brute force
Atak polega na sukcesywnym sprawdzeniu możliwych kombinacji np. hasła, w sumie to głównie hasła ;‑) Istnieje bardzo prosta metoda aby temu zaradzić - ograniczenie ilości prób logowania. W bazie przechowujmy ilość nieudanych zalogowań dla poszczególnego użytkownika i w przypadku gdy ilość ta będzie równa 5 lub 10(max) zablokujmy konto i próby logowania, poinformujmy o tym użytkownika i przedstawmy mu możliwości odblokowania konta. Można też zablokować konto na np.15 minut, za drugim razem na 24 godziny, a dopiero potem zablokować bez ograniczenia czasowego.
4. Logi, logi i jeszcze raz logi
Logujmy wszystkie istotne operacje. W przypadku nieudanych prób logowania również. Zapisujmy IP komputera, czas czy nawet User Agent - to już zależy od nas co będzie istotne w danym przypadku. Dzięki logom będziemy w stanie uchwycić wszelkie dziwne zachowania użytkowników na stronie.
5. HTTPS
Jeżeli mamy taką możliwość to korzystajmy z niej. Na nic nam wszelkie zabezpieczenia, które opisałem powyżej jak ktoś przechwyci czyjś login i hasło w formie jawnego tekstu poprzez sniffowanie. Certyfikat SSL to jest wydatek rzędu 100‑200 zł rocznie, oczywiście są i droższe ale daje on(właściwie to już popularna kłódeczka) poczucie bezpieczeństwa użytkownikom. Kiedy tworzymy aplikację prywatną można również korzystać z protokołu HTTPS bez certyfikatu, jedyne co to będziemy musieli ręcznie potwierdzić iż ufajmy stronie ale wszelkie dane będą szyfrowane ;‑) Jest również nieco inne rozwiązania, mniej bezpieczne ale darmowe - jCryption
Mhhh... sporo tego, ale o bezpieczeństwie nigdy nie za wiele, uważajmy aby nie popaść w paranoje i nie przesadzać z bezpieczeństwem - należy znać umiar.
A kolejny wpis już niedługo, też o bezpieczeństwie aplikacji internetowych.
PS. Jeżeli ktoś ma jakieś pytania, które chce abym napisał coś więcej o tym w następnym wpisie lub jakieś uwagi zachęcam do komentowania poniżej ;‑) Pozdrawiam