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

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

Метод

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

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

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

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

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

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

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

Загрузить 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

Эти шаги покажут вам, как использовать класс 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> 
    


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

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

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

Реклама