Próbuję dowiedzieć się więcej o naprawianiu sesji PHP i przechwytywaniu oraz o sposobach zapobiegania tym problemom. Czytałem następujące dwa artykuły na stronie Chrisa Shifletta:
Jednak nie jestem pewien, czy dobrze rozumiem.
Aby zapobiec utrwalaniu sesji, wystarczy wywołać session_regenerate_id (true); po pomyślnym zalogowaniu się kogoś? Myślę, że dobrze to rozumiem.
Mówi również o używaniu tokenów przekazywanych w adresach URL za pośrednictwem $ _GET, aby zapobiec przejmowaniu sesji. Jak by to dokładnie zostało zrobione? Zgaduję, że kiedy ktoś się loguje, generujesz swój token i przechowuje go w zmiennej sesji, a następnie na każdej stronie porównujesz tę zmienną sesji z wartością zmiennej $ _GET?
Czy ten token musiałby być zmieniany tylko raz na sesję czy przy każdym ładowaniu strony?
Czy jest to również dobry sposób na zapobieganie przechwytywaniu bez konieczności przekazywania wartości w adresach URL? byłoby to o wiele łatwiejsze.
Odpowiedzi:
Ok, są dwa oddzielne, ale powiązane problemy i każdy jest traktowany inaczej.
Utrwalanie sesji
W tym miejscu atakujący jawnie ustawia identyfikator sesji dla użytkownika. Zwykle w PHP robi się to poprzez nadanie im adresu URL takiego jak
http://www.example.com/index...?session_name=sessionid
. Gdy atakujący przekaże adres URL klientowi, atak jest taki sam, jak atak przejmujący sesję.Istnieje kilka sposobów zapobiegania utrwalaniu sesji (zrób wszystkie):
Ustaw
session.use_trans_sid = 0
w swoimphp.ini
pliku. To powie PHP, aby nie umieszczał identyfikatora w adresie URL i nie czytał adresu URL dla identyfikatorów.Ustaw
session.use_only_cookies = 1
w swoimphp.ini
pliku. To powie PHP, aby nigdy nie używał adresów URL z identyfikatorami sesji.Regeneruj identyfikator sesji za każdym razem, gdy zmieni się stan sesji. Oznacza to jedno z poniższych:
Session Hijacking
Jest to sytuacja, w której osoba atakująca uzyskuje identyfikator sesji i może wysyłać żądania tak, jakby był tym użytkownikiem. Oznacza to, że ponieważ atakujący ma identyfikator, są one praktycznie nie do odróżnienia od prawidłowego użytkownika w odniesieniu do serwera.
Nie można bezpośrednio zapobiec przejmowaniu sesji. Możesz jednak podjąć kroki, aby uczynić go bardzo trudnym i trudniejszym w użyciu.
Użyj silnego identyfikatora skrótu sesji:
session.hash_function
wphp.ini
. Jeśli PHP <5.3, ustawsession.hash_function = 1
na SHA1. Jeśli PHP> = 5.3, ustaw nasession.hash_function = sha256
lubsession.hash_function = sha512
.Wyślij silny hash:
session.hash_bits_per_character
inphp.ini
. Ustaw to nasession.hash_bits_per_character = 5
. Chociaż nie utrudnia to złamania, ma znaczenie, gdy atakujący próbuje odgadnąć identyfikator sesji. Identyfikator będzie krótszy, ale zawiera więcej znaków.Ustaw dodatkową entropię z
session.entropy_file
isession.entropy_length
wphp.ini
pliku. Na przykład ustaw pierwszy na,session.entropy_file = /dev/urandom
a drugi na liczbę bajtów, które zostaną odczytane z pliku entropiisession.entropy_length = 256
.Zmień nazwę sesji z domyślnego PHPSESSID. Osiąga się to przez wywołanie
session_name()
z własną nazwą identyfikatora jako pierwszym parametrem przed wywołaniemsession_start
.Jeśli jesteś naprawdę paranoikiem, możesz również obrócić nazwę sesji, ale uważaj, że wszystkie sesje zostaną automatycznie unieważnione, jeśli to zmienisz (na przykład, jeśli uzależnisz to od czasu). Ale w zależności od przypadku użycia może to być opcja ...
Często zmieniaj identyfikator sesji. Nie robiłbym tego przy każdym żądaniu (chyba że naprawdę potrzebujesz tego poziomu bezpieczeństwa), ale w losowych odstępach czasu. Chcesz to często zmieniać, ponieważ jeśli napastnik przejmie sesję, nie chcesz, aby mógł z niej korzystać zbyt długo.
Uwzględnij klienta użytkownika z
$_SERVER['HTTP_USER_AGENT']
sesji. Zasadniczo, gdy sesja się rozpocznie, zapisz ją w czymś podobnym$_SESSION['user_agent']
. Następnie przy każdym kolejnym żądaniu sprawdź, czy pasuje. Zauważ, że można to sfałszować, więc nie jest to w 100% wiarygodne, ale lepiej niż nie.Uwzględnij adres IP użytkownika z
$_SERVER['REMOTE_ADDR']
sesji. Zasadniczo, gdy sesja się rozpocznie, zapisz ją w czymś podobnym$_SESSION['remote_ip']
. Może to być problematyczne w przypadku niektórych dostawców usług internetowych, którzy używają wielu adresów IP dla swoich użytkowników (na przykład AOL). Ale jeśli go użyjesz, będzie znacznie bezpieczniejszy. Jedynym sposobem na sfałszowanie adresu IP przez napastnika jest włamanie się do sieci w pewnym momencie między rzeczywistym użytkownikiem a Tobą. A jeśli włamą się do sieci, mogą zrobić o wiele gorzej niż przejęcie (takie jak ataki MITM itp.).Dołącz token do sesji i po stronie przeglądarek, które często zwiększasz i porównujesz. Zasadniczo dla każdego żądania wykonaj
$_SESSION['counter']++
po stronie serwera. Zrób też coś w JS po stronie przeglądarki, aby zrobić to samo (używając lokalnej pamięci). Następnie, kiedy wysyłasz żądanie, po prostu weź wartość jednorazową tokena i sprawdź, czy liczba jednorazowa jest taka sama na serwerze. W ten sposób powinieneś być w stanie wykryć przejętą sesję, ponieważ atakujący nie będzie miał dokładnego licznika, a jeśli tak, będziesz mieć 2 systemy transmitujące tę samą liczbę i możesz stwierdzić, że jeden jest sfałszowany. To nie zadziała w przypadku wszystkich aplikacji, ale jest jednym ze sposobów rozwiązania problemu.Uwaga na temat dwóch
Różnica między utrwalaniem sesji a przejęciem polega tylko na tym, w jaki sposób identyfikator sesji jest zagrożony. W fiksacji identyfikator jest ustawiany na wartość, którą napastnik zna wcześniej. W Hijacking jest albo odgadnięty, albo skradziony użytkownikowi. W przeciwnym razie skutki obu są takie same, gdy identyfikator zostanie naruszony.
Regeneracja identyfikatora sesji
Zawsze, gdy ponownie generujesz identyfikator sesji przy użyciu
session_regenerate_id
starej sesji, należy go usunąć. Dzieje się to w sposób przejrzysty w przypadku podstawowego programu obsługi sesji. Jednak niektóre niestandardowe programy obsługi sesji używająsession_set_save_handler()
tego nie robią i są narażone na atak na stare identyfikatory sesji. Upewnij się, że jeśli używasz niestandardowej procedury obsługi sesji, śledzisz otwierany identyfikator, a jeśli nie jest to ten sam, który zapisujesz, jawnie usuwasz (lub zmieniasz) identyfikator ze starego.Używając domyślnego programu obsługi sesji, wystarczy tylko wywołać
session_regenerate_id(true)
. Spowoduje to usunięcie starych informacji o sesji. Stary identyfikator nie jest już ważny i spowoduje utworzenie nowej sesji, jeśli osoba atakująca (lub ktokolwiek inny w tej sprawie) spróbuje go użyć. Uważaj jednak na niestandardowe programy obsługi sesji ....Niszczenie sesji
Jeśli masz zamiar zniszczyć sesję (na przykład podczas wylogowania), upewnij się, że zniszczyłeś ją dokładnie. Obejmuje to wyłączenie pliku cookie. Używając
session_destroy
:źródło
session_regenerate_id
nie unieważnia sesji, która jest nadal powiązana ze starym ID; tylko jeśli parametr delete_old_session ma wartość true, sesja zostanie zniszczona. Ale co, jeśli osoba atakująca zainicjowała regenerację identyfikatora?session.entropy_file = /dev/urandom
. Udowodniono, że wewnętrzna generacja entropii w PHP jest wyjątkowo słaba, a pula entropii dostarczana przez / dev / random lub / dev / uranom jest najlepszą, jaką można uzyskać na serwerze WWW bez sprzętowego rng.session.cookie_httponly
isession.cookie_secure
. Pierwsza z nich pomaga udaremnić xss (ale nie jest doskonała). Drugie miejsce to najlepszy sposób na zatrzymanie OWASP A9 ...Oba ataki sesyjne mają ten sam cel: uzyskać dostęp do legalnej sesji innego użytkownika. Ale wektory ataku są różne:
W ataku typu Session Fixation atakujący ma już dostęp do ważnej sesji i próbuje zmusić ofiarę do skorzystania z tej konkretnej sesji.
W ataku „ Session Hijacking ” napastnik próbuje uzyskać identyfikator sesji ofiary, aby użyć jej / jej sesji.
W obu atakach identyfikator sesji jest poufnymi danymi, na których koncentrują się te ataki. Jest to więc identyfikator sesji, który musi być chroniony zarówno dla dostępu do odczytu (przechwytywanie sesji), jak i dostępu do zapisu (utrwalenie sesji).
W tym przypadku obowiązuje również ogólna zasada ochrony wrażliwych danych przy użyciu protokołu HTTPS. Dodatkowo wykonaj następujące czynności:
Aby zapobiec atakom Session Fixation , upewnij się, że:
true
) i ustaw go na HTTPS tylko jeśli to możliwe (ustaw session.cookie_secure natrue
); możesz zrobić jedno i drugiesession_set_cookie_params
.Aby zapobiec atakom typu Session Hijacking , upewnij się, że:
true
)Aby zapobiec atakom obu sesji, upewnij się, że:
session_regenerate_id(true)
po próbie uwierzytelnienia (true
tylko w przypadku pomyślnej) lub zmiany uprawnień i zniszczenia starej sesji. (Upewnij się, aby zapisać zmiany z$_SESSION
użyciemsession_write_close
wcześniej Jeśli chcesz zachować sesję skojarzoną ze starym identyfikatorem, wygenerowaniem identyfikatora; w przeciwnym razie te zmiany wpłyną tylko na sesję z nowym identyfikatorem).źródło
Żetony, o których wspomniałeś, są jednorazowymi numerami. Niekoniecznie muszą być używane tylko raz, ale im dłużej są używane, tym większe jest prawdopodobieństwo, że nonce można przechwycić i wykorzystać do przejęcia sesji.
Inną wadą wartości nonces jest to, że bardzo trudno jest zbudować system, który ich używa i zezwala na wiele równoległych okien w tej samej formie. np. użytkownik otwiera dwa okna na forum i zaczyna pracę nad dwoma postami:
Jeśli nie masz możliwości śledzenia wielu okien, zachowasz tylko jedną wartość jednorazową - wartość okna B / Q. Gdy użytkownik następnie prześle swój post z okna A i przejdzie jednorazowo „P”, system ten odrzuci wiadomość jako
P != Q
.źródło
Nie czytałem artykułu Shiflett, ale myślę, że coś źle zrozumiałeś.
Domyślnie PHP przekazuje token sesji w adresie URL, gdy klient nie akceptuje plików cookie. W najczęstszym przypadku token sesji jest przechowywany jako plik cookie.
Oznacza to, że jeśli umieścisz token sesji w adresie URL, PHP rozpozna go i spróbuje go później użyć. Naprawianie sesji ma miejsce, gdy ktoś tworzy sesję, a następnie nakłania innego użytkownika do współużytkowania tej samej sesji, otwierając adres URL zawierający token sesji. Jeśli użytkownik uwierzytelnia się w jakiś sposób, złośliwy użytkownik zna token sesji uwierzytelnionego użytkownika, który może mieć różne uprawnienia.
Jak na pewno Shiflett wyjaśnia, zwykłą czynnością jest ponowne generowanie innego tokena za każdym razem, gdy zmieniają się uprawnienia użytkownika.
źródło
Tak, możesz zapobiec utrwalaniu sesji, ponownie generując identyfikator sesji po zalogowaniu. W ten sposób, jeśli atakujący nie będzie znał wartości cookie nowo uwierzytelnionej sesji. Inne podejście, które całkowicie zatrzymuje problem, jest ustawione
session.use_only_cookies=True
w konfiguracji środowiska wykonawczego. Osoba atakująca nie może ustawić wartości pliku cookie w kontekście innej domeny. Fiksacja sesji polega na wysłaniu wartości pliku cookie jako GET lub POST.źródło