web-dev-qa-db-fra.com

Empêcher l'utilisateur de trouver un mot de passe via Firebug / Chrome Dev Tools

Hidden Password

Pour le champ de saisie du passeport:

<input type="text" required="" tabindex="2" class="std_textbox" placeholder="Enter your account password." id="pass" name="pass">

Quand le <input type="password"> est remplacé par <input type="text"> Le mot de passe est révélé. Cela peut être risqué dans les systèmes qui ont enregistré des mots de passe ou généré à partir des gestionnaires de mots de passe.

Revealed Password

Le cryptage côté client peut-il être utilisé ici? Comment peut-il être mis en œuvre?

23
Manoj Kumar

Réponse courte: Cela ne peut malheureusement pas être évité. En effet, tout le code côté client (JavaScript) est modifiable par le client lui-même, ce qui rend un système de sécurité basé sur le client vulnérable.

La seule solution réalisable à laquelle je peux penser est de stocker une représentation hachée du mot de passe, au lieu du mot de passe brut. Cela (si vous ne tenez pas compte des attaques par hachage bruteforce) protégera le mot de passe brut.

Un hachage est une représentation du texte d'origine et n'est pas réversible. Autrement dit, la chaîne de caractères d'origine ne peut être récupérée par aucun algorithme, en utilisant uniquement le hachage. Des exemples de hachage 'sont MD5 et SHA. Cette technique est couramment utilisée dans les routeurs, où le mot de passe est souvent stocké dans le navigateur.

Clarification: Ne stockez jamais vos mots de passe en texte brut, et si vous souhaitez adopter cette technique de mot de passe pré-entré; le hachage et/ou le chiffrement doivent avoir lieu côté serveur.

21
Eric

J'ai vu des solutions dans différentes réponses. Dans chacun d'eux, il est juste plus difficile de voir le mot de passe, mais cela n'empêche pas quelqu'un de le voir.

Remarque : Du côté client, les objets JavaScript peuvent être manipulés et inspectés. Dans les solutions fournies dans d'autres réponses, je pouvais facilement accéder aux informations de mot de passe.


Comme d'autres l'ont indiqué, vous ne pouvez pas empêcher l'utilisateur d'afficher le mot de passe à l'aide des outils de développement côté client.

Je ne pouvais pas penser à un cas d'utilisation, mais vous avez mentionné remplisseur de formulaire automatique et l'option Souvenez-vous de moi.

Remplisseur de formulaire automatique, pour autant que je sache, sont protégés par un mot de passe principal. Ils devraient être; Je ne l'utiliserais pas si je ne pouvais pas l'allumer ou l'éteindre en toute sécurité. Dans ce cas, il est de ma responsabilité de me déconnecter, chaque fois que je suis en situation de partage d'un ordinateur.

Souvenez-vous de moi, comme souvent promu par les sites Web, ne devrait être utilisé que lorsque c'est votre ordinateur personnel et que vous ne vous attendez pas à partager votre appareil avec une autre personne. Ne l'utilisez pas et assurez-vous que personne d'autre n'utilise votre compte. Encore une fois, c'est votre responsabilité.

Maintenant, vous voyez toujours la nécessité d'empêcher une telle attaque. Tout ce que je peux trouver est le suivant:

  1. Il n'y a pas de solution viable côté client. Votre solution doit donc fonctionner côté serveur.
  2. Côté serveur, vous pouvez crypter ou hacher la fonction. Veuillez voir cette question pour plus de détails. Je vais en discuter plus loin dans le reste de cette réponse. Vous pouvez opter pour l'une ou l'autre solution, mais la mise en œuvre diffère.

Si vous utilisez le chiffrement, vous pouvez toujours déchiffrer.

Cela pourrait vous aider dans le scénario suivant: Gardez le mot de passe toujours crypté. Ils doivent toujours correspondre. Cependant, lorsque l'utilisateur souhaite modifier son mot de passe, ce sera du texte clair. L'utilisateur ne peut pas le saisir sous une forme cryptée. Vous devez résoudre cela. Il y a des solutions. Je suis sûr que vous comprenez cela.

