formateur informatique

Authentification sécurisée anti-keylogger en Javascript

Accueil  >  Technique  >  Javascript  >  Javascript Avancé  >  Authentification sécurisée anti-keylogger en Javascript
Livres à télécharger


Pour partager cette vidéo sur les réseaux sociaux, voici son url absolue :

Pour l'intégrer sur votre site internet ou blog, vous pouvez l'embarquer :

Sujets et formations similaires :


Connexion sécurisée Anti-Keylogger en Javascript

Dans cette formation Javascript, nous proposons de bâtir un système d'authentification sécurisée anti-Keylogger, comme le proposent les banques, afin de protéger la saisie du mot de passe pour accéder aux comptes en ligne. Un Keylogger est un programme malveillant qui enregistre les touches du clavier au fur et à mesure de la frappe de l'internaute. Ces informations sont retournées aux hackeurs avec l'Url de la page concernée. Dès lors, ils peuvent pirater les informations bancaires et se servir.

Authentification Internet sécurisée, saisie protégée par des boutons de code aléatoires en Javascript



La solution consiste à imposer la saisie du mot de passe par clics sur des images ou boutons numérotés, qui se positionnent aléatoirement à chaque nouvelle connexion. C'est ce qu'illustre l'application finalisée sur la capture. Seul l'oeil humain peut repérer sans ambigüité la position des numéros pour reconstruire le mot de passe afin de valider l'identification.

Sources et présentation du concept
Pour concentrer notre attention sur la partie du développement en Javascript, nous proposons de récupérer les sources qui offrent la structure de la page Web de connexion. La décompression conduit au fichier de la page Web principale à la racine, accompagné de ses ressources externes dans les sous dossiers.
  • Double cliquer sur le sous dossier js pour l'ouvrir,
  • Puis, cliquer avec le bouton droit de la souris sur le fichier de script : paire_id.js,
  • Dans le menu contextuel, choisir de l'ouvrir avec un éditeur tel que le Notepad,
Ce script externe propose une seule fonction retournant la paire identifiant et mot passe permettant de réussir l'authentification, selon le code suivant :

functionid_mp()
{
var paire='bonbache|622551';
return paire;
}


Bien sûr, il s'agit ici d'une simulation. Jamais une application en production ne devra livrer des renseignements aussi sensibles sans les protéger. Le code Javascript doit se charger du positionnement aléatoire des numéros et de récolter les informations d'identification saisies. C'est le développement que nous devons réaliser ici. Ensuite, il doit transmettre ces informations à un code serveur Php qui pourra interroger la base de données, afin de valider ou non la correspondance. Mais comme il n'est pas question de code serveur ici, nous simulons le principe de transmission des informations, par le biais d'un script externe.
  • A la racine du dossier de décompression, double cliquer sur le fichier identification-securisee-cpt.html pour l'ouvrir dans un navigateur par défaut,
Structure Html pour page identification Web sécurisée pour empêcher saisie mot de passe

Comme vous le constatez, la page Web offre en effet la structure Html principale. Les boutons numérotés sont absents. Et les fonctionnalités de contrôle de saisie et de validation sont inopérantes. Il s'agit du code Javascript à bâtir.

L'objectif est de positionner aléatoirement 10 boutons, numérotés de 0 à 9, dans les cases de la grille située sur la gauche. Cette grille est réalisée par l'imbrication de calques, soit de balises Html Div. Au clic sur chaque bouton, le numéro correspondant doit s'ajouter à la suite dans la zone du mot de passe crypté. Ce contrôle Html de type Password est d'ailleurs verrouillé à la saisie pour protéger la connexion contre les Keyloggers. L'identifiant quant à lui doit être tapé au clavier. Un clic sur le bouton Valider doit déclencher un autre code Javascript capable de comparer cette paire avec les données d'authentification. Si le test échoue, la connexion est refusée. Dans le cas contraire, elle est autorisée et les données sensibles ont été protégées.
  • A la racine du dossier de décompression, cliquer avec le bouton droit de la souris sur le fichier de la page Web identification-securisee-cpt.html,
  • Dans le menu contextuel, choisir de l'ouvrir avec un éditeur tel que le Notepad ++,
