Token autentyczności służy do zapobiegania atakom typu Cross-Site Request Forgery (CSRF). Aby zrozumieć token autentyczności, musisz najpierw zrozumieć ataki CSRF.
CSRF
Załóżmy, że jesteś autorem bank.com
. Na stronie znajduje się formularz służący do przesyłania pieniędzy na inne konto z prośbą GET:
Haker może po prostu wysłać do serwera żądanie HTTP z pytaniem GET /transfer?amount=$1000000&account-to=999999
, prawda?
Źle. Atak hakerów nie zadziała. Serwer w zasadzie pomyśli?
Co? 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 osobę żądającą.
Po zalogowaniu się przy użyciu nazwy użytkownika i hasła serwer ustawia session_id
plik cookie w przeglądarce. W ten sposób nie musisz uwierzytelniać każdego żądania za pomocą nazwy użytkownika i hasła. Gdy przeglądarka wysyła session_id
ciasteczko, serwer wie:
Och, to jest John Doe. Zalogował się 2,5 minuty temu. Jest dobry do wyjścia.
Haker może pomyśleć:
Hmm Normalne żądanie HTTP nie zadziała, ale gdybym mógł dostać rękę na ten session_id
plik cookie, byłbym złoty.
Przeglądarka użytkowników ma ustawiony plik cookie dla bank.com
domeny. Za każdym razem, gdy użytkownik bank.com
wysyła żądanie do domeny, wszystkie pliki cookie są wysyłane. W tym session_id
ciasteczko.
Więc jeśli haker mógłby zmusić cię do złożenia żądania GET, które przeleje pieniądze na jego konto, odniesie sukces. Jak mógł cię oszukać? Z fałszowaniem żądań między witrynami.
Właściwie to po prostu proste. Haker może po prostu zachęcić cię do odwiedzenia jego strony internetowej. Na swojej stronie internetowej może mieć następujący tag graficzny:
<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">
Gdy przeglądarka użytkowników natrafi na ten znacznik obrazu, wysyła żądanie GET do tego adresu URL. A ponieważ żądanie pochodzi z jego przeglądarki, wyśle z nim wszystkie powiązane pliki cookie bank.com
. Jeśli użytkownik ostatnio zalogował się w bank.com
... session_id
plik cookie zostanie ustawiony, a serwer pomyśli, że użytkownik zamierzał przelać 1 000 000 USD na konto 999999!
Po prostu nie odwiedzaj niebezpiecznych stron, a wszystko będzie dobrze.
To nie wystarczy Co jeśli ktoś opublikuje ten obraz na Facebooku i pojawi się on na twojej ścianie? Co się stanie, jeśli zostanie wstrzyknięty do witryny odwiedzanej przez atak XSS?
Nie jest tak źle. Tylko żądania GET są wrażliwe.
Nie prawda. Formularz, który wysyła żądanie POST, może być generowany dynamicznie. Oto przykład z Poradnika na temat bezpieczeństwa w Railsach :
<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 masz ApplicationController
to:
protect_from_forgery with: :exception
To:
<%= form_tag do %>
Form contents
<% end %>
Jest skompilowany w to:
<form accept-charset="UTF-8" action="/" method="post">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Form contents
</form>
W szczególności generowane są następujące elementy:
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Aby zabezpieczyć się przed atakami CSRF, jeśli Railsy nie zobaczą tokena autentyczności wysłanego wraz z żądaniem, nie uzna wniosku za bezpieczne.
Jak atakujący powinien wiedzieć, co to jest ten token? Przy każdym generowaniu formularza losowo generowana jest inna wartość:
Atak Cross Site Scripting (XSS) - tak właśnie jest. Ale to inna wrażliwość na inny dzień.