Zrozumienie Tokena autentyczności Rails

Natrafiłem na pewne problemy dotyczące Tokena autentyczności w Rails, jak to już było wielokrotnie.

Ale naprawdę nie chcę po prostu rozwiązać tego problemu i iść dalej. Naprawdę chciałbym zrozumieć token autentyczności. Cóż, moje pytanie brzmi, Czy masz jakieś kompletne źródło informacji na ten temat, czy poświęciłbyś swój czas, aby wyjaśnić szczegółowo tutaj?

Author: Andrei Eliade, 2009-06-03

10 answers

Co się dzieje

Kiedy użytkownik wyświetla formularz, aby utworzyć, zaktualizować lub zniszczyć zasób, aplikacja rails tworzy losowy authenticity_token, przechowuje ten token w sesji i umieszcza go w ukrytym polu w formularzu. Kiedy użytkownik przesyła formularz, Rails szuka authenticity_token, porównuje go z tym zapisanym w sesji i jeśli pasują do żądania, może kontynuować.

Dlaczego tak się dzieje

Ponieważ token autentyczności jest przechowywany w sesji, klient nie może znać swojej wartości. Uniemożliwia to przesyłanie formularzy do aplikacji Rails bez przeglądania formularza w samej aplikacji. Wyobraź sobie, że korzystasz z usługi A, zalogowałeś się do usługi i wszystko jest w porządku. Teraz wyobraź sobie, że poszedłeś do korzystania z usługi B, i zobaczyłeś zdjęcie, które Ci się podoba, i nacisnąłeś na zdjęcie, aby zobaczyć większy rozmiar. Teraz, jeśli jakiś zły kod był tam w serwisie B, może wysłać żądanie do serwisu A (do którego jesteś zalogowany) i poprosić o usunięcie swojego konto, Wysyłając zapytanie do http://serviceA.com/close_account. Jest to coś, co jest znane jako CSRF (Cross Site Request Forgery) .

Jeśli usługa A używa tokenów autentyczności, ten wektor ataku nie ma już zastosowania, ponieważ żądanie od usługi b nie zawierałoby prawidłowego tokena autentyczności i nie będzie mogło być kontynuowane.

API docs opisuje szczegóły dotyczące meta tagów:

Ochrona CSRF jest włączona za pomocą metody protect_from_forgery, który sprawdza token i resetuje sesję, jeśli nie pasuje do tego, co oczekiwano. Wywołanie tej metody jest generowane dla nowych Rails aplikacje domyślnie. Parametr tokena jest domyślnie nazywany authenticity_token. Nazwa wartość tego tokena musi być dodana do każdego układu, który renderuje formularzy poprzez umieszczenie csrf_meta_tags w nagłówku HTML.

Uwagi

Pamiętaj, że Rails weryfikuje tylko nie idempotentne metody (POST,PUT / PATCH I DELETE). Żądania GET nie są sprawdzane pod kątem autentyczności. Dlaczego? ponieważ specyfikacja HTTP stwierdza, że żądania GET są idempotentne i powinny Nie tworzyć, zmieniać lub niszczyć zasoby na serwerze ,a żądanie powinno być idempotentne (jeśli uruchamiasz to samo polecenie wiele razy, powinieneś uzyskać ten sam wynik za każdym razem).

Również prawdziwa implementacja jest nieco bardziej skomplikowana, jak zdefiniowano na początku, zapewniając lepsze bezpieczeństwo. Rails nie wydaje tego samego przechowywanego tokena przy każdym formularzu. Nie generuje i nie przechowuje za każdym razem inny żeton. Generuje i przechowuje hash kryptograficzny w sesji i wydaje nowe tokeny kryptograficzne, które można dopasować do przechowywanego, za każdym razem, gdy strona jest renderowana. Zobacz request_forgery_protection.rb .

Lekcje

Użyj authenticity_token, aby chronić swoje Nie idempotentne metody(POST,PUT / PATCH I DELETE). Upewnij się również, że nie zezwalasz na żadne żądania GET, które mogłyby potencjalnie modyfikować zasoby na serwer.