Dans la section Head du code Html, vous notez la référence au script externe :

...
<meta http-equiv='content-language' content='fr' />
<link href='styles/mef.css' rel='stylesheet' type='text/css' />
<script language='Javascript' src='js/paire_id.js'></script>
</head>
<body>
...


Il est ainsi chargé en même temps que la page Web de connexion. Donc sa fonction id_mp peut être appelée par son nom, pour réaliser la comparaison des informations en Javascript.

Entre les lignes 50 et 77 pour un éditeur Notepad, figure l'imbrication des calques ayant permis la construction de la grille notamment. On y trouve aussi les contrôles Html des boutons qui devront déclencher le code des fonctions au clic.

...
<div class='colonne' id='liste'>
<div id='grille'>
<div class='case' id='case0'></div>
<div class='case' id='case1'></div>
<div class='case' id='case2'></div>
<div class='case' id='case3'></div>
<div class='case' id='case4'></div>
<div class='case' id='case5'></div>
<div class='case' id='case6'></div>
<div class='case' id='case7'></div>
<div class='case' id='case8'></div>
<div class='case' id='case9'></div>
<div class='case' id='case10'></div>
<div class='case' id='case11'></div>
<div class='case' id='case12'></div>
<div class='case' id='case13'></div>
<div class='case' id='case14'></div>
<div class='case' id='case15'></div>
</div>
<input type='text' id='identifiant' maxlength='10' value='Votre identifiant' onClick='init_saisie('1')' onMouseOut='init_saisie('2')'/>
<input type='password' id='motPasse' maxlength='6' value='' readOnly />
<input type='button' class='bouton' value='Valider' />
<input type='button' class='bouton' value='Generer' /><br />
<span style='font-size:14px;font-weight:normal;'>Paire à reproduire :
<strong>bonbache|631975</strong></span>
</div>
...


Vous constatez que chaque case de la grille est judicieusement nommée grâce à son attribut Id. Chaque calque est en effet préfixé de l'information statique case, associée à un numéro incrémenté. Cette désignation facilitera grandement le développement pour placer aléatoirement les boutons en fonction du nombre généré.

Enfin, en bas du code Html, vous notez la présence d'une section de Script Javascript. La fonction init_saisie est déjà présente. Elle est appelée par la zone de saisie de l'identifiant sur deux événements : OnClick et OnMouseOut. Elle permet tout simplement de vider la zone ou de restituer l'information par défaut, pour guider l'utilisateur.



Placement aléatoire des numéros d'identification
La formation Javascript pour générer des nombres aléatoires nous avait appris à maîtriser cette technique. La grille est constituée de 16 cases identifiées par un nom affublé d'un indice variant de 0 à 15. Nous devons donc générer un nombre aléatoire entier compris entre ces bornes. Cette génération aléatoire doit être reproduite 10 fois, pour chacun des boutons numérotés à disposer indépendamment. Nous devons donc nous assurer que le même nombre ne ressorte jamais deux fois, pour que ces boutons ne se chevauchent pas.

En bas de la page Html, dans la section du script, un appel anticipé de fonction existe : generation(). Mais cette fonction n'existe pas encore. Nous devons la créer. C'est elle, qui par génération aléatoire, doit positionner les boutons permettant d'inscrire le mot de passe.
  • Juste après cette ligne, créer la fonction generation comme suit :
function generation()
{

}


Comme son appel intervient en début de script, en dehors de toute fonction, son code Javascript sera exécuté en même temps que la page se charge.

Comme toujours, nous devons commencer par déclarer les variables nécessaires au traitement.
  • Dans les bornes de la fonction, ajouter les déclarations et l'instruction suivantes :
