Dans l'article précédent, nous avons déjà parlé de l'essence des vulnérabilités des attaques par injection SQL causées par un codage incorrect par les programmeurs. Nous allons maintenant continuer à parler de la façon de coder correctement pour ne pas être attaqué par l'injection SQL. problème Jetons d'abord un coup d'œil à un morceau de code :
Copiez le code comme suit :
faible sql_injdata,SQL_inj,SQL_Get,SQL_Data,Sql_Post
SQL_injdata = '|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare
SQL_inj = divisé(SQL_Injdata,|)
Si Request.QueryString<> Alors
Pour chaque SQL_Get dans Request.QueryString
Pour SQL_Data = 0 vers Ubound (SQL_inj)
si instr(Request.QueryString(SQL_Get),Sql_Inj(Sql_DATA))>0 Alors
Response.Write <Script Language=javascript>alert('Invite du système anti-injection SQL, veuillez ne pas réessayer d'injecter !'); history.back(-1)</Script>
Réponse.end
finir si
suivant
Suivant
Fin si
Si Request.Form<> Alors
Pour chaque Sql_Post dans Request.Form
Pour SQL_Data = 0 vers Ubound (SQL_inj)
si instr(Request.Form(Sql_Post),Sql_Inj(Sql_DATA))>0 Alors
Response.Write <Script Language=javascript>alert('Invite du système anti-injection SQL, veuillez ne pas réessayer d'injecter !'); history.back(-1)</Script>
Réponse.end
finir si
suivant
suivant
finir si
Il s'agit d'un morceau de code anti-injection ASP très populaire sur Internet. L'idée est de vérifier les données soumises par la méthode Post et la méthode Get, et d'empêcher l'injection SQL en filtrant les caractères sensibles tels que Insert, Update et And. , etc. En théorie, si nous filtrons suffisamment de caractères, nous pouvons certainement garantir que nous ne serons pas attaqués par injection SQL, mais soyez prudent. Lisez ce code et faites attention à la façon dont il est jugé. Il est jugé via la fonction instr. C'est-à-dire que si je veux filtrer le caractère et, ce n'est pas seulement le mot Et qui est filtré, mais aussi tous les mots. contenant et. Tous les mots avec les combinaisons de caractères suivantes ont été filtrés, comme île, continent, main... Si ces caractères étaient filtrés, est-ce que quelqu'un serait encore prêt à les utiliser ? Par conséquent, cette méthode de filtrage des caractères sensibles n'a aucun sens. Ce qui me surprend, c'est qu'une telle poubelle soit en fait publiée sur Internet comme un classique.
Certaines personnes disent que les attaques par injection SQL sont causées par l'épissage des chaînes de requête SQL. Par conséquent, l'utilisation de procédures stockées sans épissage des chaînes de requête SQL peut vous protéger contre les attaques par injection SQL. Pas nécessairement, regardons un exemple d’attaque par injection de procédure stockée.
Le code de la procédure stockée dt_GetNews est le suivant :
CRÉER UNE PROCÉDURE dt_GetNews
@newstype int
COMME
sélectionnez * parmi les actualités où newstype=@newstype
ALLER
Code d'appel :
<%
faible connexion
définir adoconnection=server.createobject(adodb.connection)
'.........Le code pertinent pour établir une connexion à la base de données est omis ici
adoconnection.execute exec dt_GetNews +request(newstype)
adoconnection.close
%>
Si la valeur de request(newstype) est égale à 1, le résultat de l'opération est de renvoyer tous les enregistrements dont le champ newstype dans la table news est 1. Cependant, si la valeur de request(newstype) est 1, supprimez la table news ; , le résultat renvoyé est que la table news est supprimée.
Cet exemple montre que même l'utilisation de procédures stockées sera toujours attaquée. De plus, sélectionnez * from news où newstype=@newstype n'est pas épissé, il n'y a donc pas de lien inévitable entre l'épissage des chaînes de requête SQL et les attaques par injection SQL. les procédures stockées peuvent ne pas être en mesure de protéger contre les attaques par injection.
Alors, comment l'écrire sans être attaqué par l'injection SQL ? Ci-dessous, je vais présenter une méthode ultime, pour le dire franchement, elle est très simple et primitive, qui est la vérification du type de données et le remplacement des guillemets simples. Qu'il s'agisse d'Oracle, Sql Server, mySql, Access ou d'autres bases de données relationnelles, les types de champs peuvent être grossièrement divisés en deux catégories : les types numériques (tels que int, float, etc.) et les types de caractères (tels que char, varchar, etc. ). Les instructions SQL correspondantes sont légèrement différentes selon le type de champ, telles que :
Le champ newstype dans Select * from news où newstype=1 doit être un champ numérique.
sélectionnez * from news où newstype='social news' le champ newstype doit être un champ de caractères.
Pour les champs numériques, nous devons vérifier le type de données du paramètre. Par exemple, lorsque nous construisons une instruction de requête en utilisant select * from news où newstype=+v_newstype, nous devons vérifier le type de données de la variable v_newstype. est au moins Il doit s'agir d'un nombre, qui peut être un nombre entier ou un nombre à virgule flottante. Si une telle vérification est effectuée, sélectionnez * from news où newstype=+v_newstype ne construira jamais quelque chose de similaire pour select * from newswhere newstype=1. ;baisse Des déclarations comme les nouvelles de table. La raison pour laquelle ASP est plus vulnérable aux attaques qu'ASP.Net, JSP, etc. est que les variables dans ASP n'ont pas besoin d'être déclarées et que le type de variable n'est pas clair.
Pour les champs de caractères, ce que nous devons faire est de traiter les guillemets simples ('). La méthode de traitement consiste à remplacer un guillemet simple par deux guillemets simples (''). Par exemple, nous utilisons select * from news où. Lorsque newstype='+v_newstype+' est utilisé pour construire l'instruction de requête, le guillemet simple dans v_newstype doit être remplacé par deux guillemets simples, car en SQL, la partie entourée de deux guillemets simples représente une chaîne et deux guillemets simples consécutifs. quote représente un guillemet simple. Après un tel traitement, nous examinerons la méthode de construction de select * from news où newstype='+v_newstype+' Lorsque la valeur de v_newstype est :
Actualités sociales';drop table news--
Après avoir remplacé un guillemet simple par deux guillemets simples, la valeur de v_newstype devient :
Actualités sociales'';drop table news--
L'instruction SQL construite devient :
sélectionnez * parmi les actualités où newstype='social news'';drop table news—'
Le résultat de la requête est de renvoyer les enregistrements dont la valeur du champ newstype dans la table news est social news';drop table news--, sans entraîner la suppression de la table news comme auparavant.
De plus, ce n'est pas seulement l'instruction Select qui doit être traitée, y compris Insert, Update, Delete, Exec, etc., vous pouvez jeter un œil aux méthodes d'injection suivantes :
Dans la structure insérer dans news(title) valeurs('+v_title+'),
Quand v_title=123';drop table news--';
Lorsque vous mettez à jour news set /> lorsque v_title=123'-- ou v_id=1;drop table news--, ce n'est donc pas seulement un problème avec l'instruction Select, mais d'autres instructions peuvent avoir des problèmes, ne vous concentrez pas uniquement sur Select
Bref, après avoir vérifié le type de données et traité les guillemets simples, même s'il possède toutes les capacités, il ne pourra pas sortir de la paume de mon Tathagata.