Gdzie przechowywać JWT w przeglądarce? Jak chronić się przed CSRF?

159

Znam uwierzytelnianie oparte na plikach cookie. Flaga SSL i HttpOnly może być stosowana do ochrony uwierzytelniania opartego na plikach cookie przed MITM i XSS. Jednak konieczne będzie zastosowanie bardziej specjalnych środków w celu ochrony przed CSRF. Są po prostu trochę skomplikowane. ( odniesienie )

Ostatnio odkryłem, że JSON Web Token (JWT) jest dość popularny jako rozwiązanie do uwierzytelniania. Znam się na kodowaniu, dekodowaniu i weryfikacji JWT. Jednak nie rozumiem, dlaczego niektóre strony internetowe / samouczki nie wymagają ochrony CSRF, jeśli używany jest JWT. Dużo czytałem i próbuję podsumować poniższe problemy. Chcę tylko, żeby ktoś przedstawił duży obraz JWT i wyjaśnił koncepcje, które źle zrozumiałem o JWT.

  1. Jeśli token JWT jest przechowywany w pliku cookie, myślę, że jest to to samo, co uwierzytelnianie oparte na plikach cookie, z wyjątkiem tego, że serwer nie musi mieć sesji, aby zweryfikować plik cookie / token. Wciąż istnieje ryzyko związane z CSRF, jeśli nie zostanie wdrożony żaden specjalny środek. Czy JWT nie jest przechowywany w pliku cookie?

  2. Jeśli token JWT jest przechowywany w localStorage / sessionStorage, nie ma plików cookie, więc nie ma potrzeby ochrony przed CRSF. Pytanie brzmi, jak wysłać token JWT do serwera. Znalazłem tutaj sugestie używania jQuery do wysyłania JWT przez nagłówek HTTP żądań ajax. Czyli tylko żądania AJAX mogą przeprowadzić uwierzytelnianie?

  3. Znalazłem też jeszcze jeden program na blogu , w którym do wysyłania tokena JWT używano „nagłówka autoryzacji” i „okaziciela”. Nie rozumiem metody, o której mówi blog. Czy mógłby ktoś wyjaśnić więcej na temat „nagłówka autoryzacji” i „okaziciela”? Czy to sprawia, że ​​token JWT jest przesyłany przez nagłówek HTTP WSZYSTKICH żądań? Jeśli tak, co powiesz na CSRF?

Przestrzeń czasowa7
źródło

Odpowiedzi:

70

Tokeny JWT są popularne, ponieważ są używane jako domyślny format tokenu w nowych protokołach autoryzacji i uwierzytelniania, takich jak OAuth 2.0 i OpenID Connect .

Gdy token jest przechowywany w pliku cookie, przeglądarka automatycznie wyśle ​​go wraz z każdym żądaniem do tej samej domeny i nadal jest podatny na ataki CSRF.

Uwierzytelnianie okaziciela jest jednym ze schematów uwierzytelniania zdefiniowanych w protokole HTTP. Zasadniczo oznacza to, że YOUtoken (JWT) należy umieścić w nagłówku HTTP Authorization żądania. Przeglądarka NOTzrobi to automatycznie, więc nie nadaje się do ochrony Twojej witryny. Ponieważ przeglądarka nie dodaje automatycznie nagłówka do żądania, nie jest narażona na atak CSRF, który zależy od automatycznego przesłania informacji uwierzytelniających do oryginalnej domeny.

Schemat nośnika jest często używany do ochrony internetowych interfejsów API (usług REST), które są używane przez wywołania AJAX lub od klientów mobilnych.