var nb_alea;
var test = true; var chaine = '';

purger();


La variable nb_alea doit permettre de stocker le nouveau nombre aléatoire généré, à chaque passage dans la boucle. 10 boutons sont à placer, donc dix nombres aléatoires compris entre les bornes 0 et 15, doivent être générés sans doublons. La variable test est déclarée comme un booléen et initialisée à true. Elle considère par défaut que le nombre aléatoire existe déjà, pour forcer la régénération. A chaque fois qu'un nombre aléatoire inédit sera produit, elle devra être affectée à False pour permettre à la boucle de traiter le bouton suivant. Justement, la variable chaine doit servir à concaténer tous les nombres aléatoires déjà produits, afin de réaliser cette vérification.

Enfin, nous appelons la fonction purger qui n'existe pas encore. Sa mission est de purger la grille des potentiels précédents boutons et de vider les zones de saisie. En effet, la fonction generation sera à terme appelée au clic sur le bouton Générer. L'objectif est de permettre à l'utilisateur de tout recommencer s'il s'est trompé. Avant de poursuivre le développement de la fonction generation, nous devons donc coder la fonction purger.
  • Après la fonction generation, créer la fonction purger, comme suit :
function purger()
{
for (var i=0;i<16;i++)
{
document.getElementById('case' + i).innerHTML = '';
}
document.getElementById('identifiant').value = 'Votre identifiant';
document.getElementById('motPasse').value = '';
}


Nous initialisons une boucle de traitement pour parcourir l'ensemble des calques de la grille, numérotés de 0 à 15. A chaque passage dans la boucle, nous accédons à chacun d'entre eux, grâce à la méthode getElementById de l'objet Javascript document. Nous passons à cette méthode l'identifiant fixe ('case') concaténé à la valeur de la variable de boucle, qui varie bien de 0 à 15, soit les 16 calques. Après la boucle, toujours avec la méthode getElementById pour désigner un contrôle Html, nous accédons aux deux zones de saisie. Celle de l'identifiant est réinitialisée à sa valeur informative par défaut, tandis que celle du mot de passe est vidée.

Il s'agit maintenant de reprendre le développement de la fonction generation. Nous devons passer en revue l'ensemble des 10 boutons.
  • A la suite du code de la fonction generation, après l'appel de la fonction purger, créer la boucle for suivante :
for (var i=0;i<10;i++)
{

}


10 passages seront donc réalisés par cette boucle. A l'intérieur de ce traitement récursif, nous devons générer un nombre aléatoire pour placer le bouton ainsi désigné dans le calque Html correspondant. Mais cette action ne vaut que si le nombre aléatoire n'a pas encore été généré. Et c'est la variable test qui l'indique. Nous devons donc l'exploiter en critère d'une boucle While. Ainsi elle ordonnera la régénération, tant que le nombre existe déjà.
  • Dans les bornes de la boucle for, ajouter les lignes suivantes :
while (test==true)
{
nb_alea = Math.floor(Math.random()*16);
}


Comme prévu, nous devons désormais nous assurer que ce nombre aléatoire n'a pas déjà été produit. S'il existe déjà, il doit être regénéré. Comme le test vaut toujours true, cette action doit se répéter jusqu'à produire un nombre nouveau. Dans le cas contraire, le code Html du bouton désigné par la variable i doit être écrit dans le calque Html désigné par la variable nb_alea. Ce nouveau nombre doit être mémorisé par concaténation dans la variable chaine. Et puis, le booléen doit être basculé à False, pour sortir de la boucle While et passer au bouton suivant, grâce à la reprise de la boucle For.
  • En conséquence, à la suite du code de la boucle While, ajouter les instructions suivantes :
if(chaine.indexOf('-' + nb_alea + '-')>-1)
nb_alea = Math.floor(Math.random()*16);
else
{
document.getElementById('case' + nb_alea).innerHTML = '<input type='button' class='btn' value='' + i + '' onClick='document.getElementById('motPasse').value += ' + i +'' />';
chaine += '-' + nb_alea + '-';
test=false;
}