EDIT: Sprawdź komentarz @erturne dotyczący żądania GET jest idempotentny. Wyjaśnia to lepiej niż ja tutaj.

 1378
Author: Faisal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-12 08:40:52

Token autentyczności jest zaprojektowany tak, abyś wiedział, że twój formularz jest przesyłany z twojej strony internetowej. Jest on generowany z komputera, na którym działa, z unikalnym identyfikatorem, który może znać tylko twój komputer, pomagając w ten sposób zapobiegać atakom fałszowania żądań między stronami.

Jeśli po prostu masz problemy z rails odmawiając dostępu do skryptu AJAX, możesz użyć

<%= form_authenticity_token %>

Aby wygenerować poprawny token podczas tworzenia formularza.

Możesz przeczytać więcej na ten temat w dokumentacja .

 130
Author: Topher Fangio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-31 00:54:30

Co to jest CSRF?

Token autentyczności jest środkiem przeciwdziałającym fałszerstwu żądań między stronami (CSRF). Co to jest CSRF, pytasz?

Jest to sposób, w jaki atakujący może potencjalnie przejąć sesje bez znajomości tokenów sesji.

Scenariusz:

  • odwiedź stronę banku, Zaloguj się.
  • następnie odwiedź Stronę atakującego (np. sponsorowaną reklamę od niezaufanej organizacji).
  • Strona atakującego zawiera formularz z tymi samymi polami co bank Formularz "przelew środków".
  • osoba atakująca zna informacje o Twoim koncie i ma wstępnie wypełnione pola formularzy, aby przelać pieniądze z twojego konta na konto osoby atakującej.
  • Strona atakującego zawiera skrypt Javascript, który przesyła formularz do Twojego banku.
  • kiedy formularz zostanie przesłany, przeglądarka zawiera pliki cookie dla strony Banku, w tym token sesji.
  • Bank przelewa pieniądze na konto atakującego.
  • formularz może znajdować się w ramce iframe, która jest niewidoczna, więc nigdy nie wiadomo, doszło do ataku.
  • nazywa się to Cross-Site Request Forgery (CSRF).

Rozwiązanie CSRF :

  • serwer może oznaczać formularze pochodzące z samego serwera
  • każdy formularz musi zawierać dodatkowy token uwierzytelniania jako ukryte pole.
  • Token musi być nieprzewidywalny(atakujący nie może go odgadnąć).
  • Serwer dostarcza poprawny token w formularzach na swoich stronach.
  • serwer sprawdza token podczas wysyłania formularza, odrzuca formularze bez odpowiedniego token.
  • przykładowy token: identyfikator sesji zaszyfrowany tajnym kluczem serwera.
  • Rails automatycznie generuje takie tokeny: patrz pole wejściowe authentity_token w każdej postaci.
 79
Author: Rose Perrone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-20 16:12:00

Minimalny przykład ataku, któremu można by zapobiec

Na mojej stronie evil.com zachęcam do przesłania poniższego formularza:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Jeśli jesteś zalogowany do swojego banku za pomocą Plików cookie sesji, pliki cookie zostaną wysłane, a przelew zostanie wykonany bez Twojej wiedzy.

Czyli w grę wchodzi Token CSRF:

  • z odpowiedzią GET, która zwróciła formularz, Rails wysyła bardzo długi losowy Ukryty parametr
  • Gdy przeglądarka wyśle żądanie POST, prześle parametr razem, a serwer zaakceptuje go tylko wtedy, gdy będzie pasował.]}

Tak więc formularz na autentycznej przeglądarce wyglądałby następująco:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Tak więc mój atak nie powiedzie się, ponieważ nie wysyłał parametru authenticity_token i nie ma mowy, żebym mógł go odgadnąć, ponieważ jest to ogromna liczba losowa.

Ta technika zapobiegania nazywa się Synchronizator Token Pattern.

