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

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

Никогда не доверяйте данным, предоставленным пользователем, обрабатывайте эти данные только после проверки; как правило, это делается путем сопоставления с образцом. В следующем примере имя пользователя ограничено буквенно-цифровыми символами и подчеркиванием и длиной от 8 до 20 символов — измените эти правила по мере необходимости.

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

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

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

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

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

Однако другие расширения баз данных 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 users WHERE name = '{$name}'");