C'est la méthode indexOf appliquée sur une variable de type chaîne de caractères, qui renvoie la position de l'occurrence qui lui est passée en paramètre. Nous l'avions exploitée dans la formation Javascript consistant à récupérer les paramètres d'Url. Elle permettait de renseigner sur la position du point d'interrogation (?), à partir duquel les informations étaient passées. Ici, nous cherchons la position de l'occurrence : '-' + nb_alea + '-'. A chaque passage en effet, nous concaténerons le nouveau nombre, encadré de tirets pour le reconnaître sans ambiguïté. Si la méthode indexOf ne retourne pas la valeur -1, cela signifie que le nombre existe déjà. En conséquence nous le régénérons.

Dans le cas contraire (else), grâce à la propriété innerHTML d'un contrôle Div, nous reconstruisons le code Html, du calque passé en paramètre de la méthode getElementById. Il s'agit du calque dont le suffixe correspond au nouveau nombre aléatoire généré entre bornes. Le code Html est celui d'un bouton sur lequel nous inscrivons le numéro (value='' + i + '') correspondant à la valeur en cours dans la boucle For. De même, nous générons son événement à la volée qui consiste à inscrire ce numéro à la suite (-=), dans le contrôle de type Password. Notez l'emploi du caractère d'échappement () pour pouvoir désigner l'identifiant du contrôle dans la méthode getElementById ('motPasse'). En effet, l'instruction Html est déjà encadrée de doubles côtes. L'instruction de l'événement onClick alterne entre simples côtes. Ni l'une ni l'autre ne peuvent donc être utilisées. Et c'est l'antislah qui permet de ne pas briser la construction de cette chaîne statique. Enfin, nous mémorisons ce nouveau nombre aléatoire à la suite (chaine += '-' + nb_alea + '-'). L'objectif est qu'il ne soit pas reproduit lors du prochain traitement. Puis, nous affectons la variable booléenne à false (test=false), pour pouvoir sortir de la boucle While et reprendre l'énumération des boutons dans la boucle For.

Un réglage est nécessaire avant de reprendre l'incrémentation de la boucle For. A la sorite de la boucle While, la variable booléenne doit être réaffectée à True. Si ce n'est pas le cas, le critère de la boucle While imbriquée ne sera jamais vérifié. En conséquence plus aucun nombre aléatoire ne sera généré.
  • Après la fermeture de la boucle While et avant la fermeture de la boucle For, ajouter l'instruction suivante :
test=true;

Notre code peut d'ores et déjà être testé au chargement de la page Web.
  • Enregistrer les modifications (CTRL + S) et basculer sur le navigateur Internet,
  • Rafraîchir la page Html à l'aide de la touche F5 du clavier,
Comme vous le constatez et comme l'illustre la capture ci-dessous, les 10 boutons sont bien présents et sont placés aléatoirement, dans les 16 cases qui leur sont proposées. Si vous cliquez sur ces derniers, les numéros encryptés se consolident dans le contrôle Password. Rappelons-le, ce dernier n'est pas accessible à la saisie, pour des raisons de sécurité.

Placement aléatoire des boutons pour saisie sécurisée du mot de passe

Avant de nous concentrer sur la fonction permettant de valider l'authentification, nous devons appeler la fonction generation au clic sur le bouton Generer. En cas de saisie erronée, l'internaute pourra réinitialiser le formulaire pour recommencer.
  • Revenir dans l'éditeur de code de la page Html,
  • Ajouter l'attribut permettant d'appeler la fonction generation, au clic sur le bouton Generer, situé à la ligne 75 pour un éditeur Notepad :
