Статья про анти sql-inj

Discussion in 'Уязвимости' started by nerezus, 5 Jan 2007.

  1. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    На сервере он всегда по нулям ;)
    А на девелоперской тачке по максимуму ;)
     
  2. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Обновил.
     
  3. Meanor

    Meanor Elder - Старейшина

    Joined:
    9 Sep 2007
    Messages:
    66
    Likes Received:
    9
    Reputations:
    0
    У меня в голове появилась кощунственная мысль засунуть кусочек кода в скрипт с библиотекой функций/классов чтобы он проводил через себя все 3 массива куков, пост и гет. С каждым элементом он производил определенные действия , а потом засовывал их обратно в массив.

    Вопрос насколько это нужно и сильно ли это нагрузит все?
     
  4. Macro

    Macro Elder - Старейшина

    Joined:
    11 Nov 2006
    Messages:
    552
    Likes Received:
    298
    Reputations:
    207
    что-то типа foreach($_REQUEST as $key=>$value){}
     
  5. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Это абсолютно не нужно. Второй вопрос тебя не должен волновать.
     
  6. Meanor

    Meanor Elder - Старейшина

    Joined:
    9 Sep 2007
    Messages:
    66
    Likes Received:
    9
    Reputations:
    0
    Скрипт составить не проблема, вопрос в том, нужно ли это делать, т.е. предпочтительней "мыть" входящие данные на входе по-отдельности или все сразу. Исходя из вышестоящего поста можно стелать вывод, что путь наибольшей головной боли предпочтительней ;)
     
  7. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Какой нафиг головной боли? Делай, как я написал, и ее не будет совсем. Нахрен тебе портить данные?
     
  8. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,324
    Likes Received:
    1,193
    Reputations:
    252
    Была бы статья о всех методах защиты....был бы большой плюс
     
  9. FraiDex

    FraiDex Elder - Старейшина

    Joined:
    16 Jun 2006
    Messages:
    193
    Likes Received:
    68
    Reputations:
    -11
    intro​

    В этой небольшой статье я расскажу о защите о всем нам известной уязвимости SQL-injection. Данной уязвимости подвержено подавляющее большинство сайтов в сети. Суть уязвимости заключается в отсутствии фильтрации спецсимволов в параметрах, передаваемых в запросах к БД. Уязвимость позволяет злоумышленнику выполнять запросы к БД… Да лан, чё я рассказываю. В разделе статьи полно информации по SQL-injection и я изобретать велосипед не буду.  Ну что ж, перейдём к сути…

    Метод №1 – Фильтрация​

    Этот метод заключается в фильтрации спецсимволов с помощью стандартной функции preg_match(). Данная функция будет обрабатывать параметры, передаваемые скрипту от пользователя, на соответствие параметрам, которые должны быть в запросе. Вот кусок уязвимого скрипта:
    PHP:

        
    if(!empty($_GET['id']))
        {
            
            
    /*Получение нужной статьи из БД*/
                
            
    $query "SELECT * FROM articles WHERE id = '$_GET[id]'";
            
    $result_query mysql_query($query);
            if (!
    $result_query) exit("Bad parametr");
            if (
    $article mysql_fetch_array($result_query))
        {


    А вот тот же код, только с использованием функции preg_match():

    PHP:

        
    if(!empty($_GET['id']))
        {
            
            
    /*Проверка переданного параметра*/
            
            
    if (preg_match("|^[\d]{1,3}$|"$_GET['id']))
            {
                
                
    /*Получение из БД нужной статьи*/
                
                
    $query "SELECT * FROM articles WHERE id = '$_GET[id]'";
                
    $result_query mysql_query($query);
                if (!
    $result_query) exit("Bad parametr");
                if (
    $article mysql_fetch_array($result_query))
                {

    else 
        {
            
            
    /*Получение из БД всех статей*/
            
            
    $query "SELECT * FROM articles";
            
    $result_query mysql_query($query);
            if (!
    $result_query) exit("Bad parametr");
            while (
    $article mysql_fetch_array($result_query))
            {

    Согласитесь, не сложно написать пару лишних строк в скрипт, которые смогут защитить ваш сайт от атаки.
    Некоторые перци обрабатывают параметр функцией mysql_escape_ptring(), она похожа на addslashes(). Лично я такой подход не уважаю. Этот способ можно использовать лиш как способ записи корректных SQL запросов и не более того. Многие используют фцнкцию str_replace() которая вырезает все спецсимволы в параметре. Но при использование данной функции запрос всё равно будет выполнен с ложными данными, и вызовет туеву хучу ошибок.

    Способ №2 – создание собственной функции обращения к БД

    Согласитесь, каждый раз добавлять preg_match достаточно нудное занятие, есть способ как этого избежать. Можно написать свою функцию , которая будет отправлять запросы к БД. Вот пример от Дмитрия Котерова, библиотека содержащая в себе функцию для защиты нашего скрипта. Суть её работы в том, что она заменяет стандартную и всем нам до боли известную функцию mysql_query() своей mysql_qw(), т.е. в либе он создал функцию, заменяющую mysql_query, в которую сразу встроена проверка спецсимволов, а так же HTML-тэгов. Данный скрипт защищает как от SQL-injection, так и от XSS. Вот код библиотеки:
    PHP:
    <?php ## Простейшая функция для работы с placeholder-ами.

    // result-set mysql_qw($connection_id, $query, $arg1, $arg2, ...)
    //  - или -
    // result-set mysql_qw($query, $arg1, $arg2, ...)
    // Функция выполняет запрос к MySQL через соединение, заданное как
    // $connection_id (если не указано, то через последнее открытое).
    // Параметр $query может содержать подстановочные знаки ?,
    // вместо которых будут подставлены соответствующие значения
    // аргументов $arg1, $arg2 и т.д. (по порядку), экранированные и
    // заключенные в апострофы.
    function mysql_qw() {
      
    // Получаем все аргументы функции.
      
    $args func_get_args();
      
    // Если первый параметр имеет тип "ресурс", то это ID соединения.
      
    $conn null;
      if (
    is_resource($args[0])) $conn array_shift($args);
      
    // Формируем запрос по шаблону.
      
    $query call_user_func_array("mysql_make_qw"$args);
      
    // Вызываем SQL-функцию.
      
    return $conn!==nullmysql_query($query$conn) : mysql_query($query);
    }

    // string mysql_make_qw($query, $arg1, $arg2, ...)
    // Данная функция формирует SQL-запрос по шаблону $query, 
    // содержащему placeholder-ы.
    function mysql_make_qw() {
      
    $args func_get_args();
      
    // Получаем в $tmpl ССЫЛКУ на шаблон запроса.
      
    $tmpl =& $args[0];
      
    $tmpl str_replace("%""%%"$tmpl);
      
    $tmpl str_replace("?""%s"$tmpl);
      
    // После этого $args[0] также окажется измененным.
      // Теперь экранируем все аргументы, кроме первого.
      
    foreach ($args as $i=>$v) {
        if (!
    $i) continue;        // это шаблон
        
    if (is_int($v)) continue; // целые числа не нужно экранировать
        
    $args[$i] = "'".mysql_escape_string($v)."'";
      }
      
    // На всякий случай запорняем 20 последних аргументов недопустимыми
      // значениями, чтобы в случае, если число "?" превышает количество
      // параметров, выдавалась ошибка SQL-запроса (поможет при отладке).
      
    for ($i=$c=count($args)-1$i<$c+20$i++) 
        
    $args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
      
    // Формируем SQL-запрос.
      
    return call_user_func_array("sprintf"$args);
    }
    ?>
    Используется он так
    PHP:
    include_once( "./mysq_qw.php" );

        
    if(!empty($_GET['id']))
        {
            
            
    /*Получение нужной статьи из БД*/
                
            
    $query "SELECT * FROM articles WHERE id = '$_GET[id]'";
            
    $result_query mysql_qw($query);
            if (!
    $result_query) exit("Bad parametr");
            if (
    $article mysql_fetch_array($result_query))
        {

     
    Конечно он староват, но работает до сих пор…

    Способ №3 – Использование mod_rewrite​

    Этот способ заключается в использовании модуля Апача под названием mod_rewrite. И так, как же мы его будем использовать??? :D Все знаю как данные передаются скрипту методом GET (www.site.ru/script.php?id=1), где id содержит параметры для обращения к БД. С использование mod_rewrite можно выше приведённой ссылке придать более человеческий вид (Например: www.site.ru/script_1.html). Для этого на нужно в веб-каталоге сервера (Например: /home/site/www) создать файл .htaccess со следующим кодом:
    Code:
    RewriteEngine on
    Options +FollowSymlinks
    RewriteBase /
    RewriteRule ^.htaccess$ - [F]
    
    Таким образом мы будем запускать модуль. Теперь перейдем к замене ссылок. Добавим в конец .htaccess следующую строку:
    Code:
    RewriteRule http://www.site.ru/script_([0-9]*).html http://www.site.ru/script.php?id=$1
    
    Теперь при обращении к сайту www.site.ru/script_1.html произойдёт замена на http://www.site.ru/script.php?id=1, которая в последствии будет выполнена. “А в чём же здесь защита?” спросите вы. Обратите внимание на script_([0-9]*).html, здесь у нас идёт проверка переданных скрипту параметров, т.е. как мы видим: если передаваемый параметр будет содержать кроме числовых ещё какие-нибудь символы, то запрос выполнен не будет…
    Дополнительную информацию о mod_rewrite и о его использовании можно найти в документации по серверу Apache. www.apache.org

    Outro
    Ну вот, я кратко описал способы решения данной проблемы. Если вам есть что добавить, просьба отписать в эту тему. Всем удачи.
     
    1 person likes this.
  10. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    FraiDex
     
  11. FraiDex

    FraiDex Elder - Старейшина

    Joined:
    16 Jun 2006
    Messages:
    193
    Likes Received:
    68
    Reputations:
    -11
    фаг.. но ведь вё равно принимает. спецсимволы она не фильтрует
     
  12. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Достаточно прогонять текстовые переменные по даной функции и больше не чего не надо
    PHP:
        function secure_sql($value) {
            if( 
    get_magic_quotes_gpc()) {
                
    $value stripslashes$value );
            }
            if( 
    function_exists"mysql_real_escape_string" )) {
                
    $value mysql_real_escape_string$value );
            } else {
                
    $value addslashes$value );
            }
            return 
    $value;
        }
     
  13. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,324
    Likes Received:
    1,193
    Reputations:
    252
    На вид большая функция а =\\

    1) Зачем цифры переводить через эту функцию?
    Достаточно
    PHP:
    <?php
    $xek 
    intval($xek);
    ?>
    2) Оох... где-то еще есть серваки с пхп 3 чтобы делать поверку на существование функции mysql_real_escape_string ?

    3) mysql_real_escape_string не экранирует символы % и _ также как mysql_escape_string что будет багой например при %LIKE% .....
    Поэтому достаточно написать свою функцию в 3 строки с реплейсом % и _ на \%, \_ ну и mysql_real_escape_string
     
  14. neval

    neval Elder - Старейшина

    Joined:
    13 Dec 2006
    Messages:
    457
    Likes Received:
    116
    Reputations:
    23

    зри в корень )
     
  15. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Могу скинуть свою обертку для запросов. Нужно?
    На самом деле это боян, обертка типа.
     
  16. PEHAT

    PEHAT New Member

    Joined:
    16 Nov 2008
    Messages:
    2
    Likes Received:
    0
    Reputations:
    0
    А зачем число ещё и mysql_escape_string'ом обрабатывать?
     
  17. Krist_ALL

    Krist_ALL Banned

    Joined:
    14 Jan 2009
    Messages:
    436
    Likes Received:
    193
    Reputations:
    24
    Mysql_real_escape_string не спасет от слепых инекций.
     
  18. .Slip

    .Slip Elder - Старейшина

    Joined:
    16 Jan 2006
    Messages:
    1,571
    Likes Received:
    977
    Reputations:
    783
    А не от слепых спасает?:о
     
  19. aleksej_sumarok

    aleksej_sumarok New Member

    Joined:
    19 Sep 2009
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    Если не трудно скинь пожалуйста :)
     
  20. Pashkela

    Pashkela Динозавр

    Joined:
    10 Jan 2008
    Messages:
    2,750
    Likes Received:
    1,044
    Reputations:
    339
    в топике ничего не упомянуто об:

    1. реферере
    2. сессии
    3. прочие "особые" моменты

    ))

    Практически никто этого не обрабатывает, если говорить про фул_паф_дискложен