The synchronizer token pattern działa ze względu na Polityka tego samego pochodzenia: gdybym mógł złożyć wniosek XHR GET do Twojego banku z evil.com i odczytać wynik, byłbym w stanie po prostu odczytać token, a następnie złożyć wniosek później. Wyjaśniłem to dalej na: https://security.stackexchange.com/a/72569/53321

Bardzo polecam przeczytanie Przewodnika OWASP w tej I każdej innej kwestii bezpieczeństwa.

Jak Rails wysyła tokeny

Covered at: Rails: jak działa csrf_meta_tag?

W zasadzie:

  • Helpery HTML jak form_tag Dodaj ukryte pole do formularza, jeśli nie jest to Formularz GET

  • AJAX jest obsługiwany automatycznie przez jquery-ujs , który odczytuje token z elementów meta dodanych do nagłówka przez csrf_meta_tags (obecny w domyślnym szablonie) i dodaje go do dowolnego żądania.

    UJS próbuje również zaktualizować token w postaciach w przestarzałych fragmentach pamięci podręcznej.

Inne metody zapobiegania

 38
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41

Authenticity Token jest metodą zapobiegającą 'ataki cross-site request forgery (CSRF lub XSRF)" .

Upraszczając, zapewnia, że żądania PUT / POST / DELETE (metody, które mogą modyfikować zawartość) do Twojej aplikacji internetowej są wysyłane z przeglądarki klienta, a nie od strony trzeciej (atakującej), która ma dostęp do pliku cookie utworzonego po stronie klienta.

 35
Author: andi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-02 20:17:18

Ponieważ Authenticity Token jest tak ważne, a w Rails 3.0+ można używać

 <%= token_tag nil %>

Aby utworzyć

<input name="authenticity_token" type="hidden" value="token_value">

Anywhere

 32
Author: Yuan He,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-01 05:12:06

Token autentyczności jest używany do zapobiegania atakom Cross-Site Request Forgery (CSRF). Aby zrozumieć token autentyczności, musisz najpierw zrozumieć ataki CSRF.

CSRF

Przypuśćmy, że jesteś autorem bank.com. Masz formularz na swojej stronie, który jest używany do przelewu pieniędzy na inne konto z żądaniem GET: {]}

Tutaj wpisz opis obrazka

Haker może po prostu wysłać żądanie HTTP na serwer mówiąc GET /transfer?amount=$1000000&account-to=999999, prawda?

Tutaj wpisz opis obrazka

Źle. Atak hakerów nie zadziała. Serwer w zasadzie pomyśli?

Huh? Kim jest ten facet, który próbuje zainicjować przeniesienie? To na pewno nie właściciel konta.

Skąd serwer o tym wie? Ponieważ nie ma session_id pliku cookie uwierzytelniającego zgłaszającego.

Gdy logujesz się za pomocą nazwy użytkownika i hasła, serwer ustawia plik cookie session_id w przeglądarce. W ten sposób nie masz aby uwierzytelnić każde żądanie za pomocą nazwy użytkownika i hasła. Kiedy twoja przeglądarka wysyła session_id cookie, serwer wie:

To John Doe. Wpisał się pomyślnie 2,5 minuty temu. Jest gotowy.

Haker może pomyśleć:

Hmm. Zwykłe żądanie HTTP nie zadziała, ale gdybym mógł dostać rękę na tym session_id ciastku, byłbym złoty.

[[19]} przeglądarka użytkowników ma kilka plików cookie ustawionych dla domeny bank.com. Za każdym razem, gdy użytkownik składa wniosek do domeny bank.com, wszystkie pliki cookie są wysyłane razem. Łącznie z ciasteczkiem session_id. Więc gdyby haker namówił Cię do wysłania żądania GET, które przelewa pieniądze na jego konto, to by mu się udało. Jak mógł cię do tego nakłonić? Z Fałszerstwem Żądań Krzyżowych. To całkiem proste. Haker może cię po prostu zmusić do odwiedzenia jego strony internetowej. Na swojej stronie internetowej mógł mieć następujący tag obrazu:
<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Gdy użytkownicy przeglądarka natknie się na ten znacznik obrazu, będzie wysyłać żądanie GET do tego adresu url. A ponieważ żądanie pochodzi z jego przeglądarki, wyśle wraz z nim wszystkie pliki cookie związane z bank.com. Jeśli użytkownik ostatnio zalogował się do bank.com... plik cookie session_id zostanie ustawiony, a serwer pomyśli, że użytkownik zamierzał przenieść $1,000,000 na konto 999999!

