Среди начинающих программистов в php популярна данная конструкция:
$user = mysql_fetch_assoc(mysql_query("SELECT * FROM `users` WHERE `username` = '{$_POST['username'}' AND `password` = '{$_POST['password']}'"));
Она не безопасна. Если пользователь введёт вместо пароля ‘ OR `username` = ‘admin, система впустит его как администратора. Приведённый пример, разумеется, элементарен. Но если не решить проблему глобально, всегда можно пропустить какой-нибудь запрос, подверженный SQL injection.
Для борьбы с этим разработчики PHP решили сделать так, чтобы вся информация, поступающая от пользователя, подвергалась обработке, и все кавычки escapeились (перед ними ставится слэш, который реализует команда addslashes).
Поэтому вся информация от пользователя приходит со слэшами. Даже та, что слэши получить не должна. Например, комментарии к статье. Но этого мало, так как это не 100-процентный способ защиты от SQL injection.
Решение есть:
со всей входящей информации снимаем слэши, если они есть.
всю информацию, поступающую в SQL запрос, фильтруем специально созданной для этого функцией mysql_real_escape_string (или аналогом для другой базы данных).
Снимаем слэши:
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { function stripslashes_deep($value) { if(is_array($value)) { $value = array_map('stripslashes_deep', $value); } elseif (!empty($value) && is_string($value)) { $value = stripslashes($value); } return $value; } $_POST = stripslashes_deep($_POST); $_GET = stripslashes_deep($_GET); $_COOKIE = stripslashes_deep($_COOKIE); } }
Создаём функцию для фильтрации (mysql_real_escape_string — длинно, да и привязанно к формату проверки. А если понадобиться поменять фильтр?)
function quote($value) { if (!is_numeric($value)) { $value = "'".mysql_real_escape_string($value)."'"; } return $value; }
и используем её везде. Как только какие-то динамические данных отсылаются SQLу, сразу используем quote:
$user = mysql_fetch_assoc(mysql_query('SELECT * FROM `users` WHERE `username` = '.quote($_POST['username']).' AND `password` = '.quote($_POST['password'])));