Учебники

SQLite — Инъекция

Если вы берете пользовательский ввод через веб-страницу и вставляете его в базу данных 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; это приведет к странным результатам при получении ваших данных.