Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

Атака з використанням межсайтовой підробки запиту (CSRF) - це тип вразливості веб-додатки, коли жертва ненавмисно запускає скрипт у своєму браузері, що використовує поточну сесію авторизованого користувача в певному сайті. Атаки CSRF можуть проводитися через GET або POST запити. Дана стаття покаже вам, як захистити своє веб-додаток від атак CSRF.

Метод

Ми будемо використовувати два методи для захисту від CSRF атак ваших GET і POST запитів.


Перший метод полягає у використанні випадкового ключа при кожному запиті, це унікальна рядок, що генерується для кожної сесії. Ми генеруємо ключ, а потім включаємо його в кожну форму у вигляді прихованого поля. Далі, система перевіряє валідність форми, порівнюючи ключ і значення, збережене в сесійному змінної користувача. Тобто, якщо зловмисник захоче згенерувати запит, він повинен буде знати значення ключа.


Другий метод - це використання випадкових назв для кожного поля форми. Значення випадкового імені для кожного поля зберігається в сесійному змінної і після того, як форма відправлена (стався сабміт), система генерує нові випадкові назви полів. Тобто, якщо зловмисник захоче провести атаку, йому потрібно буде знати ці випадкові назви полів форми.


Наприклад, запит, який раніше виглядав ось так:

Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

Буде виглядати ось так:

Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php




Метод 1 з 2: створення файлу csrf.class.php

Це основний файл, який буде містити всі методи, необхідні для запобігання атак CSRF.

  1. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    1

    Створіть файл csrf.class.php. Почніть, створивши файл, і збережіть його з наступним вмістом:

    <?phpclass csrf {

    Весь код в цій секції керівництва буде додано в кінці цього файлу.

  2. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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) в php

    7

    Закінчите клас закриваючою дужкою.
    Це завершить клас csrf.

    }

    Тепер ви можете закрити файл csrf.class.php, так як ми з ним закінчили.

Метод 2 з 2: захист сторінок за допомогою csrf.class.php

Ці кроки покажуть вам, як використовувати клас CSRF для захисту від атак CSRF.

  1. Як захиститися від атак з використанням межсайтовой підробки запиту (CSRF) в php

    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);}?>
    <?= $ Token_id; ?>"Value ="<?= $ Token_value; ?>"/><?= $ Form_names[`User`]; ?>"/><?= $ Form_names[`Password`]; ?>"/>

  2. 2