Codage côté client: comment prévenir les utilisations malveillantes?

60

Au cours des dernières années, la tendance pour les applications côté client (navigateur) a vraiment pris son envol.

Pour mon dernier projet, j'ai décidé d'essayer de me déplacer avec le temps et d'écrire une application côté client.

Une partie de cette application implique l'envoi d'e-mails de transaction aux utilisateurs (par exemple, valider l'inscription, les e-mails de réinitialisation de mot de passe, etc.). J'utilise une API tierce pour envoyer les courriels.

Normalement, mon application serait exécutée sur un serveur. J'appellerais l'API tierce à partir du code de mon serveur.

L'exécution d'une application côté client signifie que cela doit maintenant se produire sur le navigateur de l'utilisateur. L'API tierce fournit les fichiers JavaScript nécessaires pour y parvenir.

Le premier problème criant que je vois est que je dois utiliser une clé API. Cela devrait normalement être stocké en toute sécurité sur mon serveur, mais je suppose que je devrai maintenant fournir cette clé au navigateur client.

En supposant que je puisse résoudre ce problème, le prochain problème est ce qui empêche un utilisateur féru de technologie de charger l'outil de développement JavaScript dans un navigateur et d'utiliser l'API de messagerie de toute façon qu'il préfère, plutôt que de se conformer aux règles que j'ai définies dans l'application. .

Je suppose que ma question générale est la suivante: comment pouvons-nous empêcher l’utilisation malveillante d’une application côté client?

Gaz_Edge
la source
24
Une raison quelconque pour laquelle cette application ne communique pas avec votre propre serveur, qui transmet ensuite ces demandes à tout service externe que vous souhaitez utiliser? (De nombreux services interdiraient de toute façon de les utiliser de cette manière)
thorsten müller
11
C'est pourquoi les clés d'API sont finalement inutiles. Le serveur ne doit pas essayer de faire confiance à l'application qui lui envoie des commandes; il ne faut que faire confiance à l'utilisateur.
Kevin Panko
42
Je n'ai vu aucune personne sensée définir jamais une "application côté client" comme "ne communiquant jamais avec un serveur" - cela ressemble plus à un homme de paille qu'à un argument raisonnable. Il est clair que vous devez gérer certaines tâches côté serveur, mais la grande majorité des actions peuvent être effectuées localement sans problèmes, ce qui améliorera considérablement la réactivité et l'évolutivité.
Voo
4
Où voyez-vous une poussée vers "les applications de navigateur seulement?" Je n'ai jamais rien vu de semblable à ce que vous décrivez, garder les secrets du code client dans une idée incroyablement mauvaise, même les types les plus acharnés du front que je connaisse ne feraient jamais cela.
Wheeyls
2
Toute tentative de protection des ressources sécurisées côté client est condamnée car elle enfreint plusieurs lois de sécurité immuables. # 2/3 - Si votre logiciel tourne sur votre ordinateur adverse, ce n'est pas votre ordinateur par définition et vous l'avez déjà perdu. # 7 tenter de protéger une ressource par chiffrement est voué à l'échec puisqu'il faut également fournir au client la clé de déchiffrement. # 10 aucune technologie ne peut réparer ce qui précède. blogs.technet.com/b/rhalbheer/archive/2011/06/16/…
Dan Neely

Réponses:

200

Vous ne pouvez pas, et plus les gens comprennent cela, et plus ils comprennent, mieux c'est pour le monde.

Le code exécuté sur un périphérique sous le contrôle de l'utilisateur ne peut pas être contrôlé. Les smartphones peuvent être jailbreakés. Les décodeurs peuvent être fissurés. Les navigateurs ordinaires n'essaient même pas d'empêcher l'accès au code JavaScript. Si vous avez quelque chose d'intéressant à voler ou à abuser, un attaquant déterminé pourra le faire à moins que vous ne validiez tout ce que vous chérissez côté serveur.

L'obscurcissement est d'une aide minime. Le type d’opposant que vous attirez dès que quelque chose d’imprévisible à distance est lu lit le langage de montage comme les petites annonces. Le cryptage ne peut pas vous aider, car le périphérique qui gardera la clé est le même périphérique que vous devez supposer fissuré. Il existe de nombreuses autres contre-mesures apparemment évidentes qui ne fonctionnent pas, pour des raisons similaires.

Malheureusement, cette vérité est très gênante. Le monde regorge de petits et grands opérateurs qui pensent pouvoir en quelque sorte contourner la fracture fondamentale de la confiance à distance, tout simplement parce que ce serait tellement bien si nous pouvions supposer que notre code sera exécuté comme nous le pensions. Et oui, cela simplifierait tellement les choses que ce n’est même pas drôle. Mais souhaiter ne le rend pas ainsi, et espérer contre espoir que vous soyez le seul cookie intelligent qui peut éviter le désagrément ne fera que vous brûler, vous et vos clients. Par conséquent, pensez que l’Internet est un territoire ennemi, incluez ce coût supplémentaire dans vos estimations et tout ira bien.

Cela dit, bien sûr, il existe une défense en profondeur. Le fait de masquer votre JavaScript ne rebute pas un attaquant déterminé, mais risque de dissuader certains attaquants moins déterminés. Si vos actifs valent suffisamment pour protéger, mais pas à n'importe quel coût, ces mesures peuvent ajouter de la valeur commerciale à votre système. ça ne peut pas être parfait. Tant que vous êtes pleinement conscient du compromis que vous faites, cela peut être une stratégie raisonnable.

Kilian Foth
la source
6
Mais pour mettre cela en perspective: ceci est vrai pour TOUS les logiciels, qu’il s’agisse d’un système d’exploitation ou d’une transaction. En fin de compte, il existe de très bons obfuscateurs de code et vous pouvez probablement placer la barre assez haut, s'il n'y a pas d'incitatif financier immédiat à pirater votre logiciel!
Falco
5
De nos jours, les entreprises ont commencé à menacer d'engager des poursuites judiciaires contre les personnes qui piratent le contenu qu'elles ont reçu avant leur traitement (c'est-à-dire via des bloqueurs de publicité). Cela ne fait que montrer à quel point une action technique est impossible .
Kilian Foth
62
Si je peux m'étendre sur les deux premières phrases, la subtilité que les gens oublient souvent est que les applications de navigateur côté client permettent de se décharger de lourdes charges. Votre serveur reste responsable des opérations sécurisées, telles que l’envoi de courriers électroniques ou l’accès aux données. Le fait que le client génère un graphique à partir de ces données vous permet toutefois d'économiser du temps CPU (et de l'argent) sans changer le modèle de sécurité.
ssube
11
@Gaz_Edge Il est important de noter que le problème ici n'est pas que les applications côté client sont intrinsèquement peu sécurisées. Le problème est d'écrire ces applications côté client d'une manière qui nécessite de faire confiance au client avec des informations que vous ne voulez pas voir publiques. Il est tout à fait possible d'écrire une application client lourde qui est aussi sécurisée qu'une application où la plupart des traitements sont effectués sur le serveur. (Pour plus d'informations, voir la réponse de jhocking )
Ajedi32
7
@ Ajedi32 Les applications côté client ne sont pas sécurisées. Il est impossible de concevoir une application sécurisée si une logique effectuée côté client n'est pas vérifiée côté serveur. À ce stade, la logique côté client devient une astuce d’interface utilisateur ou un moyen de décharger les contrôles de base, mais tout doit toujours être vérifié sur le serveur! .
69

La règle est la suivante:

Faites tout ce qui est client qui n'affecte personne si l'utilisateur le manipule. Cela signifie notamment des effets graphiques.

Faites tout ce qui est côté serveur, qui doit être sécurisé, et envoyez simplement les événements d'interface utilisateur à partir du client (par exemple, le client dit simplement que "l'utilisateur a appuyé sur le bouton Acheter" pendant que le serveur effectue réellement la transaction). Cela signifie notamment des transactions financières.

jhocking
la source
28

C'est exactement le cas où il n'est pas approprié de faire une application entièrement côté client .

Vous pouvez effectuer la logique et la validation de base des formulaires côté client (vous devez toujours revalider sur le serveur, car une personne peut essayer de simuler la requête) pour améliorer la réactivité. Vous pouvez également effectuer des requêtes HTTP à partir de JavaScript, en passant des évitez de renvoyer des décorations de pages, etc., mais si la transaction elle-même doit être authentifiée et autorisée, elle doit quand même être exécutée sur un serveur.

Jan Hudec
la source
11
Remarque: Bien qu'il soit intéressant de valider les formulaires côté client, n'oubliez jamais de les valider également côté serveur! Au moment où vous envoyez votre code client au navigateur, il cesse d'être votre code! Vous devez valider chaque bit envoyé à nouveau!
Josef
17

Votre paragraphe du milieu est le coeur du problème:

L'exécution d'une application côté client signifie que cela doit maintenant se produire sur le navigateur de l'utilisateur. L'API tierce fournit les fichiers js nécessaires à cette fin.

Pourquoi une application côté client signifie-t-elle que vous ne pouvez pas utiliser le travail côté serveur? La poussée vers la programmation côté client ne consiste pas à éliminer les serveurs, mais à tirer parti des nouvelles technologies prises en charge par les navigateurs pour créer de meilleures interfaces utilisateur.

En ce qui concerne le .jsfichier que vous avez reçu, êtes-vous sûr qu'il est destiné à un navigateur? Serait-ce une bibliothèque node.js?

Brandon
la source
4
+1 pour la très bonne suggestion que le fichier JS est destiné à un serveur NodeJS
Machinarius
11

Revenons en arrière et examinons de plus près. Devrons-nous .. Eudora ou Outlook (une application côté client, n'ayant même pas besoin de navigateur) ont-ils déjà causé une perte financière à une entreprise? Tout le monde peut écrire sur les API POP / SMTP et devenir le client. Mais pas de perte pour le serveur. Le serveur ne limitait pas les actions du client, les calculs, le stockage, la température, la taille du disque, la taille de la RAM, le DPI, le GPU du moniteur, le FPU, mais spécifiait exactement ce à quoi il répondait, sans plus. Avez-vous déjà entendu parler de quicken ou de MS-Money utilisé pour percer dans une banque?

Votre application de navigateur (c'est-à-dire côté client) peut utiliser la même architecture.

  1. Vous construisez votre serveur avec une API (BTW se réduit toujours à des dérivés de GET POST HEAD, etc.).
  2. Sur le serveur, assurez-vous que l'API ne parle qu'avec un client authentifié et vérifié par identité pour chaque appel.
  3. Alors vous ne vous souciez pas de savoir qui est le client.
  4. Et puis vous ne vous souciez pas de savoir s'il s'agit d'un navigateur, d'un appareil jailbreaké, de Google Glass, de DOS 3.1 ou d'un tout nouveau Nexus entre les mains d'un arrière-arrière-arrière-arrière-arrière-grand-père technophobe qui a déjà voyagé jusqu'en 2014 et qui a tout raté la technologie qui a inondé nos vies au cours des 15 dernières décennies.
  5. Vous pouvez maintenant commencer à décharger tout le reste du côté client.

SoapBoxBegin

@KilianFoth soulève un point important de sensibilisation pour les naïfs et les téméraires, principalement ceux qui lisent les manchettes tout le temps mais ne pensent jamais que cela va arriver à leur application, leur code, leur employeur, leur client, leur propre compte bancaire. Encore plus téméraires sont leurs employeurs (en particulier les CTO), qui autoriseraient les applications à exposer tous les systèmes à une exposition non gérée / incontrôlée. Cependant, je suis toujours perplexe à l'idée qu'il semble que "nous n'apprenons jamais".

SoapBoxEnd

Donc, pour résumer. Créez une API côté serveur solide et compacte. Déchargez tout le reste du client en fonction de ce que le client peut gérer.

LMSingh
la source
6

Je dirais que vous ne pouvez vraiment pas. Si vous souhaitez envoyer les données au client, vous devez vous attendre à ce qu'elles soient utilisées de manière abusive, dans la mesure du possible. Votre exemple concernant la clé API illustre ce point, et je n’incluerais pas cela dans votre JS côté client: il sera volé et utilisé de manière abusive.

Vous aurez certainement encore besoin d’une certaine quantité de code serveur pour assurer la sécurité. Même quelque chose d'aussi simple que de récupérer uniquement les données relatives à l'utilisateur connecté. Cette authentification ne peut pas être entièrement effectuée côté client. Une fois encore, vous serez exploité et vos données ne sont pas sécurisées.

Je verrais toujours l'expérience client JS comme un ajout au code serveur. La validation sur le client offre une expérience utilisateur agréable, mais si vous ne vérifiez pas également les données POST sur le serveur de réception, vous vous exposez à une attaque. Tout ce qui vient du client devrait être considéré comme suspect.

Matt Klinker
la source
4

C'est assez simple, vraiment. Supposons que l'ordinateur client et tous les logiciels qui y sont exécutés sont sous le contrôle total d'un pirate informatique malicieux.

Cela signifie que le pirate malveillant connaîtra les informations que vous enverrez du serveur au client. Vous devez donc vous assurer de ne pas envoyer au client des informations qui pourraient être utilisées pour attaquer votre serveur ou votre entreprise.

Cela signifie également que tout ce qui a été envoyé du client au serveur a été créé par un pirate malveillant. Votre code de serveur doit donc vous assurer que rien de ce que le client pourrait envoyer ne serait capable d’attaquer avec succès votre serveur.

Certes, la mise en œuvre pose problème, mais l’important est l’attitude mentale, à savoir que le "client" avec lequel vous pensez que votre serveur parle n’est pas un client mais un attaquant actif.

(Vous devez également supposer que l'utilisateur est un escroc intelligent qui essaiera d'attaquer vos méthodes métier, mais cela n'a rien à voir avec la programmation côté client).

gnasher729
la source
0

À mon avis, l’application côté client concerne principalement l’interface utilisateur. Par exemple, tout votre système d'interface utilisateur sera envoyé une fois au client, qui en fera ensuite tout ce qu'il voudra.

Normalement, mon application serait exécutée sur un serveur. J'appellerais l'API tierce à partir du code de mon serveur.

L'exécution d'une application côté client signifie que cela doit maintenant se produire sur le navigateur de l'utilisateur. L'API tierce fournit les fichiers JavaScript nécessaires pour y parvenir.

Si vous avez une clé API, elle n'est pas conçue pour fonctionner côté client. Si vous attribuez la clé API côté client, tout le monde y a accès et peut ensuite l'utiliser à ses propres fins. Stockez-le et utilisez-le côté serveur lorsque le client en a besoin, puis envoyez le résultat à l'aide de Ajax / WebSockets.

C'est comme si votre banque disait: "Eh bien, je vais mettre le mot de passe du côté client de la base de données principale afin que le client puisse le demander lui-même et qu'il ne gêne plus nos serveurs."

Depado
la source