Если вы берете пользовательский ввод через веб-страницу и вставляете его в базу данных SQLite, есть вероятность, что вы широко открыли для себя проблему безопасности, известную как SQL-инъекция. В этой главе вы узнаете, как предотвратить это и защитить ваши сценарии и операторы SQLite.
Инъекция обычно происходит, когда вы запрашиваете ввод данных у пользователя, например, его имя, и вместо имени они дают вам оператор SQLite, который вы будете бессознательно выполнять в своей базе данных.
Никогда не доверяйте предоставленным пользователем данным, обрабатывайте эти данные только после проверки; как правило, это делается путем сопоставления с образцом. В следующем примере имя пользователя ограничено буквенно-цифровыми символами с подчеркиванием и длиной от 8 до 20 символов — при необходимости измените эти правила.
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)){ $db = new SQLiteDatabase('filename'); $result = @$db->query("SELECT * FROM users WHERE username = $matches[0]"); } else { echo "username not accepted"; }
Чтобы продемонстрировать проблему, рассмотрим этот отрывок —
$name = "Qadir'; DELETE FROM users;"; @$db->query("SELECT * FROM users WHERE username = '{$name}'");
Предполагается, что вызов функции извлекает запись из таблицы пользователей, где столбец имени соответствует имени, указанному пользователем. В обычных условиях $ name будет содержать только буквенно-цифровые символы и, возможно, пробелы, такие как строка ilia. Однако в этом случае, добавив совершенно новый запрос к $ name, вызов к базе данных превращается в катастрофу: введенный запрос DELETE удаляет все записи у пользователей.
Существуют интерфейсы баз данных, которые не разрешают укладку запросов или выполнение нескольких запросов за один вызов функции. Если вы попытаетесь сложить запросы, вызов завершится неудачно, но SQLite и PostgreSQL с радостью выполнят сложенные запросы, выполнив все запросы, представленные в одной строке, и создадут серьезную проблему безопасности.
Предотвращение SQL-инъекций
Вы можете грамотно обрабатывать все escape-символы на языках сценариев, таких как PERL и PHP. Язык программирования PHP предоставляет функцию string sqlite_escape_string () для экранирования входных символов, специфичных для SQLite.
if (get_magic_quotes_gpc()) { $name = sqlite_escape_string($name); } $result = @$db->query("SELECT * FROM users WHERE username = '{$name}'");
Несмотря на то, что кодировка делает вставку данных безопасной, она сделает простые текстовые сравнения и предложения LIKE в ваших запросах непригодными для столбцов, содержащих двоичные данные.
Примечание — addlashes () НЕ должен использоваться для цитирования ваших строк для запросов SQLite; это приведет к странным результатам при получении ваших данных.