Czy przechowywanie pliku jwt w localStorage za pomocąreakjs jest bezpieczne?

147

Obecnie tworzę aplikację jednostronicową przy użyciureakjs. Czytałem, że wiele powodów, dla których nie używam localStorage, wynika z luk w zabezpieczeniach XSS. Skoro React wymyka wszystkie dane wejściowe użytkownika, czy teraz byłoby bezpiecznie używać localStorage?

Kaloyan Kosev
źródło
4
wolisz przechowywanie sesji
Praneet Rohida
3
„Zaleca się, aby nie przechowywać żadnych poufnych informacji w pamięci lokalnej”. -OWASP "przechowuj je w pamięci bez żadnej trwałości" -Auth0
avejidah
Myślę, że Auth0 mogło zmienić swoje spojrzenie na to - ponieważ nie mogę znaleźć powyższego cytatu w podanym linku
DauleDK

Odpowiedzi:

141

W większości nowoczesnych aplikacji jednostronicowych rzeczywiście musimy przechowywać token gdzieś po stronie klienta (najczęstszy przypadek użycia - aby użytkownik był zalogowany po odświeżeniu strony).

Dostępne są łącznie 2 opcje: przechowywanie w sieci Web (przechowywanie sesji, pamięć lokalna) i plik cookie po stronie klienta. Obie opcje są szeroko stosowane, ale nie oznacza to, że są bardzo bezpieczne.

Tom Abbott dobrze podsumowuje sesję JWT sessionStorage i localStorage security :

Magazyn sieciowy (localStorage / sessionStorage) jest dostępny za pośrednictwem JavaScript w tej samej domenie. Oznacza to, że każdy skrypt JavaScript działający w Twojej witrynie będzie miał dostęp do pamięci sieciowej iz tego powodu może być podatny na ataki typu cross-site scripting (XSS) . Krótko mówiąc, XSS to rodzaj luki, w której osoba atakująca może wstrzyknąć JavaScript, który będzie działał na Twojej stronie. Podstawowe ataki XSS próbują wstrzyknąć JavaScript za pomocą danych wejściowych formularza, w których osoba atakująca umieszcza <script>alert('You are Hacked');</script>formularz, aby sprawdzić, czy jest uruchamiany przez przeglądarkę i czy może być przeglądany przez innych użytkowników.

Aby zapobiec XSS, typową odpowiedzią jest ucieczka i zakodowanie wszystkich niezaufanych danych. React (głównie) robi to za Ciebie! Oto świetna dyskusja na temat tego, za jaką ochronę przed lukami XSS odpowiada React .

Ale to nie obejmuje wszystkich możliwych luk! Innym potencjalnym zagrożeniem jest użycie JavaScript hostowanego w sieciach CDN lub poza infrastrukturą .

Oto znowu Tom:

Nowoczesne aplikacje internetowe obejmują zewnętrzne biblioteki JavaScript do testowania A / B, analizy ścieżek / rynku i reklam. Używamy menedżerów pakietów, takich jak Bower, do importowania kodu innych osób do naszych aplikacji.

Co się stanie, jeśli tylko jeden z używanych przez Ciebie skryptów zostanie przejęty? Na stronie może zostać osadzony złośliwy kod JavaScript, co spowoduje zagrożenie dla magazynu internetowego. Tego typu ataki XSS mogą uzyskać dostęp do Web Storage każdego, kto odwiedza Twoją witrynę, bez ich wiedzy. Prawdopodobnie dlatego wiele organizacji zaleca, aby nie przechowywać niczego wartościowego ani nie ufać żadnym informacjom w pamięci sieciowej. Obejmuje to identyfikatory sesji i tokeny.

Dlatego dochodzę do wniosku, że Web Storage jako mechanizm przechowywania nie wymusza żadnych bezpiecznych standardów podczas przesyłania . Ktokolwiek czyta Web Storage i korzysta z niego, musi dołożyć wszelkich starań, aby zawsze wysyłać token JWT przez HTTPS, a nigdy przez HTTP.

