Jeden żeton kontra wiele żetonów, aby zapobiec atakom CSRF
Używam Codeigniter i chcę zapobiec atakom CSRF, które mogą się zdarzyć. Aby to osiągnąć, dodam ukryty znacznik wejściowy z losowym tokenem do każdego formularza, który chcę chronić, a jednocześnie zachowuję ten token podczas sesji, z którą należy porównać, gdy zaczynam obchodzić się z danymi formularza.
// set a token to prevent CSRF attacks
$csrf_token = md5(uniqid(rand(), true));
$this->session->set_userdata("csrf_token", $csrf_token);
A formularz będzie wyglądał następująco:
<form action="path/to/handler/page" method="post">
<input type="text" name="title">
<input type="text" name="date">
<textarea name="content"></textarea>
<input type="hidden" name="csrf_token" value="<?php echo $this->session->userdata("csrf_token") ?>">
<input type="submit" name="submit" value="Save">
</form>
Na stronie, na której obsługuję przesyłane dane, sprawdzam CSRF atakuje coś takiego:
// make sure there is no CSRF attack attempt
$csrf_token = $this->session->userdata("csrf_token");
if (empty($csrf_token) || $csrf_token !== $this->input->post("csrf_token")) {
die("Some message here!!");
}
I to działa całkiem dobrze. Ale jak widzisz, generuję losowy token dla każdej strony zawierającej formularz, aw niektórych przypadkach powoduje to problem, jeśli na przykład otworzyłem inną kartę w przeglądarce, aby wykonać inną akcję. Rozważmy następujący scenariusz:
otworzyłemadd.php
strona, aby dodać nowy element.Wypełniłem wszystkie wymagane dane, ale nie przesłałem formularza.Teraz postanowiłem otworzyćedit.php
strona na innej karcie w przeglądarce, aby edytować istniejący element.Potem wróciłem doadd.php
strona, która została wypełniona i próbowała przesłać dane.W tym momencie dostanę błąd, ponieważ wartość tokena, który został zapisany w sesji po otwarciuadd.php
strona została zmieniona i zastąpiona innym tokenem, gdy otworzęedit.php
strona. Jak mogę rozwiązać ten problem? Czy powinienem wygenerować po jednym żetonie dla każdego użytkownika, gdy uda mu się zalogować, a następnie użyć tego żetonu na wszystkich stronach, którymi może się zajmować? Czy to podejście ma jakiekolwiek ryzyko lub wady?