Si vous utilisez le hachage (crypté) , alors il est très difficile à casser . Vous ne pouvez pas le décrypter.

Cela peut vous aider dans le scénario suivant: Le serveur envoie uniquement la version hachée. De cette façon, aucun attaquant ne peut utiliser ces informations. Vous devez le concevoir en conséquence, mais j'imagine que vous le comprenez aussi.

Cela dit, je ne vois vraiment pas de cas d'utilisation acceptable pour votre besoin.

Laissez-moi vous expliquer pourquoi. Vous voulez empêcher un attaquant de voir le mot de passe au cas où un utilisateur se souviendrait des mots de passe ou utiliserait un remplisseur de formulaire automatique. Eh bien, si un attaquant est en mesure d'accéder à l'ordinateur d'un utilisateur, il pourrait simplement se connecter, pourquoi se donner la peine de voir le mot de passe?

Il y a une raison pour laquelle des entreprises comme Google ou Facebook n'ont pas apporté de solution pour votre cas d'utilisation. Le est allé sur un autre chemin et a essayé de pousser pour une sécurité accrue en Authentification à 2 facteurs

Si vous pouvez l'utiliser, faites-le. Cela ne résout pas complètement le problème, mais vous pouvez vous attendre à ce qu'il augmente la sécurité. En particulier, c'est plus difficile pour un attaquant.

8
Ely

Comme c'est du côté client, il n'y a pas de véritable moyen d'empêcher cela. En termes de modèle de sécurité: nous ne pouvons pas faire confiance au client. D'un autre côté, cependant, il n'y a pas de véritable moyen de mettre en œuvre cela différemment sans l'utilisation d'un appareil tiers.

Si vous êtes prêt à passer par la difficulté d'avoir un appareil tiers pour aider à l'authentification: demandez au site Web de générer et d'afficher une graine aléatoire, demandez à l'appareil de demander la graine et le mot de passe pour générer un hachage, et authentifiez-vous sur le site en utilisant le hachage. Bien sûr, le hachage sera toujours visible si vous utilisez un débogueur Web, mais au moins cela ne sert à rien de le stocker/le lire car le hachage sera différent pour chaque session. Soit dit en passant, ce n'est pas complètement sécurisé, car cette méthode est sujette à l'attaque choisie en texte brut.

Bravo si vous êtes prêt à traverser tous ces problèmes. Je suppose que vous pourriez écrire une application pour que cela ait une fonction de smartphone en tant qu'appareil tiers.

4
Chavez

Eh bien, ce n'est pas possible avec la technologie actuelle. Comme d'autres l'ont indiqué, vous pouvez toujours inspecter tout le code côté client et essayer de manipuler le DOM.

L'autre solution consiste à implémenter comme la connexion bancaire. Randomisez la séquence de mots de passe à chaque connexion de l'utilisateur. Par exemple, si la longueur du mot de passe est de 10, donnez à l'utilisateur trois champs de mot de passe, demandez la séquence de mot de passe, par exemple. 3e, 5e, 10e. Cela changera chaque fois que l'utilisateur essaiera de se connecter. Et côté serveur, vous les comparez.

3
Tom Marulak

Je crois que le problème auquel vous êtes confronté est que plusieurs personnes utilisent le même ordinateur, et si un utilisateur enregistre son mot de passe sur votre site, toute autre personne qui visite le site sur le même ordinateur pourra manipuler le champ pour révéler le mot de passe.

Une façon d'empêcher cela de se produire est de désactiver la saisie semi-automatique. autocomplete="off" Placez ce code dans l'élément d'entrée et même si le mot de passe est enregistré, il ne devrait pas apparaître. <input autocomplete="off" type="text" required="" tabindex="2" class="std_textbox" placeholder="Enter your account password." id="pass" name="pass">

