Maison > développement back-end > tutoriel php > Interdire complètement les attaques par injection SQL dans PHP Partie 2

Interdire complètement les attaques par injection SQL dans PHP Partie 2

黄舟
Libérer: 2023-03-04 08:36:01
original
889 Les gens l'ont consulté

L'une des attaques par injection SQL totalement interdites en PHP

1. Types d'attaques par injection

Il peut y avoir de nombreux types différents de motivations d'attaque, mais à première vue, il semble qu'il existe d'autres types. C'est tout à fait vrai si un utilisateur malveillant invente une méthode qui effectue plusieurs requêtes. Nous en discuterons en détail plus loin dans cet article.

Si votre script exécute une instruction SELECT, alors un attaquant peut forcer l'affichage de chaque ligne d'un tableau - en injectant une condition telle que '1=1' dans la clause WHERE, comme indiqué ci-dessous (la la partie d'injection est indiquée en gras) :

SELECT * FROM vins WHERE variété = 'lagrein' OR 1=1;'



Comme nous Comme nous l'avons vu précédemment, cela peut être une information utile en soi, car elle révèle la structure générale du tableau (ce qu'un simple enregistrement ne peut pas faire), ainsi que l'affichage d'embuscade contenant des enregistrements d'informations confidentielles.

Une embuscade de commande mise à jour présente une menace plus directe. En plaçant d'autres attributs dans la clause SET, un attaquant peut modifier n'importe quel champ de l'enregistrement actuellement mis à jour, comme dans l'exemple suivant (dans lequel la partie injectée est affichée en gras) :

UPDATE wines SET type=' red', 'vintage'='9999' WHERE variété = 'lagrein'



En mettant une constante telle que 1=1 Des conditions sont ajoutées à la clause WHERE d'une instruction de mise à jour. Cette portée de correction peut être étendue à chaque enregistrement, comme dans l'exemple suivant (dans lequel la partie injection est affichée en gras) :

UPDATE wines SET type= 'red','vintage' ='9999 WHERE variété = 'lagrein' OR 1=1;'



L'instruction la plus dangereuse est probablement DELETE - ce n'est pas difficile à imaginer. La technique d'injection est similaire à ce que nous avons déjà vu - en modifiant la clause WHERE pour élargir la portée des enregistrements concernés, comme dans l'exemple suivant (dans lequel la partie injection est affichée en gras) :

DELETE FROM vins WHERE variété = 'lagrein' OR 1=1;'



 2. Injection de requêtes multiples

L'injection de requêtes multiples permettra d'augmenter le potentiel dommages qu'un attaquant peut causer en permettant à plusieurs instructions dommageables d'être incluses dans une requête. Lors de l'utilisation de la base de données MySQL, un attaquant peut facilement y parvenir en insérant un terminateur inattendu dans la requête : un guillemet injecté (simple ou double) marque la variable attendue à la fin, puis applique un point-virgule pour terminer la directive. Désormais, une commande d'attaque supplémentaire peut être ajoutée à la fin de la commande d'origine désormais terminée. La requête dommageable ultime pourrait ressembler à ceci :

SELECT * FROM wines WHERE variété = 'lagrein';
GRANT ALL ON *.* TO 'BadGuy@%' IDENTIFIED BY 'gotcha'; >


Cette injection créera un nouvel utilisateur BadGuy et lui donnera les privilèges réseau (tous les privilèges sur toutes les tables parmi elles, un mot de passe « malchanceux » est ajouté à ce simple) ; Instruction SELECT. Si vous avez suivi nos conseils de l'article précédent pour limiter strictement les privilèges de l'utilisateur du processus, alors cela ne devrait pas fonctionner car le démon du serveur web ne dispose plus des privilèges GRANT que vous avez révoqués. Mais en théorie, une telle attaque pourrait donner carte blanche à BadGuy pour exercer le contrôle qu’il a sur votre base de données.



