PDF download Загрузить PDF PDF download Загрузить PDF

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

Метод

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

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

Второй метод – это использование случайных названий для каждого поля формы. Значение случайного имени для каждого поля хранится в сессионной переменной и после того, как форма отправлена (произошел сабмит), система генерирует новые случайные названия полей. То есть, если злоумышленник захочет произвести атаку, ему нужно будет знать эти случайные названия полей формы.

К примеру, запрос, который раньше выглядел вот так:

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

Метод 1
Метод 1 из 2:

создание файла csrf.class.php

PDF download Загрузить PDF

Это основной файл, который будет содержать все методы, необходимые для предотвращения атак CSRF.

  1. Начните, создав файл, и сохраните его со следующим содержимым:

     <?php 
     class 
     csrf 
     { 
    
    Весь код в этой секции руководства будет добавлен в конце этого файла.

  2. Эта функция получает 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. Эта функция получает значение токена, если же значение еще не было сгенерировано, то оно генерируется.

     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. Эта функция проверяет на валидность 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, описанная в этой статье. Эта функция генерирует случайные имена для полей формы.

     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. Эта функция генерирует случайную строку, используя случайный фал 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 
     < 
     $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 
     ( 
     $rand 
     > 
     57 
     ) 
     $rand 
     += 
     7 
     ; 
     if 
     ( 
     $rand 
     > 
     90 
     ) 
     $rand 
     += 
     6 
     ; 
     if 
     ( 
     $rand 
     == 
     123 
     ) 
     $rand 
     = 
     52 
     ; 
     if 
     ( 
     $rand 
     == 
     124 
     ) 
     $rand 
     = 
     53 
     ; 
     $return 
     .= 
     chr 
     ( 
     $rand 
     ); 
     } 
     } 
     return 
     $return 
     ; 
     } 
    



  7. Это завершит класс csrf.

     } 
    
    Теперь вы можете закрыть файл csrf.class.php, так как мы с ним закончили.
    Реклама
Метод 2
Метод 2 из 2:

защита страниц при помощи csrf.class.php

PDF download Загрузить PDF

Эти шаги покажут вам, как использовать класс CSRF для защиты от атак CSRF.


  1. Приведенный ниже код показывает использование класса csrf для формы.

     <?php 
     session_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 
     ); 
     } 
     ?> 
      
     <form action="index.php" method="post"> 
     <input type="hidden" name=" 
     <? 
     = 
     $token_id 
     ; 
     ?> 
     " value=" 
     <? 
     = 
     $token_value 
     ; 
     ?> 
     " /> 
     <input type="text" name=" 
     <? 
     = 
     $form_names 
     [ 
     'user' 
     ]; 
     ?> 
     " /><br/> 
     <input type="text" name=" 
     <? 
     = 
     $form_names 
     [ 
     'password' 
     ]; 
     ?> 
     " /> 
     <input type="submit" value="Login"/> 
     </form> 
    


Об этой статье

Эту страницу просматривали 10 048 раз.

Была ли эта статья полезной?

Реклама