Trucsweb.com

ASP

Validation de formulaire

RDFFav

Validation de formulaire

Saisir le bon type de données ou les convertir et protéger votre base de données conetre les attaques.validation formulaire form valider, injection SQL, SQL injection, Cross-site scripting (XSS)
  • · Niveau : INTERMÉDIAIRE
  • · Compatibilité : Windows NT/2000 IIS3

Saisir le bon type de données ou les convertir et surtout protéger votre base de données contre les attaques.

Déjà s’assurer de saisir le bon type de valeur. En HTML5 nous avons la possibilité de saisir le bon type à la source :

  • Type texte : search, email, url, tel, date, week, mont, color, datetime, datetime-local, time
  • Type numérique : number, range
  • Attribut : « required » pour forcer l’usager à saisir le champ.
  • Pattern : pattern="\d{1,2}/\d{1,2}/\d{4} pour saisir une date par exemple.
<form>
  <fieldset>
    <legend>Validation HTML5 de la date</legend>
    <label>Date : <input type="text" size="12" required pattern="\d{1,2}/\d{1,2}/\d{4}" placeholder="dd/mm/yyyy" name="hDate"></label>
    <label>Heure : <input type="text" size="12" pattern="\d{1,2}:\d{2}([ap]m)?" name="hHeure"></label>
    <input type="submit" />
  </fieldset>
</form>

Non seulement on ne s’assure pas des autres types (date, real, money)... Mais en plus le HTML5 n’est pas toujours compatible. On ne peut pas s’y fier! C’est pourquoi il faut TOUJOUR refaire une validation et même deux fois plutôt qu’une! C’est-à-dire une première en JavaScript et une seconde au niveau du serveur.

En JavaScript
// Par exemple vérifier qu'un nombre est bien un nombre :
function twNombre(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}
Autre exemple complet pour valider une date
// JavaScript original de Chirp Internet: www.chirp.com.au
// Ajusté par les Trucsweb.com
<script>
function twValideDate(field) {
  var allowBlank = true;
  var minYear = 1902;
  var maxYear = (new Date()).getFullYear();
  var errorMsg = "";

  // Expression régulière pour matcher le format de date
  // yyyy-mm-dd
  re = /^(\d{4})-(\d{1,2})-(\d{1,2})$/

  if(field.value != '') {
    if(regs = field.value.match(re)) {
      if(regs[3] < 1 || regs[3] > 31) {
        errorMsg = "Date invalide : " + regs[3];
      } else if(regs[2] < 1 || regs[2] > 12) {
        errorMsg = "Mois invalide : " + regs[2];
      } else if(regs[1] < minYear || regs[1] > maxYear) {
        errorMsg = "Année invalide : " + regs[1] + " - doit être entre " + minYear + " et " + maxYear;
      }
    } else {
      errorMsg = "format de date invalide : " + field.value;
    }
  } else if(!allowBlank) {
    errorMsg = "Vous devez saisir une date valide!";
  }
  if(errorMsg != "") {
     alert(errorMsg);
     field.focus();
     return false;
   }
   return true;
}

function twValideformulaire(oForm) {
  if(!twValideDate(oForm.hDate)) return false;
  return true;
}
</script>

<form onsubmit="return twValideformulair(this);">
  <fieldset>
    <legend>Validation JavaScript de la date</legend>
    <label>Date : <input type="text" size="12" placeholder="yyyy/mm/dd" name="hDate"> <small>(dd/mm/yyyy)</small></label>
    <label>Heure : <input type="text" size="12" name="hHeure"> <small>(ex. 18:17 ou 6:17pm)</small></label>
    <input type="submit">
  </fieldset>
</form>

C’est déjà ça, et pourquoi stresser le serveur quand la validation peut se faire localement. Malheureusement et malgré de nombreuses applications gratuites sur le Web, l’usager peut désactiver son JavaScript! Consultez « Fonction de validation twValide version 2.2 - Validation de formulaire côté client »

Côté serveur

Efficace, y a pas mieux pour valider les valeurs avant l’ajout dans la base de données. Et d’ailleurs c’est très simple en ASP, il suffit de la bonne méthode pour le bon type de données.

Il y a déjà la fonction VarType :

dim maVar : maVar = "Texte"
response.write VarType(maVar)

' Résultat 4

'  Exemple avec une date
if VarType(request.form("date")) = 7 then
  ' Date valide
else
  ' Date invalide
end if

