SQL injection и безопасность запросов в PHP

Picture1[1]Среди начинающих программистов в php популярна данная конструкция:

$user = mysql_fetch_assoc(mysql_query("SELECT * FROM `users` WHERE `username` = '{$_POST['username'}' AND `password` = '{$_POST['password']}'"));

Она не безопасна. Если пользователь введёт вместо пароля ‘ OR `username` = ‘admin, система впустит его как администратора. Приведённый пример, разумеется, элементарен. Но если не решить проблему глобально, всегда можно пропустить какой-нибудь запрос, подверженный injection.

Для борьбы с этим разработчики PHP решили сделать так, чтобы вся информация, поступающая от пользователя, подвергалась обработке, и все escapeились (перед ними ставится слэш, который реализует команда addslashes).
Поэтому вся информация от пользователя приходит со слэшами. Даже та, что слэши получить не должна. Например, комментарии к статье. Но этого мало, так как это не 100-процентный способ защиты от SQL injection.

Решение есть:

со всей входящей информации снимаем слэши, если они есть.
всю информацию, поступающую в SQL запрос, фильтруем специально созданной для этого функцией mysql_real_escape_string (или аналогом для другой базы данных).
Снимаем слэши:

if (_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
       {
            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'])));


Запись навигация

Top