<input type='text' id='identifiant' maxlength='10' value='Votre identifiant' onClick='init_saisie('1')' onMouseOut='init_saisie('2')'/>
<input type='password' id='motPasse' maxlength='6' value='' readOnly   />
<input type='button' class='bouton' value='Valider' />
<input type='button' class='bouton' value='Generer' onClick='generation()'/><br />
<span style='font-size:14px; font-weight:normal;'>Paire à reproduire : <strong>bonbache|622551</strong></span>
</div>
  • Enregistrer les modifications et basculer sur le navigateur Internet,
  • Rafraîchir la page Web avec la touche F5 du clavier,
Dans un premier temps vous constatez que tous les boutons sont réorganisés aléatoirement, comme précédemment.
  • Saisir l'identifiant bonbache puis cliquer sur quelques boutons pour inscrire un mot de passe,
  • Cliquer alors sur le bouton Generer,
En même temps que les boutons sont replacés, toujours aléatoirement entre les cases 0 et 15, les zones de saisie sont effectivement réinitialisées. Et si vous cliquez de nouveau sur les boutons, vous notez que l'inscription du mot est toujours fonctionnelle.

Le code complet ayant permis le placement aléatoire des boutons pour une identification sécurisée, est le suivant :

function generation()
{
var nb_alea;
var test = true; var chaine = '';

purger();

for (var i=0;i<10;i++)
{
while (test==true)
{
nb_alea = Math.floor(Math.random()*16);
if(chaine.indexOf('-' + nb_alea + '-')>-1)
nb_alea = Math.floor(Math.random()*16);
else
{
document.getElementById('case' + nb_alea).innerHTML = '<input type='button' class='btn' value='' + i + '' onClick='document.getElementById('motPasse').value += ' + i +'' />';
chaine += '-' + nb_alea + '-';
test=false;
}
}
test=true;
}
}

function purger()
{
for (var i=0;i<16;i++)
{
document.getElementById('case' + i).innerHTML = '';
}
document.getElementById('identifiant').value = 'Votre identifiant';
document.getElementById('motPasse').value = '';
}




Valider l'authentification sécurisée
La paire de connexion utilisée par l'internaute pour s'identifier doit désormais être comparée avec les données d'identification fournies par le script externe. Ce code doit se déclencher au clic sur le bouton Valider. Nous devons donc créer cette fonction et l'appeler.
  • Revenir dans l'éditeur de code de la page Html,
  • Après la fonction purger, créer la fonction validation, comme suit :
function validation()
{

}


Nous avons besoin de variables pour récupérer les informations de connexion et les stocker indépendamment.
  • Dans les bornes de la fonction, ajouter les déclarations suivantes :
var combinaison = id_mp().split('|');
var ident = combinaison[0];
var mp = combinaison[1];


Tout d'abord, la méthode split appliquée sur une chaîne de caractères, permet de découper cette dernière sur l'occurrence qui lui est passée en paramètre. Dans la fonction du script externe, l'identifiant et le mot de passe sont en effet séparés par une barre verticale(|). Nous l'avions d'ailleurs exploitée dans la formation Javascript pour créer un album photo et dissocier toutes les images mémorisées. Le résultat de cette méthode a pour effet de transformer la variable qui est affectée, en tableau de variables. Ce dernier propose désormais autant de lignes que d'informations indépendantes sont rangées. Dans notre cas, il s'agit seulement de deux éléments : l'identifiant et le mot de passe. Le premier s'obtient en pointant sur la première ligne, repérée par l'indice 0 (combinaison[0]). Le second, fort logiquement, s'obtient en pointant sur l'indice 1.

Désormais, les informations d'identification sont clairement mémorisées et peuvent donc être comparées avec les données entrées par l'internaute. Pour que l'authentification soit un succès nous devons vérifier en même temps que les identifiants coïncident et que les mots de passe sont identiques. C'est encore une instruction conditionnelle Javascript qui va permettre de vérifier ce double critère exclusif.
  • A la suite du code de la fonction validation, ajouter les instructions suivantes :