La table de référence :

  • 0 = vbEmpty - Indique Empty (noninitialisé)
  • 1 = vbNull - Indique Null (valeur non valide)
  • 2 = vbInteger - Indique un nombre entier (integer)
  • 3 = vbLong - Indique un nombre entier long (long integer)
  • 4 = vbSingle - Indique un nombre réel de simple-précision (floating-point number)
  • 5 = vbDouble - Indique un nombre réel de double-précision (floating-point number)
  • 6 = vbCurrency - Indique une devise
  • 7 = vbDate - Indique une date
  • 8 = vbString - Indique une chaine de caractères (string)
  • 9 = vbObject - Indique un objet
  • 10 = vbError - Indique une erreur
  • 11 = vbBoolean - Indique une booléenne
  • 12 = vbVariant - Indique un « variant »
  • 13 = vbDataObject - Indique un objet de données
  • 17 = vbByte - Indique un « byte »
  • 8192 = vbArray - Indique une matrice (array)

Ou encore directement avec :

  • IsDate : Retourne une valeur booléenne qui indique si la variable peut être évaluée comme un type date.
  • IsEmpty : Retourne une valeur booléenne qui indique si la variable est initialisée ou pas.
  • IsNull : Retourne une valeur booléenne qui indique si la variable ne contient aucune valeur valide (Null).
  • IsNumeric : Retourne une valeur booléenne qui indique si la variable peut être évaluée comme un type nombre.

Enfin il y a aussi la méthode de la conversion systématique. Avec la plupart des fonctions VBScript : fonctions conversion, de date et de temps, format, mathématique, de chaine de caractères (string)...

if isNumeric(request.form(champ)) then
  ' Champ numérique
else
  ' Erreur, champ non numérique
end if

if isDate(request.form(champ)) then
  ' Champ date
else
  ' Erreur, champ non date
end if
Injections SQL

Oui, surtout, car faire planter la base de données à cause d’une mauvaise valeur est une chose. Mais planter une base de données voir la corrompe à cause d’une attaque en règle en est une autre.

Personnellement je teste toujours et systématiquement chaque requête « querystring » au serveur. Il suffit d’avoir été piraté pour comprendre l’importance de cette validation. Une simple injection SQL peut remplir votre base de données de code JavaScript malsain. Donc en plus de perdre vos données, vous participer à votre tour et à votre insu en propagent l’attaque à votre tour. Exactement comme un virus. Sauf que c’est votre serveur IIS qui sème la terreur à chaque fois qu’un utilisateur ouvre une page! Consultez Wikipedia - Injection SQL

L’idée est simple, détecter ce type d’attaque qui est toujours la même :

Considérez que vous avez une simple connexion qui demande à l’usager un ID. Et que l’usager entre comme ID « 105 or 1 = 1 » :

dim sID, sSQL
sID = request.querystring("id");
sSQL = "select * from t_usager where v_usager_id = " + sID;

' Le résulta de la requête sera donc.
« select * from t_usager where v_usager_id = 105 or 1 = 1 »

' 1 = 1 étant toujours vrais, il est possible de cette manière d'obtenir d’outrepasser la condition et obtenir ainsi une liste complète des usagers!

Il suffit donc en premier lieu de limiter le nombre de caractères, puis de limiter le type de saisie, c’est-à-dire de type nombre et surtout pas symbole, comme le « = ».

Mais il existe des requêtes beaucoup plus complexe. Je ne donnerais pas ici l’exemple, mais en une seule instruction on peut non seulement demander la structure de la base de données, mais boucler chaque champ de chaque table et modifier le contenu de chacun de ses champs avec une nouvelle valeur, en l’occurrence un JavaScriprt malsain... Et croyez-moi, ce n’est pas une expérience que l’on veut vivre!

