Ma question concerne la sécurité JavaScript.
Imaginez un système d'authentification utilisant un framework JavaScript tel que Backbone ou AngularJS , et vous avez besoin de points de terminaison sécurisés. Ce n'est pas un problème, car le serveur a toujours le dernier mot et vérifiera si vous êtes autorisé à faire ce que vous voulez.
Mais que faire si vous avez besoin d’un peu de sécurité sans impliquer le serveur? Est-ce possible?
Par exemple, supposons que vous disposiez d'un système de routage côté client et que vous souhaitiez protéger un itinéraire concret pour les utilisateurs connectés. Donc, vous envoyez une requête ping au serveur vous demandant si vous êtes autorisé à visiter des itinéraires protégés et vous poursuivez. Le problème est que lorsque vous envoyez une requête ping au serveur, vous stockez la réponse dans une variable. Ainsi, lors de votre prochain passage sur une route privée, il vérifiera que, si vous êtes déjà connecté (pas de ping vers le serveur), sur la réponse cela ira ou pas.
Est-il facile pour un utilisateur de modifier cette variable et d'obtenir un accès?
Mes connaissances en sécurité (et JavaScript) ne sont pas excellentes. Mais si une variable n’a pas une portée globale et se trouve dans la partie privée d’un modèle de module qui n’a que des accesseurs, mais pas des setters, même dans ce cas, pouvez-vous pirater la chose?
la source
manipulate any part of the sight without long lines
site vs sightRéponses:
Veuillez lire la réponse de Joachim avant de lire celle-ci. Il couvre les raisons générales de la vulnérabilité côté client. Maintenant, pour une suggestion, comment vous pourriez résoudre ce problème ...
Un schéma sécurisé pour la communication client-serveur sans devoir s’authentifier manuellement auprès du serveur à chaque requête:
Vous laissez toujours le serveur avoir le dernier mot et le serveur doit toujours valider tout ce que dit le client, mais cela se fait de manière transparente.
Supposons que le protocole HTTPS empêche les attaques par interception (MITMA).
Le client dialogue pour la première fois avec le serveur. Le serveur génère une clé publique pour le client et conserve une clé privée à l'aide d'un schéma de chiffrement asymétrique. Le client stocke la clé "publique" du serveur dans la mémoire de stockage locale, chiffrée avec un mot de passe sécurisé que vous n'enregistrez nulle part.
Le client est maintenant hors ligne. Le client veut effectuer des actions approuvées. Le client entre son mot de passe et saisit la clé publique du serveur.
Le client effectue maintenant des actions en fonction de sa connaissance de ces données et le client chiffre chaque action qu'il effectue avec la clé publique du serveur pour ce client .
Lorsque le client est en ligne, le client envoie son ID client et toutes les actions effectuées par le client sont envoyées au serveur cryptées avec la clé publique du serveur.
Le serveur décrypte les actions et si leur format est correct, il est convaincu qu'elles ont été créées par le client.
Remarque:
Vous ne pouvez pas stocker le mot de passe du client n'importe où, sinon un attaquant pourrait récupérer la clé et signer les actions comme siennes. La sécurité de ce schéma repose uniquement sur l'intégrité de la clé générée par le serveur pour le client. Le client doit toujours être authentifié auprès du serveur pour demander cette clé.
En fait, vous comptez toujours sur le serveur pour la sécurité et non sur le client. Chaque action effectuée par le client doit être validée sur le serveur.
Il est possible d'exécuter des scripts externes dans des travailleurs Web . Gardez à l'esprit que chaque demande JSONP que vous avez est maintenant un problème de sécurité beaucoup plus important. Vous devez protéger la clé à tout prix. Une fois que vous l'avez perdu, un attaquant peut usurper l'identité de l'utilisateur.
Cela répond à votre demande selon laquelle «aucun ping vers le serveur» n'est effectué. Un attaquant ne peut pas simplement imiter une requête HTTP contenant des données falsifiées s’il ne connaît pas la clé.
La réponse de Joachim est toujours correcte . En fait, vous effectuez toujours toute l’authentification sur le serveur . La seule chose que vous avez enregistrée ici est la nécessité de valider le mot de passe avec le serveur à chaque fois. Vous devez maintenant uniquement impliquer le serveur lorsque vous souhaitez valider ou extraire des données mises à jour. Tout ce que nous avons fait ici est de sauvegarder une clé approuvée côté client et de le valider à nouveau.
C'est un schéma assez courant pour les applications à une seule page (par exemple, avec AngularJS).
J'appelle la clé publique du serveur "public" à cause de ce que cela signifie dans des schémas comme RSA , mais il s'agit en fait d'informations sensibles dans le schéma et doit être sauvegardé.
Je ne garderais le mot de passe nulle part en mémoire. Je ferais en sorte que l'utilisateur envoie son mot de passe "hors connexion" chaque fois qu'il commence à exécuter du code hors connexion.
Ne lancez pas votre propre cryptographie - utilisez une bibliothèque connue comme celle de Stanford pour l'authentification.
Suivez ce conseil tel quel . Avant de lancer ce type d'authentification dans une application critique du monde réel, consultez un expert en sécurité . Il s’agit d’un problème grave, à la fois douloureux et facile à se tromper.
Il est essentiel qu'aucun autre script n'ait accès à la page. Cela signifie que vous n'autorisez que les scripts externes avec des travailleurs Web. Vous ne pouvez faire confiance à aucun autre script externe susceptible d'intercepter votre mot de passe lorsque l'utilisateur le saisit.
Utilisez un champ de mot de passe
prompt
et non un mot de passe en ligne si vous n'êtes pas complètement sûr et que vous ne retardez pas son exécution (autrement dit, il ne devrait pas survivre à un point où les événements y ont accès, mais uniquement en code de synchronisation). Et ne stockez pas réellement le mot de passe dans une variable - encore une fois, cela ne fonctionne que si vous faites en sorte que l'ordinateur de l'utilisateur ne soit pas compromis (bien que ce soit tout aussi vrai pour la validation sur un serveur).J'aimerais ajouter à nouveau que nous ne faisons toujours pas confiance au client . Vous ne pouvez pas faire confiance au client seul, et je pense que la réponse de Joachim résume tout. Nous avons seulement eu l'avantage de ne pas avoir à envoyer une requête ping au serveur avant de commencer à travailler.
Matériel connexe:
la source
window.prompt
méthode afin d'intercepter la phrase secrète, ou lancer sa propre invite (éventuellement au sein d'un iframe!). Un champ de mot de passe présente un avantage supplémentaire: les caractères ne sont pas affichés.C'est simple: tout mécanisme de sécurité reposant sur le client qui ne fait que ce que vous lui dites de faire peut être compromis lorsqu'un attaquant contrôle le client.
Vous pouvez effectuer des vérifications de sécurité sur le client, mais uniquement pour agir efficacement en tant que "cache" (afin d'éviter d'effectuer un aller-retour coûteux vers le serveur si le client sait déjà que la réponse sera "non").
Si vous souhaitez conserver les informations d'un ensemble d'utilisateurs, assurez-vous que le client de ces utilisateurs ne parvient jamais à ces informations. Si vous envoyez ces "données secrètes" avec des instructions "mais ne les affichez pas," il deviendra trivial de désactiver le code qui vérifie cette demande.
Comme vous le voyez, cette réponse ne mentionne pas vraiment les spécificités de JavaScript / Navigateur. C'est parce que ce concept est le même, peu importe ce que votre client est. Peu importe qu'il s'agisse d'un client lourd (application client / serveur traditionnelle), d'une application Web de la vieille école ou d'une application d'une seule page avec JavaScript étendu côté client.
Une fois que vos données ont quitté le serveur, vous devez supposer qu'un attaquant en a un accès total.
la source
Il y a un dicton dans la communauté de jeu: " Le client est entre les mains de l'ennemi". Tout code exécuté en dehors d'une zone sécurisée, telle que le serveur, est vulnérable. Dans le scénario le plus élémentaire, vulnérable au risque de ne pas être exécuté en premier lieu. C'est le client qui décide d'exécuter votre" code de sécurité "et l'utilisateur peut "opt-out". Bien qu'avec le code natif, vous ayez au moins une obfuscation automatique dans l'assembly et une couche de protection supplémentaire du fait qu'un attaquant doit être un bon programmeur pour manipuler cela, JS est normalement sans obfucated et en texte brut. Pour lancer une attaque, il suffit de disposer d'outils primitifs, tels qu'un serveur proxy et un éditeur de texte, mais il faudra encore un certain niveau d'instruction en programmation, mais il est beaucoup plus simple de modifier un script à l'aide d'un éditeur de texte que d'injecter du code dans un exécutable.
la source
Ce n'est pas une question de piratage JavaScript. Si je voulais attaquer votre application, j'utiliserais un proxy privé qui me permettrait de capturer, de modifier et de rejouer le trafic. Le système de sécurité que vous proposez ne semble pas avoir mis en place de protection.
la source
En ce qui concerne spécifiquement Angular:
La protection d'un itinéraire côté client n'existe tout simplement pas. Même si vous "cachez" un bouton sur cette route, l'utilisateur peut toujours le saisir, Angular se plaindra, mais le client pourra y coder.
À un moment donné, votre contrôleur va devoir demander au serveur les données nécessaires au rendu de la vue. Si l'utilisateur n'est pas autorisé à accéder à ces données, il ne les recevra pas car vous avez protégé ces données côté serveur. et votre application Angular doit gérer le 401 de manière appropriée.
Si vous essayez de protéger les données brutes, vous ne pouvez pas utiliser le côté client. Si vous voulez seulement qu'un utilisateur particulier puisse uniquement visualiser les données communes d'une certaine manière, créez les "vues" des données sur le serveur plutôt que les envoyer. données brutes au client et de les réorganiser (vous devriez de toute façon déjà le faire pour des raisons de performances).
Note latérale: les modèles de vue que Angular demande ne doivent en aucun cas être sensibles, mais ne le faites pas. Si c'est le cas, vous devez protéger ces modèles de vue côté serveur, comme vous le feriez si vous effectuiez un rendu côté serveur.
la source