if(document.getElementById('identifiant').value.toLowerCase() == ident.toLowerCase() && document.getElementById('motPasse').value == mp)
document.getElementById('apercu').innerText = 'Vous êtes désormais connecté';
else
document.getElementById('apercu').innerText = 'L'authentification a échoué';


C'est l'opérateur && dans une instruction conditionnelle Javascript, qui permet d'imposer la double vérification. Si l'un des deux critères n'est pas satisfait, la condition globale est considérée comme non remplie. La propriété value des contrôles Input Html permet d'accéder respectivement au contenu des éléments d'identifiant identificant et motPasse. La méthode Javascript toLowerCase permet de convertir les informations en minuscules pour qu'il n'y ait pas de différence de casse dans la comparaison.

Dans le cas où les deux conditions sont vérifiées, la propriété innerText du contrôle Div, permet d'inscrire un message de succès à l'authentification, dans le calque apercu situé en bas de la page Html. Dans le cas contraire, c'est un message d'échec qui est inscrit.

Nous devons maintenant appeler cette fonction au clic sur le bouton Valider.
  • Ajouter la gestion de l'événement du clic dans le code Html du bouton Valider, en ligne 74 pour un éditeur Notepad, comme suit :
<input type='text' id='identifiant' maxlength='10' value='Votre identifiant' onClick='init_saisie('1')' onMouseOut='init_saisie('2')' />
<input type='password' id='motPasse' maxlength='6' value='' readOnly   />
<input type='button' class='bouton' value='Valider' onClick='validation()'/>
<input type='button' class='bouton' value='Generer' onClick='generation()' /><br />
<span style='font-size:14px;font-weight:normal;'>Paire à reproduire : <strong>bonbache|622551</strong></span>
</div>
  • Enregistrer les modifications et basculer sur le navigateur Internet,
  • Rafraîchir la page avec la touche F5 du clavier,
  • Saisir un identifiant et cliquer sur les boutons de manière à inscrire un mot de passe erroné,
  • Cliquer sur le bouton valider,
Comme vous le remarquez, le message d'échec apparaît instantanément dans le calque inférieur.
  • Cliquer sur le bouton Générer pour replacer aléatoirement les boutons de code,
  • Saisir le bon identifiant : bonbache,
  • Puis inscrire le vrai mot de passe en cliquant sur les boutons dédiés : 622551,
  • Cliquer sur le bouton valider,
Validation identification sécurisée contrôlée en Javascript sur mot de passe inscrit par des boutons placés aléatoirement

Cette fois, l'identification est un succès comme en atteste le message du calque inférieur. Aucun des chiffres du mot de passe n'a été saisi au clavier. De plus, leur inscription par clic se fait depuis des emplacements perpétuellement renouvelés, grâce à ce positionnement aléatoire. La sécurisation de la connexion est donc un succès puisqu'aucun logiciel malveillant de type keylogger, n'est en mesure d'enregistrer les frappes du mot de passe.

Le code complet de la fonction validation est le suivant :

function validation()
{
var combinaison = id_mp().split('|');
var ident = combinaison[0];
var mp = combinaison[1];

if(document.getElementById('identifiant').value.toLowerCase() == ident.toLowerCase() && document.getElementById('motPasse').value == mp)
document.getElementById('apercu').innerText = 'Vous êtes désormais connecté';
else
document.getElementById('apercu').innerText = 'L'authentification a échoué';
}


Encore une fois, la fin de l'application doit consister en une transmission des informations du code Javascript à un code serveur Php. C'est lui qui doit se charger d'interroger la base de données afin de valider la correspondance de ces informations confidentielles. Néanmoins, nous avons ici parfaitement réussi à sécuriser l'application d'authentification, par le code client Javascript, afin d'empêcher l'enregistrement des caractères saisis.

 
Sur Facebook
Sur G+
Sur Youtube
Les livres
Contact
Mentions légales