Tutaj wpisz opis obrazka

Nie odwiedzaj niebezpiecznych miejsc, a wszystko będzie dobrze.

To nie jest wystarczy. Co jeśli ktoś zamieści to zdjęcie na Facebook ' u i pojawi się na Twojej ścianie? Co jeśli zostanie wstrzyknięty do witryny, którą odwiedzasz, atakując XSS?

Nie jest tak źle. Tylko żądania GET są podatne na ataki.
Nieprawda. Formularz wysyłający żądanie POST może być generowany dynamicznie. Oto przykład z poradnika Rails na temat bezpieczeństwa :
<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Token Autentyczności

Kiedy twoje ApplicationController ma to:

protect_from_forgery with: :exception

To:

<%= form_tag do %>
  Form contents
<% end %>

Jest skompilowany do tego:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

W szczególności generuje się:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

W celu ochrony przed atakami CSRF, jeśli Rails nie zobaczy tokena autentyczności wysłanego wraz z żądaniem, nie uzna żądania za bezpieczne.

Skąd napastnik ma wiedzieć, czym jest ten token? Inna wartość jest generowana losowo za każdym razem, gdy formularz jest generowany:

Tutaj wpisz opis obrazka

Krzyż Atak skryptów witryny (XSS) - w ten sposób. Ale to inna podatność na inny dzień.

 27
Author: Adam Zerner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 21:37:48

Uwaga Mechanizm Tokena autentyczności może skutkować warunkami wyścigu, jeśli masz wiele jednoczesnych żądań od tego samego klienta. W takiej sytuacji serwer może wygenerować wiele tokenów autentyczności, gdy powinien być tylko jeden, a Klient otrzymujący wcześniejszy token w formie zawiedzie przy następnym żądaniu, ponieważ token cookie sesji został nadpisany. Jest zapis na ten problem i nie do końca trywialne rozwiązanie proszę.: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/

 25
Author: jdp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 23:52:45

Metody gdzie authenticity_token jest wymagane

authenticity_token jest wymagane w przypadku metod idempotentnych, takich jak post, put i delete, Ponieważ Metody Idempotentne wpływają na dane.

Dlaczego jest to wymagane

Jest wymagane, aby zapobiec przed złymi działaniami. authentity_token jest przechowywany w sesji, za każdym razem, gdy formularz jest tworzony na stronach internetowych w celu utworzenia lub aktualizacji do zasobów, token autentyczności jest przechowywany w ukrytym polu i wysyłany za pomocą formularza na serwerze. Przed wykonaniem akcji wysłane przez użytkownika authentity_token jest sprawdzane krzyżowo z authenticity_token przechowywanym w sesji. Jeśli authenticity_token jest takie samo, to Proces jest kontynuowany, w przeciwnym razie nie wykonuje akcji.

 8
Author: uma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 08:31:06

Co to jest authentication_token ?

Jest to losowy ciąg używany przez aplikację rails, aby upewnić się, że użytkownik żąda lub wykonuje akcję ze strony aplikacji, a nie z innej aplikacji lub witryny.

Dlaczego authentication_token jest konieczne ?

Aby chronić Twoją aplikację lub witrynę przed fałszowaniem żądań między stronami.

Jak dodać authentication_token do formularza ?

Jeśli generujesz formularz za pomocą znacznika formula_for authentication_token jest automatycznie dodawany w przeciwnym razie możesz użyć <%= csrf_meta_tag %>.

 3
Author: Pradeep Sapkota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-04 15:54:11