Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Hash to nie wszystko - bezpieczne logowanie

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.OR '1'='1'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 pozaif($_SESSION["zalogowany"]==1)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.session_regenerate_id();

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 .htaccessini_set('session.save_path', '/bezpieczna/lokalizacja/sesji');

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 

internet bezpieczeństwo programowanie

Komentarze

0 nowych
Mifczu   11 #1 21.02.2013 15:42

Jeszcze jest najprostszy atak świata DoS o ile z samym atakiem ciężko jest walczyć to np z parserami naszej strony które można np weryfikując access logi i ip które za dużo razy w określonym czasie się odwołuje do naszej strony wyświetlić capche przed jakimikolwiek odwołaniami do bazy.

Inny dość częsty szczególnie tworzy błąd/dziura to XSS czyli wyświetlanie gdzieś danych pochodzących od użytkownika które nie zostały odpowiednio "wyescapowane". Można wtedy wstrzyknąć swój javascript albo zupełnie rozsypać wygląd strony.

  #2 21.02.2013 15:45

"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."

Hm.. rzutowanie + kontrola zakresu.
Samo sprawdzenie czy to cyfry to za mało, chyba że dopuszczasz ludzi urodzonych np. w 9125 roku xD


"w przypadku PHP korzystajmy z PDO."

+1, ale warto dopisać, że z głową
Wiem że to się może wydawać dziwne, ale z PDO też da się zrobić kod podatny na SQL Injection.


"Sesje"

Dodam tylko, że warto też stosować session.use_only_cookies.
Zawsze wtedy "ukrywamy" identyfikator, dosłownie przed oczami wścibskich.


"HTTPS"

Tutaj można by napisać dużo, naprawdę dużo. Samo wrzucenie https nie zawsze wiele daje. Przykład z brzegu: najczęściej ciasteczka i tak nie są zabezpieczone.


Jak dla mnie zabrakło info o XSS i CSRF, chociażby podstawowego.


@Mifczu:
DOSem nie powinien się w żadnym wypadku zajmować skrypt.
Nie jest on za bardzo w stanie nic zdziałać.
Z tym trzeba (próbować) walczyć na dużo niższym poziomie.

Niemniej, jak ktoś będzie chciał, to jedynym ograniczeniem będzie łącze, reszta i tak padnie.

Autor edytował komentarz.
Ardziej   5 #3 21.02.2013 15:53

@Mifczu, @lukasamd - tak jak wspominałem będzie kolejny wpis i tam będzie nieco więcej o XSS i CSRF ;-)
@lukasamd - to był przykład tylko dla konkretnego pola, co do roku urodzenia zastanawiałem się czy by nie dać widełek, ale z drugiej strony nie wpływa to na bezpieczeństwo i robi naszą aplikacje bardziej przyszłościową haha. ;-D joke.
Co do PHPSSID to na szczęście coraz rzadziej spotykany problem i domyślna konfiguracja serwera to wyłącza, ale przyznam bez bicia, że zapomniałem o tym a myślałem aby dać ;-)
HTTPS służy tylko i wyłącznie ochronie przed sniffowaniem, pozostałem zabezpieczenia trzeba zastosować i tak, ale samo rzeczywiście jest na nic ;-)
Będzie kolejna część ;-)

Mifczu   11 #4 21.02.2013 15:59

@lukasamd oczywiście nie powinno to być jedyne zabezpieczenie ale dla podejrzanych powtarzających się "ciężkich" akcji warto robić zabezpieczenia może nie tyle przed samym DoS-em ale przed zbyt częstym wywoływaniem akcji które mogą zamulić serwer.

tfl   8 #5 21.02.2013 17:57

"prywatną można również korzystać z protokołu HTTPS bez certyfikatu, "

No raczej bez certyfikatu sie nie pyknie :) w takiej sytuacji wystawia sie samopodpisany certyfikat lub stosuje sie cudzy (a czemu by nie, skoro sie da?).

@lukasamd

"Przykład z brzegu: najczęściej ciasteczka i tak nie są zabezpieczone. " Masz na mysli flage secure?
Jesli tak, to spiesze z wyprowadzaniem z bledu :)

Flow ustawiania ciasteczka wyglada mnie wiecej tak:
1) przegladarka robi GET lub POST do serwera
2) Serwer odpowiada naglowkami w tym (by ustawic ciastko) sle headera Set-Cookie:
3) Przegladarka majac cookie wysyla w requestach naglowek Cookie

Wobec tego, jesli nie uzywam wszedzie https to ustawienia flagi secure moze spodowac spektakularne wywalenie aplikacji (brak dostepu do jakiejs sekcji wymagajacej logowania itp).

A dlaczego czasem nie da sie uzywac wszedzie https? Na przyklad dlatego, ze gdy musimy osadzic na stronie kontent, ktory nie jest podawany przez https przegladarka zareaguje informacja, ze nie wszystko na stronie jest szyfrowane, co czesto przez przecietnego usera www powoduje atak strachu i pewnosc inwigilacji.

kwpolska   5 #6 21.02.2013 18:04

SQL injection powinno być tak:

' or 1=1 --

tfl   8 #7 21.02.2013 18:46

@kwpolska

Doprawdy?

Sprobujmy...

Query w oryginale niechaj ma taka forme:

Select `id` from `auth` where `login` = 'admin' and `haslo` = 'haslo'

Zamiast stringa haslo wstrzykujemy to co napisales, mam wiec taki efekt:

Select `id` from `auth` where `login` = 'admin' and `haslo` = '' or 1=1 --'

i co dostaniemy?

Select `id` from `auth` where `login` = 'admin' and `haslo` = '' or 1=1 --' Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''

Wszystko zalezy od sposobu w jaki zbudowane jest query i w jaki sposob silnik bazy danych komentuje

Mifczu   11 #8 22.02.2013 11:33

SQL injection może mieć wiele form i nie zawsze musi być to formularz logowania i dostanie się do konta innego użytkownika. Często tam gdzie wyświetlane są jakieś dane z bazy na podstawie jakiś ustawień na stronie (pole wyszukiwania, filtry, sortowanie itp). Wtedy można np wyświetlić sobie serię danych i skopiować bazę :)

  #9 22.02.2013 13:52

@tfl:
Ok, ja sobie z tego zdaję sprawę.
Dlatego używam HTTPS na całości + flaga.
Nie ma problemów z wywalaniem sesji, a że zabezpieczone cookies wskazują na konkretny adres, to nie ma też żadnych straszliwych komunikatów (ewentualnie tylko ikonka dodatkowa przy adresie, lub info od IE, że jest wyświetlana tylko bezpieczna zawartość).