Avantages
Vous n'avez pas à vous soucier des utilisateurs partageant des ordinateurs et des mots de passe révélés pour la plupart.
Contre
Les utilisateurs peuvent penser que leurs mots de passe sont enregistrés (et ils peuvent toujours enregistrer les mots de passe) mais lorsqu'ils arrivent sur votre site, il n'apparaîtra pas.
[~ # ~] note [~ # ~] Ce n'est pas la manière la plus complète d'empêcher les utilisateurs du formulaire de manipuler le formulaire et récupérer les mots de passe des autres utilisateurs.

Par ailleurs, si le site ne se rafraîchit pas après avoir entré un mot de passe et un nom d'utilisateur, le navigateur Web ne demandera pas de sauvegarder le mot de passe. Par exemple, utiliser un appel ajax à la place du formulaire d'envoi.

Vous pouvez utiliser JavaScript pour effacer le texte à l'intérieur du champ de mot de passe lors du chargement de la page. Un meilleur style serait d'ajouter le champ lorsque la page se charge avec JavaScript comme ceci: var x = document.createElement ("INPUT"); x.setAttribute ("type", "mot de passe");

Une alternative à la saisie semi-automatique = "off" alternative à la saisie semi-automatique Cela implique de générer un nom à partir du backend et de l'utiliser comme nom des champs afin que la saisie semi-automatique ne sache jamais où mettre les données enregistrées de vos utilisateurs

3
Jacob Finamore

Absolument pas. Vous ne pouvez pas empêcher l'utilisateur final de manipuler le DOM à partir des outils de développement ou de Firebug.

L'utilisation de toute astuce côté client ne peut pas empêcher l'utilisateur de le faire. Jusqu'à ou à moins que le navigateur n'empêche l'utilisateur de le faire.

3
naim shaikh

Vous ne pouvez pas, et vous ne devriez pas. Ce n'est pas un problème de sécurité que vous devriez aborder sur votre site Web. Il appartient à l'utilisateur de protéger ses mots de passe. Si j'ai la possibilité d'utiliser la console de développement ou d'injecter le javascript sur votre page, quoi que vous fassiez, les mots de passe de l'utilisateur seront toujours compromis.

Si un utilisateur choisit d'enregistrer ses mots de passe dans son navigateur, c'est à lui de l'empêcher de tomber entre de mauvaises mains, et vous ne pouvez absolument rien y faire sur votre site. En fait, si vous utilisez Chrome et que vos mots de passe sont enregistrés, accédez à chrome: // settings/passwords et cliquez sur certains champs de mot de passe.

D'autres réponses parlent de hachage des mots de passe, etc. C'est quelque chose que vous devez absolument faire, mais sur votre serveur. Vous pouvez bien sûr hacher ou chiffrer un mot de passe avant de l'envoyer à votre serveur (et vous devriez vraiment aussi, en utilisant https), mais c'est un problème complètement différent.

2
Schlaus

Tu ne peux pas.

Mais là encore . Il existe bien sûr un moyen d'empêcher l'utilisateur de le voir à l'aide de la console développeur - n'affichez jamais le champ INPUT contenant le mot de passe.

L'alternative serait d'émuler le comportement du champ afin qu'il semble être là, mais qu'il ne l'est pas. Je n'ai pas encore trouvé de solution techniquement solide, mais comment voici comment procéder: (mis à jour) http://jsfiddle.net/858kef4h/

Dans cet exemple, l'idée est de créer un pseudofield basé sur DIV qui ressemble à un mot de passe INPUT et écoute les touches de l'utilisateur et enregistre la valeur dans une variable JavaScript

<div class="pwField">
  <div class="pwData"></div>
  <div class="cursor"><div class="tfarea"></div></div>
</div>

Ce hack simple n'a que trois variables d'état pour le mot de passe, l'état de focus et la zone de texte cachée

var pw = "", bHasFocus = false, tfArea;

La classe "curseur" est activée/désactivée en utilisant JavaScript pour émuler le vrai curseur

setInterval( function() {
   $(".cursor").toggleClass("blink");
},600);

Lorsque le div est cliqué, il crée une zone de texte à l'endroit du curseur et se concentre sur celui-ci.

$(".pwField").on("click", function() {
    // enable cursor and create element if needed
    $(".pwField").addClass("active");
    if(tfArea) { // if already created, just focus to the field
        tfArea.focus(); 
        bHasFocus = true;
        return;
    }
    tfArea = document.createElement("textarea");
    tfArea.value="";
    $(".tfarea").append(tfArea);
    tfArea.focus();   
    bHasFocus = true;
    $(tfArea).on("blur", function() {
        // disable cursor and exit
        $(".pwField").removeClass("active");
        bHasFocus = false; 
    });
});

Ensuite, vous pouvez écouter keyup/keydown et enregistrer les valeurs

$(document).keydown(function(  ) {
    if(!bHasFocus) return;
    pw = tfArea.value;
    // print asterisks
    $(".pwData").html( asterisks( pw.length ) );
});

Et lorsque vous êtes prêt à vous connecter, la valeur est dans la variable "pw".

Ce TEXTAREA créé dynamiquement peut passer inaperçu par les gestionnaires de mots de passe automatiques, car ce n'est pas le type de champ INPUT que les gestionnaires de mots de passe s'attendent à voir.

L'utilisateur qui modifie le champ peut naturellement inspecter la valeur de cet élément en utilisant les outils de développement Chrome, mais le fait est que si le gestionnaire PW ne considère pas ce champ comme un mot de passe, il ne le remplit pas avec le mot de passe de l'utilisateur précédent.

Je ne recommande pas d'utiliser ceci, c'était juste fait par curiosité. L'idée était de montrer que même si vous ne pouvez pas empêcher l'utilisateur de voir les éléments, vous pourrez toujours masquer le résultat aux gestionnaires de mots de passe. Mais comme le dit le vieil adage, "vous pouvez duper certains d'entre eux de temps en temps, mais pas tous tout le temps".

L'expérience utilisateur n'est pas la même qu'avec une entrée standard, mais elle pourrait être améliorée. Un problème est également que, même si vous vouliez empêcher l'affichage du mot de passe, c'est peut-être ce que les utilisateurs veulent vraiment. Ils peuvent vouloir utiliser le gestionnaire de mots de passe. Mais dans ce cas, vous n'avez pas de chance de toute façon.

Il peut également y avoir des problèmes de clic, de mise au point et de flou avec différents navigateurs, ils peuvent ne pas fonctionner avec les appareils mobiles comme vous vous y attendez. Si ce type de piratage est utilisé, vous devez le tester soigneusement. Il pourrait être utilisé si vous savez exactement quel type de navigateur les utilisateurs utilisent et que vous savez qu'ils ont activé JavaScript.

EDIT: J'ai testé l'approche avec certains appareils mobiles et cela semblait fonctionner quelque peu, mais avec l'iPad, et j'ai remarqué que le placement de la zone de texte cachée créera toujours un curseur visible et changez le zoom, alors maintenant la zone de texte cachée est placée à l'intérieur du pseudocurseur DIV et le zoom doit le suivre.

2
Tero Tolonen

Vous pouvez utiliser un code Javascript simple pour stocker la valeur du mot de passe dans une variable onblur, puis la restaurer sur onfoucs ou/et onsubmit.

Regardez le code de démonstration suivant et sa démonstration en ligne ici :

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
<script>
password = '';
function setPasswordBack(){
  showPassword();
}
function hidePassword(){
  p = document.getElementById('pass');
  password = p.value;
  p.value = '*********';
}
function showPassword(){
  p = document.getElementById('pass');  
  p.type= "password"; 
  p.value = password;
}
</script>
</head>
<body>
<form action="" method="get" onsubmit="setPasswordBack()">
<input type="password" value="" name="password" id="pass" onblur="hidePassword()" onfocus="showPassword()" />
<input type="submit" />
</form>
</body>
</html>

Il est clair que la solution dépend de JavaScript, donc dans le cas de la désactivation de javascript, vous pouvez utiliser noscript pour demander un navigateur compatible JavaScript.

2
SaidbakR

Comme déjà dit, avoir un mot de passe dans un élément d'entrée permettra à l'utilisateur de révéler facilement le mot de passe.

... Et comme @Elyasin le demande, vous devriez vraiment nous faire savoir quel est votre cas d'utilisation.

Étant dans l'ignorance de votre cas d'utilisation, supposons que vous ayez un site Web auquel les utilisateurs peuvent s'abonner moyennant des frais et que vous ne souhaitiez pas que plusieurs utilisateurs partagent la connexion d'une personne pour contourner le paiement de vos frais d'abonnement.

Vous pouvez utiliser l'authentification par cookie pour vérifier qu'un utilisateur est abonné à votre site.

  1. Lorsqu'un nouvel utilisateur s'inscrit, envoyez-lui un e-mail contenant un lien vers une page d'inscription spéciale sur votre site Web.

  2. Lorsque l'utilisateur suit ce lien, placez un cookie sur l'ordinateur de l'utilisateur indiquant qu'il est un abonné valide.

  3. Créez une page de destination sur votre site. Cette page de destination lira le cookie de l'ordinateur de l'utilisateur et authentifiera qu'il s'agit bien d'un abonné valide.

  4. Toutes les autres pages de votre site doivent rediriger les utilisateurs vers la page de destination si ces utilisateurs ne disposent pas du cookie de validation.

  5. Étant donné que les utilisateurs non abonnés peuvent être redirigés vers la page de destination, vous pouvez proposer de les laisser devenir abonnés sur la page de destination.

  6. Si l'abonnement d'un utilisateur abonné a expiré, vous supprimez le cookie de l'ordinateur de l'utilisateur (maintenant non abonné) la prochaine fois qu'il visite votre site. Comme tout utilisateur non abonné, vous le redirigez vers la page de destination.

S'il est vrai que les cookies peuvent être interceptés ou volés, cela dépasse généralement la capacité de l'utilisateur occasionnel de le faire.

Si vous souhaitez plus de sécurité à l'aide de cookies, vous pouvez capturer l'adresse IP d'un utilisateur lors de son abonnement initial. Ensuite, vous pouvez vérifier que l'utilisateur possède à la fois un cookie de validation et qu'il accède également à partir de la même adresse IP à laquelle il s'est initialement abonné. Bien sûr, cela limite l'abonnement à l'utilisation de leur adresse IP d'origine uniquement pour accéder à votre site.

2
markE

Remarque: Je pense que vous devriez éviter de faire cela car cela casserait les fonctionnalités de base du navigateur.

Mais si vous insistez, vous pourriez faire en sorte plus difficile que quelqu'un révèle le mot de passe en "déléguant" la saisie à un autre champ de saisie et en remplissant le champ du mot de passe avec des caractères aléatoires.

Voici un exemple d'une façon de le faire. Gardez à l'esprit que cela n'empêche en aucun cas quelqu'un de récupérer le mot de passe directement du corps de la demande ou s'il trouve votre élément délégué 'caché'.

!function() {

    var passwordEl, delegateEl;

    function syncPassword() {
        passwordEl.value = 
            Array(delegateEl.value.length + 1).join('*');
    }

    function createDelegate() {
        delegateEl = document.createElement('input');
        delegateEl.style.position = 'absolute';
        delegateEl.style.top = '-9999px';

        delegateEl
            .addEventListener('keyup', syncPassword, false);

        document.body.appendChild(delegateEl);
    }

    window.addEventListener('load', function() {
        passwordEl = document.getElementById('passwordId');
        createDelegate();

        // steal the focus from the password input
        passwordEl.addEventListener('focus', function(e) {
            e.preventDefault();
            delegateEl.focus();
        }, false);

        syncPassword(); // clear if was auto completed

    }, false);
}();

Vous avez maintenant la possibilité de remplir à nouveau votre entrée de mot de passe avec le mot de passe correct lors de la soumission du formulaire, ou simplement de demander à votre serveur que le mot de passe arrive du champ délégué.

Si vous le souhaitez, vous pouvez ajouter le style approprié au champ de mot de passe lorsque le champ délégué est concentré et donner ainsi à l'utilisateur l'impression qu'il reste concentré sur le champ de mot de passe lui-même.

Mais non.

2
Peleg

La prémisse de cette question est que l'ordinateur client est compromis et est utilisé par quelqu'un qui ne devrait pas y avoir accès. En supposant qu'un gestionnaire de mots de passe est utilisé (tel que Chrome) qui ne nécessite pas de mot de passe principal avant chaque remplissage automatique du formulaire de connexion, vous ne pouvez rien faire pour empêcher l'attaquant d'accéder aux comptes.

Vous essayez de résoudre un problème au niveau de l'application lorsque le problème d'accès est plus profond que cela.

Supposons que Bob oublie de se déconnecter de son ordinateur. Un attaquant (Eve) tombe sur sa session Windows ouverte et souhaite accéder à son compte Paypal. Bob utilise un gestionnaire de mots de passe pour plusieurs comptes, y compris ses comptes Gmail, Paypal et Reddit. Supposons que Paypal prenne des précautions au niveau de l'application pour empêcher Eve d'apprendre le mot de passe de Bob à partir du remplissage automatique d'un gestionnaire de mots de passe. Eve pense qu'elle ne pourra contrôler le compte Paypal de Bob que le temps qu'il lui faudra pour revenir. Mais alors, Eve remarque la fonctionnalité de lien de réinitialisation du mot de passe de Paypal. Le compte de messagerie de Bob est également compromis car son mot de passe se trouve également dans le gestionnaire de mots de passe. Avec l'accès au compte de messagerie électronique de Bob, Eve peut réinitialiser tous les mots de passe de Bob qu'elle souhaite. Elle pourrait maintenir l'accès en installant un enregistreur de frappe sur l'ordinateur de Bob.

En bout de ligne, les problèmes de sécurité que vous essayez de résoudre sont au-delà de votre pouvoir de réponse (en supposant un modèle de mot de passe de nom d'utilisateur classique). Même sans rien supposer de votre application, Eve a un accès physique à l'ordinateur de Bob, elle peut donc le compromettre de multiples façons.

Si vous faites en sorte que vos utilisateurs utilisent l'authentification à deux facteurs (envoyez-leur un code via SMS via Twilio), faites-leur transporter une clé USB matérielle, etc ... vous augmenterez la sécurité et éviterez le problème du gestionnaire de mot de passe.

Mais en fin de compte, vous faites face à un compromis entre sécurité et convivialité. Si Bob est trop paresseux/oublieux/apathique/négligent pour se déconnecter de son PC, aucune quantité de JavaScript que vous écrivez ne pourra le sauver.

1
Kevin Dice

Eh bien, en 2019, il existe un moyen délicat ... vous pouvez générer des formulaires avec JavaScript/jQuery sur une div et vous pouvez les mettre en lecture uniquement. Si l'attaquant désactive JavaScript, alors le code gen ne fonctionnera pas, il ne sera alors sous aucune forme ...

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <title>Basic security for mr. Hacker</title>
 </head>
 <body>
 <div id="ticketAF0122"></div><!-- it is assumed that id is generated every time !!!  -->
 <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
 <script>
    $(document).ready(function(){
        function readonly(){
            $('div#ticketAF0122').html('My password<form method="post" action=""><input type="password" name="password"><input type="submit"></form>');
        }
        readonly()
        $('div#ticketAF0122').bind("DOMSubtreeModified", function(){
            readonly();
        });
    });
    /*

    Basicly you can load this part from an encoding external php file:
    <script src="page.php?ticket=ticketAF0122">< /script>

    and the php file generate something like:
    $(document).ready(function(){
        function readonly(){
            $('div#ticketAF0122').html('My password<form method="post" action=""><input type="password" name="password"><input type="submit"></form>');
        }
        readonly()
        $('div#ticketAF0122').bind("DOMSubtreeModified", function(){
            readonly();
        });
    });

    */

 </script>
 </body>
</html>

je vérifie déjà cela sur xampp/windows 10 avec firefox et en changeant avec l'inspecteur de type = "mot de passe" en type = "texte" le script "réparera" encore les choses

dans Edge fonctionne buggy: quand avec Inspector je modifie ce truc alors tout le formulaire est strip puis inséré au dessus du document html

0
Constantin