À chaque fois qu'un programme effectue une requête SQL à partir de données entrées par l'utilisateur, il s'expose aux injections SQL. Comme donnée entrée par l'utilisateur, on peut retrouver :
Les injections SQL sont bien connues des utilisateurs malveillants : lorsqu'une requête SQL utilise une information entrée par l'utilisateur, on tente d'intercepter la requête originale à l'aide de caractères pouvant être interprétés par le SGBD. Tout ceci sera fait dans le but d'effectuer une requête différente de celle qui était originalement prévue.
Par exemple, prenons la requête suivante. Remarquez que j'ai barré une partie de la requête pour bien faire comprendre qu'il ne faut pas faire ceci.
SELECT * FROM wp_posts WHERE ID=
Dans cette requête, la valeur de $_GET['post_id'] peut être n'importe quoi. Elle est tirée d'un URL sous la forme « https://monsite.com/unepage.php?post_id=5 ».
Si un utilisateur malveillant modifiait l'URL ainsi :
« https://monsite.com/unepage.php?post_id=5' OR 1=1; UPDATE wp_users SET user_pass='motdepassecrypte' -- »
La requête exécutée sur le serveur serait la suivante :
SELECT post_title FROM wp_posts WHERE ID=5 OR 1=1; UPDATE wp_users SET user_pass='motdepassecrypte'
En entrant un mot de passe de son choix, l'utilisateur malveillant aura ainsi accès à tous les comptes d'utilisateurs du site Web. Ouch !
La plupart des extensions SQL, par exemple mysqli qui est utilisée par WordPress, empêchent nativement de transformer une requête en deux requêtes comme dans cet exemple. Cependant, certaines plus anciennes laissent cette porte ouverte.
Voici un autre exemple d'attaque, cette fois qui passera le test peu importe l'extension SQL utilisée.
SELECT post_title FROM wp_posts WHERE ID=5 UNION SELECT CONCAT_WS(CHAR(32,58,32),user(),database(),version())
Cette fois, l'usager malveillant aura accès à de l'information sensible qui l'aidera à mener des attaques plus dangereuses.
Lors de l'insertion de données, si vous utilisez $wpdb->insert(), vous avez automatiquement une protection contre les injections SQL.
$resultat = $wpdb->insert(
$table_matable,
[
'champ1' => $nombre,
'champ2' => $chaine,
],
[
'%d',
'%s',
]
);
Dans le cas d'une requête SELECT, il faut entourer la requête par un appel à $wpdb->prepare() afin de bénéficier d'une protection contre les injections SQL.
Remarquez que $wpdb->prepare() exige que chaque paramètre soit identifié par son type dans la requête :
$enreg = $wpdb->get_row(
$wpdb->prepare(
"SELECT post_title FROM $wpdb->posts WHERE ID = '%d' ",
$_GET['post_id']
)
);
« Better Know a Vulnerability: SQL Injection ». Otto on WordPress. http://ottopress.com/2013/better-know-a-vulnerability-sql-injection/
▼Publicité