Kaloyan Kosev
źródło
10
Więc jeśli dobrze Cię rozumiem, polecasz ciasteczka? Tylko dla pewności. Dzięki!
SuperLemon,
7
Tak. Polecam pliki cookie ze względu na dodatkowe bezpieczeństwo, które zapewniają oraz prostotę ochrony przed CSRF za pomocą nowoczesnych frameworków internetowych. Web Storage (localStorage / sessionStorage) jest podatny na XSS, ma większą powierzchnię ataku i może mieć wpływ na wszystkich użytkowników aplikacji po udanym ataku.
Kaloyan Kosev
48
Myślę, że to pomieszałeś? Nowoczesne frameworki internetowe mają silną wbudowaną ochronę dla XSS. Ale nie tak bardzo w przypadku xsrf. Najlepszą obroną przed xsrf jest całkowite unikanie używania plików cookie. Lokalny magazyn jest przypisany do określonej domeny, co oznacza, że ​​domena atakującego nie może uzyskać do niego dostępu. Struktury internetowe chronią przed xss, automatycznie kodując i oczyszczając dane wejściowe użytkownika. Zobacz angular.io/guide/security
mikejones1477
47
Jeśli „polecasz ciasteczka [zamiast]”, to czy mogę polecić, abyś powiedział to gdzieś w odpowiedzi? A nie tylko w komentarzach?
przemówienie
7
Jestem tu trochę spóźniony, właśnie czytam teraz te tematy i jestem zdezorientowany co do jednej rzeczy, wiele osób mówi o tym, że jesteś chroniony za pomocą pliku cookie typu http, jeśli jesteś skompromitowany z Xss, ale jeśli masz xss Ataker nie musi niczego kraść, może po prostu zrobić post ze strony, aby podszyć się pod Ciebie za pomocą tego pliku cookie (nawet jeśli nie może go ukraść). Czy coś mi brakuje ???
Borja Alvarez
35

Wiem, że to stare pytanie, ale zgodnie z tym, co powiedział @ mikejones1477, nowoczesne biblioteki i frameworki interfejsu użytkownika wymykają się z tekstu, zapewniając ochronę przed XSS. Powodem, dla którego pliki cookie nie są bezpieczną metodą używającą poświadczeń, jest to, że pliki cookie nie zapobiegają CSRF, gdy robi to localStorage (pamiętaj również, że pliki cookie są również dostępne przez javascript, więc XSS nie jest tutaj dużym problemem), ta odpowiedź wznawia dlaczego .

Powodem przechowywania tokena uwierzytelniającego w lokalnej pamięci i ręcznego dodawania go do każdego żądania zabezpieczającego przed CSRF jest to słowo kluczowe: manual. Ponieważ przeglądarka nie wysyła automatycznie tego tokena autoryzacji, jeśli odwiedzę evil.com i uda jej się wysłać POST http://example.com/delete-my-account , nie będzie w stanie wysłać mojego tokena autoryzacji, więc żądanie jest ignorowane.

Oczywiście httpOnly jest świętym Graalem, ale nie możesz uzyskać dostępu zreakjs ani żadnego frameworka js, poza tym nadal masz lukę w zabezpieczeniach CSRF. Moją rekomendacją byłoby przechowywanie lokalne lub jeśli chcesz używać plików cookie, upewnij się, że zaimplementujesz jakieś rozwiązanie problemu CSRF, tak jak robi to django .

Jeśli chodzi o CDN, upewnij się, że nie używasz dziwnych CDN, na przykład CDN, takich jak Google lub Bootstrap, są obsługiwane przez społeczność i nie zawierają złośliwego kodu, jeśli nie masz pewności, możesz je przejrzeć.

Mauricio Cortazar
źródło
2
Nie jestem pewien, dlaczego powiedziałbyś, że nadal jesteś podatny na CSRF podczas korzystania z plików cookie. Korzystanie z pliku cookie z flagami HttpOnly SameSite=stricti secure, zapewni bezpieczeństwo informacji ustawionych w plikach cookie. Następnie w przypadku XSS po prostu upewnij się, że Twój JavaScript nie zna żadnych danych związanych z uwierzytelnianiem, takich jak tokeny i hasła (co oznacza, że ​​nie przechowuj ich w Web Storage) - jeśli zaimportujesz złośliwy skrypt, ten skrypt nie będzie miał dostępu wrażliwych danych. Tak, nie będziesz mieć również dostępu do tokena przez JS, ale to naprawdę nie powinno stanowić problemu.
miphe
@miphe, to właśnie powiedziałem. Ale OP prosi o sposób na dostęp z javascript. Tutaj tylko wyjaśniam, jaki jest najlepszy sposób przechowywania tokena dostępnego z js.
Mauricio Cortazar
21

Zasadniczo można przechowywać swój token JWT w lokalnym magazynie.

Myślę, że to dobry sposób. Jeśli mówimy o XSS, XSS używającym CDN, istnieje również potencjalne ryzyko uzyskania loginu / przepustki klienta. Przechowywanie danych w pamięci lokalnej zapobiegnie przynajmniej atakom CSRF.

Musisz być świadomy obu i wybrać to, czego chcesz. Oba ataki to nie wszystko, o czym musisz wiedzieć, pamiętaj tylko: CAŁA APLIKACJA JEST TYLKO TAK BEZPIECZNA JAK NAJMNIEJ BEZPIECZNY PUNKT TWOJEJ APLIKACJI.

Po raz kolejny przechowywanie jest OK, bądź podatny na XSS, CSRF, ... nie jest