C’est pourquoi j’utilise ce petit bout de code dans mon fichier global qui détecte et capture toutes requêtes au serveur et supprimer les mnémoniques et mots-clés les plus dangereux : update delete drop declare nvarchar chr( cast( ;set%

dim sChaineSQComplete
sChaineSQComplete = request.servervariables("QUERY_STRING") 
' Si je trouve la requête louche,
' je garde une trace dans un fichier log.
' avec une redirection, générallement vers Walt Disney.
if twVerifieInjectionSQL(sChaineSQComplete) = false then
 Dim sChaineQS
 for each oItem in request.servervariables
  sChaineQS = sChaineQS & oItem & "=" & request.servervariables(oItem) & vbcrlf
 next
 call twLogHack([chemin]","trapHack",sChaineQS)
 response.redirect("http://www.waltdisney.com/")
end if

function twVerifieInjectionSQL(sChaineTempHack)
 sChaineTempHack = lcase(sChaineTempHack)
 sMotsInjectes = "update delete drop declare nvarchar chr( cast( ;set%"
 aQS = split(sMotsInjectes, " ")
 for nIhack =0 to ubound(aQS)
  if instr(sChaineTempHack, aQS(nIhack)) > 0 then
       twVerifieInjectionSQL = false
   exit function
  end if
 next
 twVerifieInjectionSQL = true
end function

Et voilà, c’est tout. De cette manière, en la combinant avec les tests de base, vous pouvez éviter la plupart des attaques.

En plus, à chaque saisie, d’un simple ID à un formulaire complexe, dès que je dois ajouter une valeur à la base de données, je lui applique cette conversion supplémentaire :

Function twProtegeSQL(sMots)
  dim sTemp
  sTemp = replace(sMots,"^","")
  sTemp = replace(sTemp,"’","’")
  sTemp = replace(sTemp,"Or 1=1","HACK")
  sTemp = replace(sTemp,"--","")
  sTemp = replace(sTemp,";","")
  sTemp = replace(sTemp," OR "," ")
  sTemp = replace(sTemp," or "," ")
  sTemp = replace(sTemp," NOT "," ")
  sTemp = replace(sTemp," not "," ")
  sTemp = replace(sTemp," IN "," ")
  sTemp = replace(sTemp," in "," ")
  sTemp = replace(sTemp," = "," ")
  sTemp = replace(sTemp,"update","HACK")
  sTemp = replace(sTemp,"UPDATE","HACK")
  sTemp = replace(sTemp,"declare","HACK")
  sTemp = replace(sTemp,"DECLARE","HACK")
  sTemp = replace(sTemp,"nvarchar","HACK")
  sTemp = replace(sTemp,"NVARCHAR","HACK")
  sTemp = replace(sTemp,"chr(","HACK")
  sTemp = replace(sTemp,"CHR(","HACK")
  sTemp = replace(sTemp,"cast(","HACK")
  sTemp = replace(sTemp,"CAST(","HACK")
  sTemp = replace(sTemp,";SET%","HACK")
  sTemp = replace(sTemp,";set%","HACK")
  sTemp = replace(sTemp,"delete","HACK")
  sTemp = replace(sTemp,"DELETE","HACK")
  'sTemp = replace(sTemp,"input","HACK")
  'sTemp = replace(sTemp,"INPUT","HACK")
  sTemp = replace(sTemp,"insert into","HACK")
  sTemp = replace(sTemp,"INSERT INTO","HACK")
  'sTemp = replace(sTemp,"insert","HACK")
  'sTemp = replace(sTemp,"INSERT","HACK")
  sTemp = replace(sTemp,"remove","HACK")
  sTemp = replace(sTemp,"REMOVE","HACK")
  sTemp = replace(sTemp,"execute","HACK")
  sTemp = replace(sTemp,"EXECUTE","HACK")
  sTemp = replace(sTemp,"''","")
  twProtegeSQL = trim(sTemp)
End Function
Conclusion

Et voilà, c’est aussi simple que ça. Pour éviter la grande majorité des problèmes de format, de piratage et d’injection SQL. L’idéale est d’encapsuler le tout en fonction globale appelé systématiquement après chaque saisie de formulaire, de la simple recherche au formulaire de gestion complexe.

Django (Oznog) Blais
Dernière mise à jour :

Commentaires

10/10 sur 1 revues.
       Visites : 793 - Pages vues : 1655
X

Trucsweb.com Connexion

Connexion

X

Trucsweb.com Mot de passe perdu

Connexion

X

Trucsweb.com Conditions générales

Conditions

Responsabilité

La responsabilité des Trucsweb.com ne pourra être engagée en cas de faits indépendants de sa volonté. Les informations mises à disposition sur ce site le sont uniquement à titre purement informatif et ne sauraient constituer en aucun cas un conseil ou une recommandation de quelque nature que ce soit.

Aucun contrôle n'est exercé sur les références et ressources externes, l'utilisateur reconnaît que les Trucsweb.com n'assume aucune responsabilité relative à la mise à disposition de ces ressources, et ne peut être tenue responsable quant à leur contenu.

Droit applicable et juridiction compétente

Les règles en matière de droit, applicables aux contenus et aux transmissions de données sur et autour du site, sont déterminées par la loi canadienne. En cas de litige, n'ayant pu faire l'objet d'un accord à l'amiable, seuls les tribunaux canadien sont compétents.

X

Trucsweb.com Trucsweb

X

Trucsweb.com Glossaire

X

Trucsweb.com Trucsweb

X

Trucsweb.com Trucsweb

Conditions

Aucun message!

Merci.

X
Aucun message!
X

Trucsweb.com Créer un compte

Créer un compte

.
@