Как да развалим магията на магическите кавички в PHP
Публикувана от smilev на January 12 2011 10:39:02

Разширена новина
Какво са магическите кавички?
Ако сте се занимавали с обработка на текстови данни от формуляри, сигурно вече сте се се сблъсквали с неприятния проблем на магическите кавички. Същността на проблема е в това, че когато конфигурационната директива magic_quotes_gpc е включена, енджина на PHP сам поставя "обезопасителни" наклонени черти преди всички кавички в стойностите на суперглобалните променливи $_GET, $_POST, $_COOKIE, $_SERVER и т.н.
Идеята за магическите кавички е възникнала в по-ранните версии на PHP, когато разработчиците на езика са се опасявали, че има твърде много неразумни програмисти, които никога няма да извикат функцията addslashes() върху някой низ преди да го използват в SQL заявка например. За всички останали магическите кавички са просто едно неудобство. Когато те са включени, ако някой потребител въведе например стойността "It's me" в дадено текстово поле на формуляр, то истинската стойност на променливата, когато тя бъде получена от обработващия PHP скрипт ще бъде "It's me". Добре написания PHP код не трябва да разчита на magic_quotes_gpc. Всички разработчици на езика насърчават хората да спрат да използват magic_quotes_gpc. Дори е планувано в PHP6 тази директива да бъде напълно премахната.
Сега следва да ви покажа няколко начина, чрез които можете да развалите "магията" на магическите кавички.
Начини за предотвратяване

Първи начин: директно от php.ini

Ако сървъра е ваш или имате възможност да редактирате php.ini, тогава отворете този файл и просто напишете "Off" срещу директивата magic_quotes_gpc.


Втори начин: чрез .htaccess файл

Ако хоствате сайта си на споделен сървър, едва ли ще е възможно да редактирате php.ini. Но при повечето хостове е позволено да слагате .htaccess файлове във вашите директории. Напишете следното във файл, наречен ".htaccess":


php_flag magic_quotes_gpc "Off"


След това качете този файл в директорията, където са вашите PHP скриптове и така те вече няма да бъдат "омагьосвани" от магическите кавички.

Трети начин: динамично разваляне на магията по време на изпълнение


Сигурно някои от вас си задават въпроса: не може ли това да стане просто с един ред като този: ini_set("magic_quotes_gpc", 0)? Отговорът е НЕ. Ако се разровите в PHP документацията, ще видите, че директивата magic_quotes_gpc е от ниво PHP_INI_PERDIR|PHP_INI_SYSTEM. Това означава, че тя може да се променя по горните два начина, които вече обясних, но не и по време на изпълнение. Причината е в това, че енджина на PHP слага тези наклонени черти още преди изпълнението на скрипта, при регистрирането на суперглобалните променливи. Но както знаете няма невъзможни неща, и аз обичам да казвам, че когато нещо не може да се направи по стандартен начин, винаги е възможно да се заобиколи като се приложи някаква хитрост:

if (get_magic_quotes_gpc()) {
function traverse (&$arr) {
if (!is_array($arr))
return;

foreach ($arr as $key => $val) {
if (is_array($arr[$key])) {
traverse($arr[$key]);
} else {
$arr[$key] = stripslashes($arr[$key]);
}
}
}
$gpc = array(&$_GET, &$_POST, &$_COOKIE);
traverse($gpc);
}

Ако поставите това парче код в началото на вашия скрипт, ще видите, че след него ефекта на магическите кавички ще бъде премахнат. Идеята тук е да се провери дали са включени магическите кавички чрез функцията get_magic_quotes_gpc(), и в случай, че са включени започваме да обхождаме рекурсивно всички елементи на суперглобалните масиви като извикваме за всеки от тях функцията stripslashes(), която премахва наклонените черти. Хубавото на този подход е, че винаги работи, дори когато предните два начина са неприложими. Този начин също е доста подходящ когато искате да пишете преносими PHP скриптове, които не зависят от настройките на конкретната PHP среда, в която вървят. Единствения недостатък тук може би е лекото забавяне на изпълнението на скрипта, но в повечето случаи време от порядъка на 0.005s просто не се усеща.


Добра идея е да сложите горния код в отделен файл, например strip_gpc.php. След това в началото на вашите скриптове просто пишете require_once 'strip_gpc.php' и така с един ред премахвате всички главоболия.


Да свикнем да пишем код без magic_quotes_gpc


След като вече разбрахте как да изключите ефекта на магическите кавички е време да запомните някои важни неща, отнасящи се до сигурността. Най-важното е винаги да използвате addslashes(), там където е необходимо. Пишете SQL заявките така, че да е невъзможно някое по-хитро script kiddie да предизвика грешка в SQL синтаксиса, или по-сериозното - да направи SQL инжекция, което си е доста сериозна заплаха за сигурността. Този кратък пример илюстрира как трябва да се пише PHP код с изключени магически кавички:


if (isset($_POST['search_name'])) {
// изкарване на стойността на променливата, така както си е въведена от потребителя,
// без дразнещите наклонени черти
echo "Вие търсите за {$_POST['search_name']}";
...
// при използване в SQL заявки задължително добавяйте наклонени черти,
// за да не създавате проблеми на SQL парсера и на себе си :)
mysql_query("SELECT * FROM `tbl` WHERE `name`='" . addslashes($_POST['search_name']) . "'");
}