MvdD
źródło
1
@ Timespace7 Nie, tokeny JWT są również często używane przez klientów natywnych. OAuth 2.0 ma przepływy przeznaczone specjalnie dla klientów natywnych (mobilnych). To, czego nie robią, to niejawne uwierzytelnianie przeglądarki (takie jak pliki cookie lub podstawowe uwierzytelnianie).
MvdD
5
Mówię, że jeśli twoje API pobiera token JWT tylko z nagłówka Authorization, nie jest podatny na CSRF. Każda witryna lub interfejs API, który pobiera token z pliku cookie, wymaga ograniczenia CSRF.
MvdD
13
Czy to oznacza, że ​​możemy efektywnie przechowywać jwt w ciasteczku i będzie bezpieczne, jeśli wyślemy z nim żądania w nagłówku Authorization?
cameronroe
10
@cameronjroe możesz przechowywać je w swoich plikach cookie, ale tylko wtedy, gdy nie używasz plików cookie do uwierzytelniania (w tym przypadku używasz nagłówków)
Jaakko
1
Połączenia AJAX również pochodzą z przeglądarki. Tokeny JWT są głównie używane do uwierzytelniania internetowych interfejsów API (udostępniania danych) w porównaniu z plikami cookie używanymi do uwierzytelniania aplikacji internetowych (wyświetlanie znaczników, obrazów, CSS i JavaScript)
MvdD
144

Musimy przechowywać token JWT na komputerze klienckim. Jeśli przechowujemy go w LocalStorage / SessionStorage, może być łatwo przechwycony przez atak XSS. Jeśli przechowujemy go w plikach cookie, haker może go użyć (bez czytania) w ataku CSRF i podszyć się pod użytkownika oraz skontaktować się z naszym API i wysłać prośby o wykonanie działań lub uzyskanie informacji w imieniu użytkownika.

Istnieje jednak kilka sposobów zabezpieczenia tokenów JWT w plikach cookie, aby nie zostały łatwo skradzione (ale nadal istnieją zaawansowane techniki umożliwiające ich kradzież). Ale jeśli chcesz polegać na LocalStorage / SessionStorage, możesz uzyskać do niego dostęp za pomocą prostego ataku XSS.

Aby rozwiązać problem CSRF, używam Double Submit Cookies w mojej aplikacji.

Metoda podwójnego przesyłania plików cookie

  1. Przechowuj JWT w pliku cookie HttpOnly i używaj go w trybie bezpiecznym do przesyłania przez HTTPS.

  2. Większość ataków CSRF ma inne źródło lub nagłówek strony odsyłającej z oryginalnym hostem w żądaniach. Sprawdź więc, czy masz któreś z nich w nagłówku, czy pochodzą one z Twojej domeny, czy nie! Jeśli nie, odrzuć je. Jeśli w żądaniu nie ma zarówno źródła, jak i strony odsyłającej, nie martw się. Możesz polegać na wynikach walidacji nagłówka X-XSRF-TOKEN, które wyjaśnię w następnym kroku.

  3. Chociaż przeglądarka automatycznie dostarcza pliki cookie dla domeny żądania, istnieje jedno przydatne ograniczenie: kod JavaScript uruchomiony na stronie internetowej nie może odczytać plików cookie innych witryn. Możemy to wykorzystać do stworzenia naszego rozwiązania CSRF. Aby zapobiec atakom CSRF, musimy utworzyć dodatkowy czytelny plik cookie JavaScript o nazwie: XSRF-TOKEN. Ten plik cookie musi zostać utworzony, gdy użytkownik jest zalogowany i powinien zawierać losowy, niemożliwy do odgadnięcia ciąg. Zapisujemy również ten numer w samym JWT jako roszczenie prywatne. Za każdym razem, gdy aplikacja JavaScript chce wysłać żądanie, będzie musiała odczytać ten token i wysłać go w niestandardowym nagłówku HTTP. Ponieważ te operacje (odczyt pliku cookie, ustawienie nagłówka) można wykonać tylko w tej samej domenie aplikacji JavaScript,

Angular JS ułatwia życie

Na szczęście używam Angular JS w naszej platformie, a Angular pakuje podejście tokenowe CSRF, co ułatwia nam wdrożenie. Na każde żądanie, które nasza aplikacja Angular wysyła do serwera, $httpusługa Angular automatycznie wykona te czynności:

  • Poszukaj pliku cookie o nazwie XSRF-TOKEN w bieżącej domenie.
  • Jeśli ten plik cookie zostanie znaleziony, odczytuje wartość i dodaje ją do żądania jako nagłówek X-XSRF-TOKEN.