Alex Lyalka
źródło
2
Dlatego bezpieczne jest wykonanie następujących czynności: - Przechowywanie tokena JWT w pliku cookie, aby nie można go było pobrać z XSS - Przechowywanie tokena CSRF w localStorage, aby nie można go było pobrać z CSRF
Alejandro Cavazos
33
Dajesz dobry punkt: jeśli Twoja witryna uruchamia złośliwy skrypt, gra i tak się kończy. Mogą po prostu powiązać zdarzenia keydown z danymi wejściowymi typu password i wykraść w ten sposób informacje uwierzytelniające użytkownika (co jest dużo, dużo gorsze niż kradzież tokena autoryzacji JWT). Przechowywanie tokenów JWT w localStorage nie zwiększa już i tak ogromnych możliwych uszkodzeń spowodowanych przez XSS.
Carl Leth
8

Nie jest bezpieczne, jeśli używasz sieci CDN:

Na stronie może zostać osadzony złośliwy kod JavaScript, co spowoduje zagrożenie dla magazynu internetowego. Tego typu ataki XSS mogą uzyskać dostęp do Web Storage każdego, kto odwiedza Twoją witrynę, bez ich wiedzy. Prawdopodobnie dlatego wiele organizacji zaleca, aby nie przechowywać niczego wartościowego ani nie ufać żadnym informacjom w pamięci sieciowej. Obejmuje to identyfikatory sesji i tokeny.

via stormpath

Każdy skrypt, którego potrzebujesz z zewnątrz, może zostać potencjalnie naruszony i może pobrać dowolny JWTS z pamięci klienta i wysłać dane osobowe z powrotem na serwer atakującego.

Stephen L.
źródło
6
Jeśli nie planuję używać cdns, czy będzie to bezpieczne?
1
Autor artykułu nigdy nie rozróżniał między XSS w witrynach obsługiwanych przez CDN lub bezpośrednio z centralnego serwera. Czy twoje wyjaśnienie tutaj nie odnosi się również ogólnie, nie tylko do CDN?
Vlad,
5

Localstorage jest zaprojektowany tak, aby był dostępny przez javascript, więc nie zapewnia żadnej ochrony przed XSS. Jak wspomniano w innych odpowiedziach, istnieje kilka możliwych sposobów przeprowadzenia ataku XSS, przed którym magazyn lokalny nie jest domyślnie chroniony.

Jednak pliki cookie mają flagi bezpieczeństwa, które chronią przed atakami XSS i CSRF. Flaga HttpOnly uniemożliwia dostęp javascript po stronie klienta do pliku cookie, flaga Secure pozwala przeglądarce tylko na przesyłanie pliku cookie za pośrednictwem protokołu SSL, a flaga SameSite zapewnia, że ​​plik cookie jest wysyłany tylko do źródła. Chociaż właśnie sprawdziłem, a SameSite jest obecnie obsługiwane tylko w Operze i Chrome, więc do ochrony przed CSRF lepiej jest użyć innych strategii. Na przykład wysłanie zaszyfrowanego tokena w innym pliku cookie z niektórymi publicznymi danymi użytkownika.

Dlatego pliki cookie są bezpieczniejszym sposobem przechowywania danych uwierzytelniających.

Ivan
źródło
nie mogę uzyskać: w jaki sposób HttpOnly może chronić Cię przed CSRF?
Alex Lyalka
@AlexLyalka Nie chciałem powiedzieć, że HttpOnly zapobiega CSRF, a nie wszystkie flagi plików cookie razem mogą chronić przed XSS i CSRF. SameSite zapewnia pewną ochronę, zapobiegając wysyłaniu plików cookie do witryny innej niż pochodzenie. Chociaż właśnie sprawdziłem i wsparcie dla tej flagi jest bardzo niskie. Możliwe jest również uniknięcie CSRF za pomocą oddzielnego zaszyfrowanego tokena z pewną identyfikacją użytkownika, który jest sprawdzany na serwerze.
Ivan
1
Cóż, jeśli ktoś może wykonać kod w Twojej sieci, czy nie może po prostu opublikować posta w Twojej sieci w imieniu użytkownika? Ok, nie może dostać twoich plików cookie tylko z http, ale może dzwonić za pomocą tych plików cookie, więc nadal nie widzę sensu
Borja Alvarez
2
@BorjaAlverez Jest duża różnica. Tak, przez XSS ktoś mógłby wysyłać żądania w imieniu zalogowanego użytkownika, ale włamanie do tokena jest gorsze. Na przykład: token może zapewniać dostęp do interfejsów API, których aplikacja kliencka nie używa; token może zawierać inne informacje o użytkowniku (adres e-mail, profil i granty); token może zostać użyty w atakach typu replay na twoją aplikację; token może zostać przekazany id_token_hintdo serwera uwierzytelniania OIDC; token dostarcza atakującemu informacji o szyfrze, który został użyty do jego podpisania; itd.
avejidah
3

