Token CSRF jest potrzebny podczas korzystania z uwierzytelniania bezstanowego (= bezsesyjnego)?

125

Czy konieczne jest stosowanie ochrony CSRF, gdy aplikacja opiera się na uwierzytelnianiu bezstanowym (przy użyciu czegoś takiego jak HMAC)?

Przykład:

  • Mamy jedną aplikację, stronę (w przeciwnym razie mamy do dołączania żeton na każdym linku: <a href="...?token=xyz">...</a>.

  • Użytkownik uwierzytelnia się za pomocą POST /auth. Po pomyślnym uwierzytelnieniu serwer zwróci pewien token.

  • Token będzie przechowywany za pośrednictwem JavaScript w jakiejś zmiennej wewnątrz aplikacji pojedynczej strony.

  • Ten token będzie używany do uzyskiwania dostępu do ograniczonych adresów URL, takich jak /admin.

  • Token będzie zawsze przesyłany w nagłówkach HTTP.

  • NIE ma sesji HTTP ani plików cookie.

O ile rozumiem, nie powinno być (?!) możliwości stosowania ataków między witrynami, ponieważ przeglądarka nie przechowuje tokena, a co za tym idzie, nie może automatycznie wysłać go na serwer (tak by się stało, gdybyśmy korzystali z Cookies / Sesja).

Czy coś mi brakuje?

Benjamin M.
źródło
6
Uważaj na Basic Auth. Wiele przeglądarek automatycznie wysyła podstawowe nagłówki uwierzytelniania do końca sesji. Może to spowodować, że podstawowe uwierzytelnianie będzie tak samo podatne na CSRF jak uwierzytelnianie plików cookie.
typy

Odpowiedzi:

159

Znalazłem informacje o tym, że CSRF + nie używa plików cookie do uwierzytelniania:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    „ponieważ nie korzystasz z plików cookie, nie musisz chronić się przed żądaniami z innych witryn”

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    „Jeśli skorzystamy z plików cookie, naprawdę musisz wykonać CSRF, aby uniknąć żądań między witrynami. To jest coś, co możemy zapomnij o używaniu JWT, jak zobaczysz ”.
    (JWT = Json Web Token, uwierzytelnianie oparte na tokenach dla aplikacji bezstanowych)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    „Najłatwiejszym sposobem na uwierzytelnienie bez ryzyka podatności CSRF jest unikanie używania plików cookie do identyfikacji użytkownika "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    „Największym problemem związanym z CSRF jest to, że pliki cookie nie zapewniają absolutnie żadnej ochrony przed tego typu atakami. Jeśli używasz uwierzytelniania plików cookie musisz również zastosować dodatkowe środki w celu ochrony przed CSRF. Najbardziej podstawowym środkiem ostrożności, jaki możesz podjąć, jest upewnienie się, że aplikacja nigdy nie wywoła żadnych skutków ubocznych w odpowiedzi na żądania GET. "

Jest o wiele więcej stron, które stwierdzają, że nie potrzebujesz żadnej ochrony CSRF, jeśli nie używasz plików cookie do uwierzytelniania. Oczywiście nadal możesz używać plików cookie do wszystkiego innego, ale unikaj przechowywania czegoś takiego w session_idśrodku.


Jeśli chcesz zapamiętać użytkownika, masz dwie możliwości:

  1. localStorage: Magazyn wartości klucza w przeglądarce. Zapisane dane będą dostępne nawet po zamknięciu przez użytkownika okna przeglądarki. Dane nie są dostępne dla innych stron internetowych, ponieważ każda witryna ma własne miejsce.

  2. sessionStorage: Również magazyn danych w przeglądarce. Różnica polega na tym, że: dane są usuwane, gdy użytkownik zamyka okno przeglądarki. Jest to jednak przydatne, jeśli Twoja aplikacja internetowa składa się z wielu stron. Możesz więc wykonać następujące czynności:

    • Użytkownik loguje się, a następnie zapisujesz token sessionStorage
    • Użytkownik klika link, który ładuje nową stronę (= prawdziwy link, bez zastępowania treści javascript)
    • Nadal możesz uzyskać dostęp do tokena z sessionStorage
    • Aby się wylogować, możesz ręcznie usunąć token z sessionStoragelub poczekać, aż użytkownik zamknie okno przeglądarki, co spowoduje wyczyszczenie wszystkich zapisanych danych.

(dla obu zajrzyj tutaj: http://www.w3schools.com/html/html5_webstorage.asp )


Czy są jakieś oficjalne standardy autoryzacji tokena?

JWT (Json Web Token): Myślę, że to wciąż szkic, ale jest już używany przez wiele osób, a koncepcja wygląda na prostą i bezpieczną. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
Istnieją również biblioteki wielu dostępnych frameworków. Po prostu wygoogluj to!

Benjamin M.
źródło
37
Świetne podsumowanie CSRF! Zwrócę uwagę, że przechowywanie twoich tokenów w localStorage lub sessionStorage jest podatne na ataki XSS i że dane mogą być przeglądane przez skrypty na stronie - więc jeśli masz zainfekowany skrypt obsługiwany z CDN lub jeśli w jednym z twoich Biblioteki JS mogą ukraść token z tych miejsc przechowywania. Zobacz: stormpath.com/blog/… Myślę, że najbezpieczniejszym podejściem jest przechowywanie tokenu JWT + CSRF w pliku cookie, a następnie umieszczenie obliczonego tokena JWT z tokenem CSRF wewnątrz niego w nagłówku żądania.
Aaron Grey
W odniesieniu do: „Najbardziej podstawowym środkiem ostrożności, jaki można podjąć, jest upewnienie się, że aplikacja nigdy nie wykonuje żadnych skutków ubocznych w odpowiedzi na żądania GET”. Czy atak CSRF może sfałszować żądanie POST?
Costa
W zależności od aplikacji po stronie serwera może to być możliwe. Istnieją frameworki internetowe, które używają czegoś takiego jak http://.../someRestResource?method=POST. Jest to więc w zasadzie GETżądanie, ale aplikacja serwera interpretuje je jako POSTżądanie, ponieważ została skonfigurowana do używania methodparametru zamiast nagłówka HTTP. ...Jeśli chodzi o popularne przeglądarki internetowe, egzekwują one zasady tego samego pochodzenia i wykonują GETżądania tylko do serwerów zagranicznych. Chociaż może być możliwe wykonywanie POSTżądań, jeśli przeglądarka internetowa nie stosuje tych standardów sieciowych (błąd, złośliwe oprogramowanie).
Benjamin M
1
Dodatek do Server Side App: Nadal nie jest możliwe wysłanie treści żądania, ponieważ popularne przeglądarki na to nie pozwalają. Jeśli jednak aplikacja serwera na to zezwala method=POST, może również zezwolić body={someJson}na przesłonięcie domyślnej treści żądania. To naprawdę zły projekt API i niezwykle ryzykowny. Chociaż jeśli Twoja aplikacja serwerowa na to pozwala http://...?method=POST&body={someJson}, powinieneś naprawdę przemyśleć, co tam zrobiłeś, dlaczego i czy w ogóle jest to konieczne. (Powiedziałbym, że w 99,9999% przypadków nie jest to konieczne). Ponadto przeglądarki mogą w ten sposób wysyłać tylko kilka kilobajtów.
Benjamin M
@BenjaminM zauważył, że zasady Same Origin chronią tylko przed dostępem kodu javaScript do wyniku, więc gdy żądanie jest „zablokowane”, faktycznie dociera do serwera - jsbin.com/mewaxikuqo/edit?html,js,output Testowałem to tylko na firefoxie, ale możesz otworzyć narzędzia deweloperskie i zobaczyć, że nawet jeśli otrzymujesz „Zablokowano żądanie między źródłami”, zdalny serwer faktycznie widzi całe żądanie. dlatego musisz mieć tokeny lub niestandardowe nagłówki (i jeśli to możliwe oba) do wszystkich swoich żądań POST
Yoni Jah
59

TL; DR

JWT, jeśli jest używany bez plików cookie, neguje potrzebę tokena CSRF - ALE! przechowując token JWT w session / localStorage, ujawniasz swój token JWT i tożsamość użytkownika, jeśli witryna ma lukę w zabezpieczeniach XSS (dość powszechną). Lepiej jest dodać csrfTokenklucz do tokena JWT i przechowywać go w pliku cookie z ustawionymi atrybutami securei http-only.

Przeczytaj ten artykuł z dobrym opisem, aby uzyskać więcej informacji https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Możesz uczynić tę ochronę CSRF bezstanową, dołączając żądanie xsrfToken JWT:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Będziesz więc musiał przechowywać csrfToken w localStorage / sessionStorage, a także w samym JWT (który jest przechowywany w bezpiecznym pliku cookie obsługującym tylko protokół http). Następnie w celu ochrony csrf sprawdź, czy token csrf w tokenie JWT jest zgodny z przesłanym nagłówkiem csrf-token.

Scott Jungwirth
źródło
2
Czy należy zwolnić z używania tokenu csrf podczas uwierzytelniania użytkownika za pomocą interfejsu API?
user805981
3
Warto zwrócić uwagę (jak inni również wspominali w komentarzach do linku źródłowego), że wszelkie środki zaradcze CSRF, które wykorzystują a) pliki cookie, które nie są tylko http lub b) przechowują token CSRF w lokalnej pamięci, są podatne na XSS. Oznacza to, że przedstawione podejście może pomóc w utrzymaniu JWT w tajemnicy przed atakującym za pomocą XSS, ale atakujący nadal byłby w stanie wykonać złośliwe żądanie w Twoim API, ponieważ jest w stanie dostarczyć prawidłowy JWT (poprzez plik cookie, przeglądarka z podziękowaniami) i token CSRF (odczyt przez wstrzyknięty JS z lokalnej pamięci / pliku cookie).
Johannes Rudolph
1
W rzeczywistości nawet token CSRF nie może Cię chronić na tym poziomie XSS, ponieważ zakładasz, że atakujący może uzyskać dostęp do localStorage, co jest obecnie jedynym sposobem uzyskania dostępu do poziomu skryptu, do którego i tak może spojrzeć na token CSRF .
nieważny
1
Czy nie to właśnie mówił @JohannesRudolph? Gdy tylko zapiszesz token CSRF w Web Storage / plik cookie inny niż HTTP, zwiększasz swój ślad ataku XSS, ponieważ są one dostępne za pośrednictwem JS.
adam-beck
1
Nie jestem tutaj ekspertem, ale jeśli nadal jesteś narażony na XSS, tak jak na początku, nie jestem pewien, czy część lepiej jest dodać ... naprawdę się trzyma. Prawdopodobnie trochę (?) Bardziej skomplikowane jest zdobycie tokena CSRF przez napastnika, ale na końcu nadal jest w stanie wykonać żądanie w Twoim imieniu, nawet bez znajomości tokena JWT. Czy to jest poprawne? Dzięki
superjos