Учебники

SQL — инъекция

Если вы берете пользовательский ввод через веб-страницу и вставляете его в базу данных SQL, есть вероятность, что вы оставите себя широко открытым для проблемы безопасности, известной как SQL-инъекция . Эта глава научит вас, как предотвратить это, и поможет защитить ваши сценарии и операторы SQL в сценариях на стороне сервера, таких как сценарий PERL.

Инъекция обычно происходит, когда вы запрашиваете ввод данных у пользователя, например, его имя, и вместо имени они дают вам оператор SQL, который вы будете бессознательно выполнять в своей базе данных. Никогда не доверяйте предоставленным пользователем данным, обрабатывайте эти данные только после проверки; как правило, это делается с помощью Pattern Matching .

В приведенном ниже примере имя ограничено буквенно-цифровыми символами и подчеркиванием и длиной от 8 до 20 символов (при необходимости измените эти правила).

if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
   $result = mysql_query("SELECT * FROM CUSTOMERS 
      WHERE name = $matches[0]");
} else {
   echo "user name not accepted";
}

Чтобы продемонстрировать проблему, рассмотрим этот отрывок —

// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

Предполагается, что вызов функции извлекает запись из таблицы CUSTOMERS, где столбец имени совпадает с именем, указанным пользователем. В обычных условиях $ name будет содержать только буквенно-цифровые символы и, возможно, пробелы, такие как строка ilia. Но здесь, добавив совершенно новый запрос к $ name, обращение к базе данных превращается в катастрофу; введенный запрос DELETE удаляет все записи из таблицы CUSTOMERS.

К счастью, если вы используете MySQL, функция mysql_query () не разрешает составлять запросы или выполнять несколько запросов SQL за один вызов функции. Если вы попытаетесь сложить запросы, вызов не удастся.

Однако другие расширения базы данных PHP, такие как SQLite и PostgreSQL, успешно выполняют суммированные запросы, выполняя все запросы, представленные в одной строке, и создают серьезную проблему безопасности.

Предотвращение SQL-инъекций

Вы можете грамотно обрабатывать все escape-символы на языках сценариев, таких как PERL и PHP. Расширение MySQL для PHP предоставляет функцию mysql_real_escape_string () для экранирования входных символов, которые являются специальными для MySQL.

if (get_magic_quotes_gpc()) {
   $name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");

Как затруднительное положение

Чтобы решить проблему LIKE, пользовательский механизм экранирования должен преобразовывать предоставленные пользователем символы «%» и «_» в литералы. Используйте addcslashes () , функцию, которая позволяет вам указать диапазон символов для экранирования.