(PHP 4 >= 4.3.0, PHP 5, PECL mysql:1.0)
mysql_real_escape_string — Protège les caractères spéciaux d'une commande SQL
mysql_real_escape_string() protège les caractères spéciaux de la chaîne unescaped_string , en prenant en compte le jeu de caractères courant de la connexion link_identifier . Le résultat peut être utilisé sans problème avec la fonction mysql_query() . Si des données binaires doivent être insérées, cette fonction doit être utilisée.
mysql_real_escape_string() appelle la fonction mysql_escape_string() de la bibliothèque MySQL qui ajoute un slash aux caractères suivants : NULL , \x00 , \n , \r , \ , ' , " et \x1a .
Cette fonction doit toujours (avec quelques exceptions) être utilisée pour protéger vos données avant d'envoyer la requête à MySQL.
La chaîne à échapper.
La connexion MySQL. S'il n'est pas spécifié, la dernière connexion ouverte avec la fonction mysql_connect() sera utilisée. Si une telle connexion n'est pas trouvée, la fonction tentera d'ouvrir une connexion, comme si la fonction mysql_connect() avait été appelée sans argument. Si aucune connexion n'est trouvée ou établie, une alerte E_WARNING est générée.
Retourne la chaîne échappée, ou FALSE si une erreur survient.
Exemple 1609. Exemple simple avec mysql_real_escape_string()
<?php
// Connexion
$link
=
mysql_connect
(
'mysql_host'
,
'mysql_user'
,
'mysql_password'
)
OR die(
mysql_error
());
// Requête
$query
=
sprintf
(
"SELECT * FROM users WHERE user='%s' AND password='%s'"
,
mysql_real_escape_string
(
$user
),
mysql_real_escape_string
(
$password
));
?>
Exemple 1610. Un exemple d'attaque par injection SQL
<?php
// Demande à la base de vérifier si un utilisateur correspond
$query
=
"SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'"
;
mysql_query
(
$query
);
// Nous ne vérifions pas $_POST['password'], il peut contenir ce que l'utilisateur veut ! Par exemple :
$_POST
[
'username'
] =
'aidan'
;
$_POST
[
'password'
] =
"' OR ''='"
;
// Cela signifie que la requête envoyée à MySQL sera :
echo
$query
;
?>
La requête envoyée à MySQL :
SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''
Cela permet à n'importe qui de s'identifier sans mot de passe valide.
Exemple 1611. Meilleure pratique
L'utilisation de la fonction mysql_real_escape_string() sur chaque variable évite les injections SQL. Cet exemple démontre la méthode la plus propre pour envoyer une requête à la base, indépendamment de votre configuration des guillemets magiques .
<?php
if (isset(
$_POST
[
'product_name'
]) && isset(
$_POST
[
'product_description'
]) && isset(
$_POST
[
'user_id'
])) {
// Connect
$link
=
mysql_connect
(
'mysql_host'
,
'mysql_user'
,
'mysql_password'
);
if(!
is_resource
(
$link
)) {
echo
"Échec de la connexion au serveur\n"
;
// ... historisation de l'erreur
} else {
// Annule les effets magic_quotes_gpc/magic_quotes_sybase sur ces variables si ON.
if(
get_magic_quotes_gpc
()) {
if(
ini_get
(
'magic_quotes_sybase'
)) {
$product_name
=
str_replace
(
"''"
,
"'"
,
$_POST
[
'product_name'
]);
$product_description
=
str_replace
(
"''"
,
"'"
,
$_POST
[
'product_description'
]);
} else {
$product_name
=
stripslashes
(
$_POST
[
'product_name'
]);
$product_description
=
stripslashes
(
$_POST
[
'product_description'
]);
}
} else {
$product_name
=
$_POST
[
'product_name'
];
$product_description
=
$_POST
[
'product_description'
];
}
// Faire une requête sécurisée
$query
=
sprintf
(
"INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)"
,
mysql_real_escape_string
(
$product_name
,
$link
),
mysql_real_escape_string
(
$product_description
,
$link
),
$_POST
[
'user_id'
]);
mysql_query
(
$query
,
$link
);
if (
mysql_affected_rows
(
$link
) >
0
) {
echo
"Produit inséré\n"
;
}
}
} else {
echo
"Remplissez le formulaire proprement\n"
;
}
?>
La requête s'exécute maintenant correctement et les attaques par injection SQL ne fonctionnent plus.
Note: Une connexion MySQL est nécessaire avant d'utiliser la fonction mysql_real_escape_string() , sinon, une erreur de niveau E_WARNING sera générée, et FALSE sera retourné. Si link_identifier n'est pas défini, la dernière connexion MySQL est utilisée.
Note: Si magic_quotes_gpc est activée, appliquez d'abord la fonction stripslashes() à vos données. Utiliser cette fonction sur des données qui ont déjà été protégées, les protègera une deuxième fois.
Note: Si cette fonction n'est pas utilisée pour protéger vos données, la requête sera vulnérable aux attaques par injection SQL .
Note: mysql_real_escape_string() n'échappe ni % , ni _ . Ce sont des jokers en MySQL si combinés avec LIKE , GRANT , ou REVOKE .