Если взять ввод данных пользователя через веб – страницу и вставить его в базу данных SQL, есть шанс, что вы оставили открытыми ворота для проблемы безопасности, известной как SQL Injection. Эта глава покажет вам, как помочь предотвратить это и поможет вам защитить ваши скрипты и операторы SQL в скриптах на вашем сервере, такие как скрипт PERL.
Инъекции обычно происходят, когда вы просите ввод пользователя, как их имя и вместо имени они дают вам SQL запросы, и вы будете неосознанно работать на вашей базе данных. Никогда не доверяйте пользователям предоставлять данные, обрабатывать эти данные только после проверки; как правило, это делается путем сопоставления с образцом.
В приведенном ниже примере, имя ограничивается буквенно-цифровыми символами, а также подчеркиванием, и длиной от 8 до 20 символов (изменить эти правила в случае необходимости).
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) { $result = mysql_query("SELECT * FROM CUSTOMERS WHERE name = $matches[0]"); } else { echo "имя пользователя не принято"; }
Чтобы продемонстрировать эту проблему, рассмотреть этот отрывок:
// предполагаемый ввод $name = "Qadir'; DELETE FROM CUSTOMERS;"; mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");
Вызов функции предполагает извлечь запись из таблицы CUSTOMERS, где имя столбца совпадает с именем, указанным пользователем. При нормальных обстоятельствах, $name будет содержать только буквенно-цифровые символы и , возможно, пробелы, такие как строка ilia. Но здесь, путем добавления совершенно новый запрос к имени $, вызов к базе данных превращается в бедствие; нагнетаемый запрос DELETE удаляет все записи из таблицы Customers.
К счастью, если вы используете MySQL, то функция mysql_query() не допускает запуск запроса или выполнения нескольких запросов SQL в вызове одной функции. Если попытаться стек запросов, вызов неудачен.
Тем не менее, другие расширения PHP базы данных, такие как SQLite и PostgreSQL с удовольствием выполняют стеки запросов, выполняя все запросы, представленные в одной строке и создают серьезную проблему безопасности.
Вы можете обрабатывать все спецсимволы в скриптовых языках, таких как 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(), которая позволяет указать диапазон символов, чтобы избежать иньекции.
$sub = addcslashes(mysql_real_escape_string("%str"), "%_"); // $sub == \%str\_ mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");