Quant à savoir si une telle requête multi-requête sera traitée par le serveur MySQL, la conclusion n'est pas unique. Cela peut être dû en partie à différentes versions de MySQL, mais la plupart du temps, cela est dû à la manière dont plusieurs requêtes existent. Le programme de surveillance de MySQL permet pleinement une telle requête. L'interface graphique MySQL-phpMyAdmin couramment utilisée copiera tout le contenu précédent avant la requête finale, et ne fera que cela.

Cependant, la plupart des requêtes multiples dans un contexte d'injection sont gérées par l'extension mysql de PHP. Heureusement, par défaut, il ne permet pas d'exécuter plusieurs instructions dans une requête ; essayer d'exécuter deux instructions (comme l'injection illustrée ci-dessus) provoquera simplement un échec - aucune erreur n'est définie et aucune information de sortie. Dans ce cas, bien que PHP implémente simplement son comportement par défaut "étape par étape", il vous protège de la plupart des attaques par injection simples.

La nouvelle extension mysqli en PHP5 (voir http://php.net/mysqli), tout comme mysql, ne prend pas automatiquement en charge plusieurs requêtes, mais elle fournit une fonction mysqli_multi_query() pour vous aider à implémenter plusieurs requêtes - si vous voulez vraiment le faire.

Cependant, la situation est encore plus désastreuse pour SQLite, le moteur de base de données SQL intégrable fourni avec PHP5 (voir http://sqlite.org/ et http://php.net/sqlite), attirant l'attention d'un grand nombre d'utilisateurs en raison de sa facilité d'application. Dans certains cas, SQLite autorise par défaut de telles requêtes multi-instructions car la base de données peut optimiser les requêtes par lots, en particulier le traitement des instructions INSERT par lots, ce qui est très efficace. Cependant, si les résultats de la requête sont utilisés par votre script (par exemple, lors de l'utilisation d'une instruction SELECT pour récupérer des enregistrements), la fonction sqlite_query() ne permettra pas l'exécution de plusieurs requêtes.


3. Vulnérabilité d'injection SQL INVISION Power BOARD

Invision Power Board est un système de forum bien connu. Le 6 mai 2005, une vulnérabilité d'injection SQL a été découverte dans le code de connexion. Son inventeur est James Bercegay de GulfTech Security Research.

Cette requête de connexion est la suivante :

$DB->query('SELECT * FROM ibf_members WHERE id=$mid AND password='$pid'');
Où , la variable d'ID de membre $mid et la variable d'ID de mot de passe $pid sont récupérées de la fonction my_cookie() à l'aide des deux lignes de code suivantes :

$mid = intval($std->my_getcookie('member_id ')) ;
$pid = $std->my_getcookie('pass_hash');
Ici, la fonction my_cookie() récupère les variables demandées du cookie à l'aide de l'instruction suivante :

return urldecode($ _COOKIE[$ibforums->vars['cookie_id'].$name]);
 【Remarque】La valeur renvoyée par ce cookie n'est fondamentalement pas traitée. Bien que $mid soit converti en un entier avant d'être appliqué à la requête, $pid reste inchangé. Par conséquent, il est vulnérable aux attaques de type injection dont nous avons parlé plus tôt.

Par conséquent, en corrigeant la fonction my_cookie() comme suit, cette vulnérabilité sera exposée :

if ( ! in_array( $name, array('topicsread', 'forum_read', 'collapseprefs ') ) )
{
return $this->
clean_value(urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name])) ;
}
else
{
return urldecode($_COOKIE[$ibforums->vars['cookie_id'].$name]);



>
Après une telle correction, les variables clés sont renvoyées après avoir « passé » la fonction globale clean_value(), tandis que les autres variables ne sont pas vérifiées.

Maintenant que nous avons une compréhension générale de ce qu'est l'injection SQL, de son principe d'injection et de la vulnérabilité de cette injection, explorons comment la prévenir efficacement. Heureusement, PHP nous fournit des ressources abondantes, nous pouvons donc prédire en toute confiance qu'une application soigneusement et minutieusement construite à l'aide de nos techniques recommandées éliminera fondamentalement toute possibilité d'injection SQL de vos scripts - Ceci est réalisé en « liquidant » vos utilisateurs. données avant qu’elles puissent causer des dommages.

4. Définissez chaque valeur dans votre requête

Nous vous recommandons de vous assurer de définir chaque valeur dans votre requête. Les valeurs de chaîne sont les premières à être affectées, ainsi que le contenu pour lequel vous vous attendez normalement à utiliser des guillemets « simples » (plutôt que « doubles »). D'une part, si vous utilisez des guillemets doubles pour permettre à PHP d'échanger des variables au sein d'une chaîne, cela peut faciliter la saisie des requêtes. D'autre part, cela (certes, seulement dans une très petite mesure) réduira également le besoin de PHP à l'avenir ; Travail d'analyse de code.

Ensuite, utilisons la requête sans injection que nous avons utilisée au début pour illustrer ce problème :

SELECT * FROM wines WHERE variété = 'lagrein'
Ou en instruction PHP Exprimé as :

$query = 'SELECT * FROM wines WHERE variété = '$variety'';
Techniquement parlant, les guillemets n'ont pas besoin d'être appliqués aux valeurs numériques. Cependant, si cela ne vous dérange pas d'utiliser des guillemets autour d'une valeur pour un champ comme wine et si votre utilisateur entre une valeur nulle dans votre formulaire, alors vous verrez quelque chose comme ceci : Requête :

SELECT * FROM wines WHERE vintage =
Bien sûr, cette requête est syntaxiquement invalide ; cependant, la syntaxe suivante est valide :

SELECT * FROM wines WHERE vintage = ''
La deuxième requête renverra (probablement) rien, mais au moins il ne renverra pas de message d'erreur.


5. Vérifiez le type de valeur soumise par l'utilisateur

De la discussion précédente, nous pouvons voir que jusqu'à présent, l'origine importante de l'injection SQL est souvent en panne lors d'une importation de formulaire inattendue. Cependant, lorsque vous offrez à l'utilisateur la possibilité de soumettre certaines valeurs via un formulaire, vous devriez avoir une bonne idée de la saisie que vous souhaitez obtenir - cela peut faciliter la vérification de la validité de la saisie de l'utilisateur. Nous avons déjà discuté de ces en-têtes de vérification dans des articles précédents ; nous ne résumerons donc ici que brièvement les points clés dont nous avons alors discuté. Si vous recherchez un nombre, vous pouvez utiliser l'une de ces techniques pour vous assurer que vous obtenez réellement un type numérique :

Utilisez la fonction is_int() (ou is_integer() ou is_long()) .

 · Appliquez la fonction gettype().

 · Appliquez la fonction intval().

 · Appliquez la fonction settype().

Pour vérifier la longueur de la saisie utilisateur, vous pouvez utiliser la fonction strlen(). Pour vérifier si une heure ou une date souhaitée est valide, vous pouvez utiliser la fonction strtotime(). Cela garantira presque certainement que l'importation d'un utilisateur ne contient pas de caractère point-virgule (à moins que la ponctuation puisse être légitimement incluse). Vous pouvez facilement y parvenir à l'aide de la fonction strpos(), comme indiqué ci-dessous :


if( strpos( $variety, ';' ) ) exit ( '$variety est une valeur non valide pour la variété !' );
Comme nous l'avons mentionné précédemment, tant que vous analysez soigneusement vos attentes en matière de saisie utilisateur, vous devriez être en mesure de détecter facilement la présence de nombreux problèmes.

6. Filtrez tous les caractères suspects de votre requête

Bien que dans les articles précédents, nous ayons discuté de la façon de filtrer les titres contenant des caractères dangereux, mais ici, exagérons brièvement et résumons ce titre ; encore une fois :

· N'utilisez pas la commande magic_quotes_gpc ou sa fonction 'partenaire en coulisses'-addslashes(), qui est restreinte dans le développement d'applications et cette fonction demande également l'application d'une étape supplémentaire -. l'application de la fonction stripslashes().

 · En comparaison, la fonction mysql_real_escape_string() est plus couramment utilisée, mais elle a aussi ses propres défauts.

Ce qui précède est la deuxième partie de l'interdiction complète des attaques par injection SQL en PHP. Pour plus de contenu connexe, veuillez faire attention au site Web chinois de PHP (www.php.cn) !


Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal