Защита от CSRF
19-10-2012
Питахме какво е, 'що е това Cross-site request forgery(CSRF)? Е реших да направя 50-тото си мнения и да напиша урок относно това. Надявам се да ви е от полза и да не злорадствате :))

CSRF е широко използвана уязвимост в уеб приложенията. Тази атака, атакуващия може да наруши цялостта на потребителската сесия с уеб страница, като инжектира заявка по мрежата посредством браузъра на потребителя. Политиката на сигурност на browser-ите позволява уеб адресите да изпращат HTTP заявка до който и да е мрежови адрес.

Накратко: CSRF е мястото, където злонамерен уеб сайт ще се опита да издаде действия по отношение на друг сайт, без знанието на потребителя от него, настъпили.

Имаме следната ситуация. Направилисте си регистрация в някой сайт за онлайн банкиране ОК, няма проблеми. Дали сте отметка на "Запомни ме", когато сте се вписали.
Сега.. да предположим, че имате опция за лесно прехвърляне на пари между хората. Т.е. искам да кажа прехвърляте си пари от Адриян до Петкан. (например)
При трансфера, ако се загледате може да забележите нещо от вида на: banka.com/transfer.php?To=46346442634?cena=1000.

Какво всъщност правите с горния линк? Правите трансфер до клиентски номер: 46346442634, на стойност 1000 $/лв/евро - все тая.
Всъщност. Трансфера ще е успешно до Петкан - няма проблеми ние искахме да му преведем дадената сума, НО ако имаме някой зъл хакер, който иска да ни манипулира и не само нас, но и всички хора, които имат регистрация във въпросния сайт.
Може да ни прехвърли парите ни в неговата сметка. Това може, да стане ако сайта е уязвим към CSRF. Виждате някакъв безобиден сайт, но всъщност е "заразен". Който прави горната манипулация и се прехвърлят парите.

Този проблем е известен като (CSRF) и това е потенциален проблем във всеки един динамичен уеб сайт.
Докато кражба на пари е краен пример, CSRF може да се използва, за да открадне "бисквитки" от един уеб сайт или да публикувате нежелана поща
коментари по блогове, изтриване на албуми, снимки, без потребителят да е наясно, че това го правят от друг сайт(злонамерен).

Действия на уеб сайтове винаги са свързани с форми - влизане в системата, прехвърляне на пари или публикуване на коментар в блога.
Решение на проблема CSRF е да се генерира уникален ключ, когато потребител посети страницата с формата.

Сега ще създаден един уникален ключ и ще използваме сессии. Когато заявката е подадена ще проверим ключа, записан в сесията, както и ключа от страницата на формата за публикуване(например).
Ако те са едни и същи, значи че потребителят доброволно подава заявка. Ако те не съвпадат или $_SESSION ключа е празен, тогава предполагаме, че това е злонамерен начин и се случва нещо нередно.
Можем спокойно да пренасочим потребителя и да не направи никакви действия.

<?php
session_start();
if(isSet($_POST['submit'])) {
if(isSet($_SESSION['token'] == $_POST['token'])) { //проверяваме ключа
echo 'ОК';
} else { //ако има проблем го връщваме в началната страница.
header("Location: ./index.php");
}
} else {
$token = md5(uniqid(rand(), true)); //генерираме нашия уникален ключ
$_SESSION['token'] = $token; //запазваме го в сесия
$form = '
<form method="POST" action="">
Текст: <input type="text" name="message" /><br />
<input type="hidden" name="token" value="' . $token . '" />
<input type="submit" name="submit" />
</form>';
echo $form;
}
?>


Няма нищо сложно, нали? :) Имаме една сесия, генериране на уникален ключ и една проверка.

Надявам се да сте ме разбрали и да съм ви помогнал. Въпреки всичко.. няма непредолима защита, но е хубаво да е има! :)







/ Трябва да сте регистриран за да напишете коментар /
От: Ticketa
16:13 24-10-2012
Вместо:

if(isSet($_SESSION['token'] == $_POST['token'])) { //проверяваме ключа

Ползвайте:

if(isSet($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) {
1