Sposobem na przyjrzenie się temu jest rozważenie poziomu ryzyka lub szkody.

Czy tworzysz aplikację bez użytkowników, POC / MVP? Czy jesteś startupem, który musi szybko wejść na rynek i przetestować swoją aplikację? Jeśli tak, prawdopodobnie wdrożyłbym najprostsze rozwiązanie i skupiłbym się na znalezieniu produktu dopasowanego do rynku. Użyj localStorage, ponieważ często jest łatwiejszy do wdrożenia.

Czy tworzysz wersję 2 aplikacji z wieloma codziennymi aktywnymi użytkownikami lub aplikację, od której ludzie / firmy są w dużym stopniu zależni. Czy włamanie oznaczałoby niewiele lub brak miejsca na powrót do zdrowia? Jeśli tak, przyjrzałbym się dokładnie twoim zależnościom i rozważał przechowywanie informacji o tokenach w pliku cookie obsługującym tylko protokół http.

Używanie zarówno localStorage, jak i przechowywania plików cookie / sesji ma swoje zalety i wady.

Jak stwierdzono w pierwszej odpowiedzi: Jeśli Twoja aplikacja ma lukę w zabezpieczeniach XSS, żadna z nich nie ochroni Twojego użytkownika. Ponieważ większość nowoczesnych aplikacji ma kilkanaście lub więcej różnych zależności, coraz trudniej jest zagwarantować, że jedna z zależności aplikacji nie jest podatna na XSS.

Jeśli Twoja aplikacja ma lukę w zabezpieczeniach XSS, a haker był w stanie ją wykorzystać, będzie mógł wykonywać działania w imieniu Twojego użytkownika. Haker może wykonywać żądania GET / POST, pobierając token z localStorage lub może wykonywać żądania POST, jeśli token jest przechowywany w pliku cookie obsługującym tylko protokół http.

Jedyną wadą przechowywania twojego tokena w lokalnej pamięci jest to, że haker będzie mógł odczytać twój token.

HenokG
źródło
1

Czy nie są akceptowane ani localStorage ani httpOnly cookie? Jeśli chodzi o zagrożoną bibliotekę innej firmy, jedyne znane mi rozwiązanie, które ograniczy / zapobiegnie kradzieży poufnych informacji, będzie egzekwowane integralność zasobów podrzędnych .

Subresource Integrity (SRI) to funkcja zabezpieczeń, która umożliwia przeglądarkom weryfikację, czy zasoby, które pobierają (na przykład z CDN), są dostarczane bez nieoczekiwanej manipulacji. Działa, umożliwiając podanie kryptograficznego skrótu, który musi być zgodny z pobieranym zasobem.

Dopóki zhakowana biblioteka innej firmy jest aktywna w Twojej witrynie, keylogger może zacząć zbierać informacje, takie jak nazwa użytkownika, hasło i cokolwiek innego wprowadzisz do witryny.

Plik cookie httpOnly uniemożliwi dostęp z innego komputera, ale nie zrobi nic, aby uniemożliwić hakerowi manipulowanie komputerem użytkownika.

CICHY
źródło
-10

Przechowywanie tokena w localStorage jest bezpieczne, o ile go zaszyfrujesz. Poniżej znajduje się skompresowany fragment kodu przedstawiający jeden z wielu sposobów, w jaki możesz to zrobić.

    import SimpleCrypto from 'simple-crypto-js';

    const saveToken = (token = '') => {
          const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
          const encryptedToken = encryptInit.encrypt(token);

          localStorage.setItem('token', encryptedToken);
     }

Następnie przed użyciem swojego tokena odszyfruj go za pomocą PRIVATE_KEY_STORED_IN_ENV_FILE

Kidali Kevin
źródło
@HassanAle jeśli nie masz tu sensu, nigdy nie będzie w 100% bezpiecznej aplikacji dowodowej, po prostu zmniejszasz powierzchnię ataku i przynajmniej plik env nie zostanie opublikowany bezpośrednio na githubie. Ponadto dołączony kod zostanie zaciemniony i zniekształcony, co utrudni atakującym ich znalezienie.
Kidali Kevin,
Klucz prywatny nie powinien być ujawniany. Naraziłbyś cały interfejs API.
Hassan Althaf
Z mojego doświadczenia Jeśli zrobiłeś coś inteligentnie i poprawnie, twój klucz prywatny nie zostanie ujawniony w twojej kompilacji produkcyjnej, jeśli tak, zrzut ekranu obsługujący ten lub nawet adres URL.
Kidali Kevin