W ten sposób implementacja po stronie klienta jest obsługiwana automatycznie! Musimy tylko ustawić plik cookie nazwany XSRF-TOKENna bieżącej domenie po stronie serwera, a kiedy nasze API otrzyma jakiekolwiek wywołanie od klienta, musi sprawdzić X-XSRF-TOKENnagłówek i porównać je z XSRF-TOKENtokenem JWT. Jeśli pasują, to użytkownik jest prawdziwy. W przeciwnym razie jest to sfałszowane żądanie i możesz je zignorować. Ta metoda jest inspirowana metodą „Double Submit Cookie”.

Uwaga

W rzeczywistości nadal jesteś podatny na XSS, po prostu atakujący nie może ukraść Twojego tokena JWT do późniejszego wykorzystania, ale nadal może wysyłać żądania w imieniu użytkowników za pomocą XSS.

Niezależnie od tego, czy przechowujesz swój localStoragetoken JWT w pliku cookie, czy też przechowujesz swój token XSRF w pliku cookie innym niż HttpOnly, XSS może je łatwo pobrać. Nawet twój token JWT w pliku cookie HttpOnly może zostać przechwycony przez zaawansowany atak XSS, taki jak metoda XST .

Dlatego oprócz metody Double Submit Cookies, należy zawsze przestrzegać najlepszych praktyk przeciwko XSS, w tym zawartości ucieczki. Oznacza to usunięcie dowolnego wykonywalnego kodu, który spowodowałby, że przeglądarka zrobiłaby coś, czego nie chcesz. Zwykle oznacza to usunięcie // <![CDATA[tagów i atrybutów HTML, które powodują ocenę kodu JavaScript.

Przeczytaj więcej tutaj:

Iman Sedighi
źródło
1
@AranDehkharghani tak, wydaje mi się, że zapobiega to atakowi typu replay, zwłaszcza jeśli zmienisz JWT i wygaśniesz poprzedni JWT za każdym razem, gdy jest używany przez API. oznacza to, że Twój token JWT stanie się jednorazowym hasłem (OTP). Możesz używać JWT na różne sposoby, w zależności od tego, jak bardzo zależy Ci na bezpieczeństwie na Twojej platformie.
Iman Sedighi
7
Jak wspomniałeś, jeśli witryna jest podatna na XSS, to tylko kwestia czasu, zanim użytkownik zostanie wykorzystany. Wygląda na to, że handlujemy znaczną złożonością za bardzo mały wzrost bezpieczeństwa.
shusson
3
@shusson Musisz zadbać o ataki XSS i XSRF, aby chronić swój JWT. Nie zgadzam się, że handlujesz znaczną złożonością za bardzo mały wzrost bezpieczeństwa. Jeśli bezpieczeństwo ma znaczenie, musisz dołożyć wszelkich starań, aby nie mieć luk w zabezpieczeniach XSS. Ta metoda ma na celu ochronę tokenu przed atakami XSRF. ale to nie znaczy, że możesz ignorować luki w zabezpieczeniach XSS.
Iman Sedighi,
5
@ImanSedighi Nie było jasne, przechowując jwt w pliku cookie, dodajesz złożoność i musisz teraz chronić przed XSRF. Dlaczego więc nie skorzystać po prostu z lokalnego magazynu z tokenami o krótkiej żywotności i skoncentrować się na zapobieganiu XSS?
shusson
2
@Royi Namir: Spoofing przez Wireshark nie powinien być problemem, jeśli używasz certyfikatu SSL o wartości 10 USD! Jeśli bezpieczeństwo strony jest ważne, należy zaszyfrować dane i skorzystać z protokołu HTTPS.
Iman Sedighi,
2

Inny punkt widzenia na całą kwestię przechowywania tokenów JWT:

  1. JWT nigdy nie powinny być przechowywane w lokalnym magazynie
  2. W rzeczywistości nie powinny one być nawet przechowywane w plikach cookie , chyba że jesteś w stanie zaimplementować bardzo ścisłą ochronę CSRF

Sprawdź to dla motywacji

  • JWT jako id_token jest jak poświadczenia użytkownika
  • JWT jako access_token jest jak token sesji

Najbezpieczniejszą opcją jest w pamięci . Sprawdź to na głębokie nurkowanie

człowiek
źródło