Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php
Атака з використанням межсайтовой підробки запиту (CSRF) - це тип вразливості веб-додатки, коли жертва ненавмисно запускає скрипт у своєму браузері, що використовує поточну сесію авторизованого користувача в певному сайті. Атаки CSRF можуть проводитися через GET або POST запити. Дана стаття покаже вам, як захистити своє веб-додаток від атак CSRF.
Метод
Ми будемо використовувати два методи для захисту від CSRF атак ваших GET і POST запитів.
Перший метод полягає у використанні випадкового ключа при кожному запиті, це унікальна рядок, що генерується для кожної сесії. Ми генеруємо ключ, а потім включаємо його в кожну форму у вигляді прихованого поля. Далі, система перевіряє валідність форми, порівнюючи ключ і значення, збережене в сесійному змінної користувача. Тобто, якщо зловмисник захоче згенерувати запит, він повинен буде знати значення ключа.
Другий метод - це використання випадкових назв для кожного поля форми. Значення випадкового імені для кожного поля зберігається в сесійному змінної і після того, як форма відправлена (стався сабміт), система генерує нові випадкові назви полів. Тобто, якщо зловмисник захоче провести атаку, йому потрібно буде знати ці випадкові назви полів форми.
Наприклад, запит, який раніше виглядав ось так:
Буде виглядати ось так:
Кроки
Метод 1 з 2: створення файлу csrf.class.php
Це основний файл, який буде містити всі методи, необхідні для запобігання атак CSRF.
1
Створіть файл csrf.class.php. Почніть, створивши файл, і збережіть його з наступним вмістом:<?phpclass csrf {
Весь код в цій секції керівництва буде додано в кінці цього файлу.2
Створіть метод get_token_id ().
Ця функція отримує id ключа (токен) з сесійного змінної, якщо ж він ще не був створений, то вона генерує випадковий токен.public function get_token_id() {if(isset($ _SESSION[`Token_id`])) {return $ _SESSION[`Token_id`];} else {$ Token_id = $ This->random(10);$ _SESSION[`Token_id`] = $ Token_id;return $ Token_id;}}
3
Створіть метод get_token ().
Ця функція отримує значення токена, якщо ж значення ще не було згенеровано, то воно генерується.public function get_token() {if(isset($ _SESSION[`Token_value`])) {return $ _SESSION[`Token_value`];} else {$ Token = hash(`Sha256`, $ This->random(500));$ _SESSION[`Token_value`] = $ Token;return $ Token;}}
4
Створіть метод check_valid ().
Ця функція перевіряє на валідність id і значення токена. Перевірка відбувається шляхом порівняння значень, отриманих при GET або POST запитах зі значеннями, збереженими в сесійному змінної користувача.public function check_valid($ Method) {if($ Method == `Post` || $ Method == `Get`) {$ Post = $ _POST;$ Get = $ _GET;if(isset(${$ Method}[$ This->get_token_id()]) (${$ Method}[$ This->get_token_id()] == $ This->get_token())) {return true;} else {return false;}} else {return false;}}
5
Створіть метод form_names ().
Це другий захист проти атак CSRF, описана в цій статті. Ця функція генерує випадкові імена для полів форми.public function form_names($ Names, $ Regenerate) {$ Values = array();foreach ($ Names as $ N) {if($ Regenerate == true) {unset($ _SESSION[$ N]);}$ S = isset($ _SESSION[$ N]) ? $ _SESSION[$ N] : $ This->random(10);$ _SESSION[$ N] = $ S;$ Values[$ N] = $ S;}return $ Values;}
6
Створіть метод random ().
Ця функція генерує випадкову рядок, використовуючи випадковий фал linux для більшої хаотичності значень.private function random($ Len) {if (function_exists(`Openssl_random_pseudo_bytes`)) {$ ByteLen = intval(($ Len / 2) + 1);$ Return = substr(bin2hex(openssl_random_pseudo_bytes($ ByteLen)), 0, $ Len);} elseif (@is_readable(`/ Dev / urandom`)) {$ F=fopen(`/ Dev / urandom`, `R`);$ Urandom=fread($ F, $ Len);fclose($ F);$ Return = ``;}if (empty($ Return)) {for ($ I=0;$ I<</span>$ Len-++$ I) {if (!isset($ Urandom)) {if ($ I%2==0) {mt_srand(time()%2147 * 1000000 + (double)microtime() * 1000000);}$ Rand=48+mt_rand()%64;} else {$ Rand=48+ord($ Urandom[$ I])%64;}if ($ Rand57)$ Rand+=7;if ($ Rand90)$ Rand+=6;if ($ Rand==123) $ Rand=52;if ($ Rand==124) $ Rand=53;$ Return.=chr($ Rand);}}return $ Return;}
7
Закінчите клас закриваючою дужкою.
Це завершить клас csrf.}
Тепер ви можете закрити файл csrf.class.php, так як ми з ним закінчили.
Метод 2 з 2: захист сторінок за допомогою csrf.class.php
Ці кроки покажуть вам, як використовувати клас CSRF для захисту від атак CSRF.
1
Захист POST форми.
Наведений нижче код показує використання класу csrf для форми.<?phpsession_start();include `Csrf.class.php`;$ Csrf = new csrf();// Генерація id і значення токена$ Token_id = $ Csrf->get_token_id();$ Token_value = $ Csrf->get_token($ Token_id);// Генерація випадкових назв для полів форми$ Form_names = $ Csrf->form_names(array(`User`, `Password`), false);if(isset($ _POST[$ Form_names[`User`]], $ _POST[$ Form_names[`Password`]])) {// Перевіряємо чи є валідними id і значення токена.if($ Csrf->check_valid(`Post`)) {// Отримуємо змінні форми.$ User = $ _POST[$ Form_names[`User`]];$ Password = $ _POST[$ Form_names[`Password`]];// Метод форми йде тут}// Генеруємо нове випадкове значення для форми.$ Form_names = $ Csrf->form_names(array(`User`, `Password`), true);}?>
2