SQLite - Injection

Si vous prenez une entrée utilisateur via une page Web et l'insérez dans une base de données SQLite, il est possible que vous vous soyez laissé ouvert à un problème de sécurité appelé injection SQL. Dans ce chapitre, vous apprendrez comment éviter que cela ne se produise et vous aider à sécuriser vos scripts et instructions SQLite.

L'injection se produit généralement lorsque vous demandez à un utilisateur une entrée, comme son nom, et au lieu d'un nom, il vous donne une instruction SQLite que vous exécuterez sans le savoir sur votre base de données.

Ne faites jamais confiance aux données fournies par l'utilisateur, ne traitez ces données qu'après validation; en règle générale, cela se fait par correspondance de modèles. Dans l'exemple suivant, le nom d'utilisateur est limité aux caractères alphanumériques plus le trait de soulignement et à une longueur comprise entre 8 et 20 caractères - modifiez ces règles si nécessaire.

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";
}

Pour démontrer le problème, considérez cet extrait -

$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT * FROM users WHERE username = '{$name}'");

L'appel de fonction est censé récupérer un enregistrement de la table users où la colonne name correspond au nom spécifié par l'utilisateur. Dans des circonstances normales,$namene contiendrait que des caractères alphanumériques et peut-être des espaces, comme la chaîne ilia. Cependant dans ce cas, en ajoutant une requête entièrement nouvelle à $ name, l'appel à la base de données se transforme en catastrophe: la requête DELETE injectée supprime tous les enregistrements des utilisateurs.

Il existe des interfaces de bases de données qui ne permettent pas l'empilement de requêtes ou l'exécution de plusieurs requêtes en un seul appel de fonction. Si vous essayez d'empiler des requêtes, l'appel échoue mais SQLite et PostgreSQL exécutent volontiers des requêtes empilées, exécutant toutes les requêtes fournies dans une chaîne et créant un sérieux problème de sécurité.

Empêcher l'injection SQL

Vous pouvez gérer tous les caractères d'échappement intelligemment dans des langages de script comme PERL et PHP. Le langage de programmation PHP fournit la fonctionstring sqlite_escape_string() pour échapper les caractères d'entrée spécifiques à SQLite.

if (get_magic_quotes_gpc()) {
   $name = sqlite_escape_string($name);
}
$result = @$db->query("SELECT * FROM users WHERE username = '{$name}'");

Bien que l'encodage permette d'insérer les données en toute sécurité, il rendra de simples comparaisons de texte et LIKE clauses de vos requêtes inutilisables pour les colonnes contenant les données binaires.

Note - addslashes()ne doit PAS être utilisé pour citer vos chaînes pour les requêtes SQLite; cela conduira à des résultats étranges lors de la récupération de vos données.