Sécurité des applications client: conseils pratiques pour un développeur frontal

Comme vous le savez, la plupart des attaques des pirates BlackHat visent à compromettre les données du serveur des applications et services Web. Dans le même temps, la partie cliente est attaquée au moins aujourd'hui. Selon la définition sèche, toute attaque est un ensemble de mesures de la part d'un pirate visant le réseau et le transfert de données, les données et leur substitution, l'infrastructure et les caractéristiques techniques de la mise en œuvre de l'application Web. Par conséquent, les entreprises internationales exigent que les ingénieurs de développement adoptent une approche plus responsable et approfondie de la sécurité des applications clientes.


Sur l'exemple de mon projet, je parlerai de la façon dont les applications clientes attaquent aujourd'hui et comment vous pouvez éviter ces menaces.


Les 10 principales menaces de 2013 à 2017
Les 10 principales menaces pour 2013-2017.

Comme vous pouvez le voir, parmi les principales menaces, l'injection, le déclenchement d'erreur, le contournement de l'authentification et les données confidentielles non sécurisées occupent la première place. La menace d'utiliser des composants avec des vulnérabilités connues est toujours d'actualité. De nouvelles menaces sont également apparues: piratage du mécanisme de contrôle d'accès, désérialisation et sérialisation non sécurisées des données, journalisation et surveillance insuffisamment détaillées.


En 2001, Mark Curfy et Dennis Groves ont fondé l' OWASP (Open Web Application Security Project). Il s'agit d'un projet international OpenSource pour l'échange d'expériences sur la lutte contre les vulnérabilités dans les applications clientes, auquel participe un grand nombre d'ingénieurs en sécurité des applications. La communauté OWASP remplit le portail d'une multitude d'articles contenant des informations sur les vulnérabilités, du matériel de formation, des outils pour tester et repousser les attaques. Les vraies attaques sont décrites, leurs aspects sont révélés et ce qui doit être fait pour prévenir les menaces est décrit.


Pour comprendre quelles menaces sont dangereuses pour un projet, vous devez le tester à fond. Pour ce faire, le réseau dispose d'applications, de frameworks et de services en ligne qui identifient automatiquement certaines vulnérabilités. Pour les tests locaux, je recommande d'utiliser des applications et des frameworks, et pour tester des projets en fonctionnement, il est également très utile d'ajouter des services en ligne.




Mais même si les outils de test ne vous ont pas indiqué dans les rapports de vulnérabilités importantes (ce qui est peu probable), faites toujours attention au stockage des données sensibles dans le système de contrôle de version, à la création de l'application, au mécanisme d'authentification, à l'algorithme de hachage de mot de passe, au chiffrement des données sensibles, ainsi qu'aux systèmes de journalisation et surveiller l'ensemble de l'application Web. Dans ce cas, il est préférable de jouer en toute sécurité et de ne pas faire aveuglément confiance à l'automatisation.


Git


Tout d'abord, parlons des données sensibles dans Git. Idéalement, un référentiel séparé de secrets est alloué pour stocker les données sensibles. De là, lors de l'assemblage pour la mise en service, des données confidentielles sont extraites et cousues dans l'application. Aujourd'hui, Hashicorp Vault, Keywhiz, Docker secrets, Azure Key Vault et un certain nombre d'autres sont populaires.


Mais que faire si vous ne disposez pas d'un tel stockage? Vous pouvez utiliser des outils pour coder et masquer des fichiers avec des secrets qui élargiront les capacités des systèmes de contrôle de version.


La première chose qui me vient à l'esprit est la solution universelle BlackBox. Il peut être utilisé avec n'importe quel système de contrôle de version, par exemple, Mercurial, Git, etc. De plus, il existe deux extensions pour Git: git-crypt et git-secret. Je recommande d'utiliser le second, car il m'a semblé le plus pratique à utiliser et le plus compréhensible en termes de description dans la documentation officielle. Après avoir installé git-secret, vous devez l'initialiser dans le référentiel Git. N'oubliez pas de spécifier l'extension à utiliser dans le fichier .gitattributes . Ensuite, configurez l'accessibilité des secrets: identifiez les utilisateurs auxquels vous souhaitez donner accès aux données sensibles. Ajoutez ensuite des fichiers contenant des données sensibles et git-secret-hide les via git-secret-hide . Vous pouvez obtenir des fichiers cachés via git-secret-reveal.


brew install git-secret //
git secret init //
git secret tell your@gpg.email  //
git secret add <files...> //
git secret hide  //
git secret reveal  //

Webpack


Une autre façon d'éliminer les menaces consiste à configurer correctement le webpack. Pour vous protéger contre les attaques XSS, XEE et similaires, vous devez envisager de respecter les politiques CORS (Cross-origin resource sharing) et CSP (Content Security Policy). Dans les deux cas, il est important de suivre les en-têtes afin de vérifier l'authenticité de certains scripts utilisés dans le projet. Les navigateurs ont des mécanismes pour vérifier la fiabilité d'une source particulière, par exemple, Safari émettra des avertissements à chaque étape si CORS et CSP sont configurés incorrectement.


Il existe deux façons de se conformer à CORS et CSP. La première consiste à configurer les en-têtes de réponse dans le back-end. La seconde consiste à enregistrer les deux politiques via des balises META et des attributs. Cette dernière méthode est recommandée si vous avez des développeurs back-end paresseux, ils sont toujours occupés et ne sont pas intéressés par les politiques de sécurité. Les balises META peuvent être enregistrées immédiatement lors de la création de l'application. Des plugins comme html-webpack-plugin, html-webpack-exclude-assets-plugin, script-ext-html-webpack-plugin, csp-html-webpack-plugin et crypto nous aideront à cela. De plus, si vous avez des ressources tierces dans votre projet (par exemple, des liens vers des polices externes utilisées dans CSS; des ressources chargées à partir de CDN, etc.), je recommande également d'utiliser webpack-subresource-Integrity-plugin. Ainsi, vous informerez le navigateur que les ressources chargées dans le script sont fiables, qu'elles ne contiennent aucune injection, qu'elles sont entières et intactes. Et même si quelqu'un a injecté des données malveillantes dans la ressource et que vous les avez téléchargées, vous devez vous y préparer et protéger votre projet contre de telles menaces.


Je veux prêter une attention particulière à l'ordre dans lequel les instances de classe pour les plugins sont créées. L'ordre doit être comme ceci:


 const SHA256 = (str) => CRYPTO.createHash('sha256').update( str, 'utf8').digest('base64'); const sha256Str = SHA256( '' + Date.now() ); […] new HtmlWebpackPlugin({   filename: 'index.html',   template: 'public/index.html' }), new ScriptExtHtmlWebpackPlugin({    custom: [{           test: /\.js$/,           attribute: 'nonce',           value: 'nonce-' + sha256Str    }] }), new HtmlWebpackExcludeAssetsPlugin(), new CspHtmlWebpackPlugin({    'base-uri': '\'self\'',    'object-src': '\'none\'',    'script-src': ['\'self\'', '\'unsafe-eval\'', '\'nonce-' + sha256Str + '\''],    'style-src': ['\'unsafe-inline\'', '\'self\''] }, {    devAllowUnsafe: false,    enabled: true,    hashingMethod: 'sha256' }), new SriPlugin({    hashFuncNames: ['sha256', 'sha384'],    enabled: true }), […] 

Ensuite, pendant l'assemblage, la <hed> affichera la méta-balise http-equiv=content-security-policy . Les directives seront écrites dans l'attribut content , qui indique quels scripts et ressources peuvent être approuvés.


La directive base-uri indique quelle URL de base est utilisée pour charger des scripts, CSS, images, etc.


Les objets ne se chargent généralement pas, définissez donc none sur la directive object-sr c.


La directive script-src s'applique aux scripts JS.


N'oubliez pas d'enregistrer un attribut de type nnce-<hshVlue> chaque fois. De plus, le hachage doit être calculé à l'aide de l'algorithme SHA256 ou SHA512.


Quant à la directive style-src , notre projet a une particularité: nous utilisons des composants de style pour écrire du CSS pour chaque composant et les isoler les uns des autres. Et par conséquent, il est nécessaire de spécifier qu'en nous, style-src unsafe-inline et self sont utilisés dans style-src , sinon les composants style tomberont.





La balise de script sera automatiquement définie sur nnce-<hshVlue> , integrity et cross-origin . Ils indiquent au navigateur que les ressources sont extraites de sources fiables. Sinon, si le navigateur voit que la ressource ne correspond pas à CSP ou CORS, il ne chargera tout simplement pas ce script ou fichier CSS, et il écrira quelque chose dans la console comme: "Faites attention à ce script, à cette ligne où vous initialisez lui. Regardez, vous avez quelque chose de mal! " .


La documentation MDN , OWASP et W3C fournit des directives pour l'application des politiques CSP et CORS. De plus, tout outil de test d'intrusion signalera la conformité aux règles CORS et CSP du projet. Tout cadre ou outil qui effectuera des tests automatiques d'un projet signalera des failles.


Authentification des utilisateurs


Nous utilisons OpenID Connect et le protocole Kerberos. Un standard OpenID assez courant est utilisé pour authentifier les utilisateurs externes.


Kerberos est plus adapté au réseau interne, dans la banque il est utilisé pour l'authentification automatique des employés. Supposons qu'il existe une machine locale sur laquelle travaille un employé de l'organisation. Il s'est authentifié une fois sur cette machine, puis il n'aura plus besoin de saisir à nouveau le login et le mot de passe: l'employé se connecte à n'importe quelle application et le système l'authentifie immédiatement. Kerberos a des paramètres subtils pour la machine locale, ce qui est difficile car il doit être configuré pour chaque ordinateur et chaque navigateur. Si Internet Explorer récupère normalement les paramètres par défaut et que Chrome récupère les paramètres IE, Firefox doit le configurer séparément. Safari sur MacOS X trouvera les paramètres lui-même, mais pour Safari sur Windows, vous devrez les spécifier manuellement.


Vous devez vérifier votre application dans tous les navigateurs, que ce soit partout où il fonctionne comme il se doit. Par exemple, si je travaille sur Windows, j'installe Safari localement et y teste mon projet, et si je travaille sur Mac, j'élève Windows dans une machine virtuelle pour exécuter l'application sur les versions correspondantes des navigateurs.


L'authentification peut être implémentée dans des applications modernes à l'aide de Passport.js et de packages de session express, ainsi que du SDK Auth0.


Si vous ne parvenez pas à développer un service d'authentification via OpenID Connect ou tout autre protocole, utilisez une couche proxy, telle que Auth0 et similaires, afin que l'authentification s'effectue via une société tierce spécialisée dans la fourniture aux utilisateurs d'un accès sécurisé aux ressources Internet.


Lorsque nous mettons à niveau une application vers Node.js, nous vous recommandons d'utiliser les packages Passport.js, express-session, etc. sur le serveur. Pour assurer la sécurité du client, nous élevons indépendamment le composant pour l'authentification. N'oubliez pas de spécifier l'attribut de saisie semi-automatique sur le formulaire d'authentification pour exclure la saisie semi-automatique des champs du formulaire.


Hachage de mot de passe


Le site Web de l'OWASP vous recommande de ne pas utiliser de mécanismes de hachage de mot de passe intégrés à la base de données. Pour cela, il est préférable d'utiliser des packages tels que Argon2, PBKDF2, ccrypt et bcrypt. Dans ma pratique, j'utilise Argon2 - c'est un wrapper pour GCC, les algorithmes PGP / GPG, etc., mais il vous oblige à installer d'abord le paquet GCC. Schéma d'utilisation d'Argon2:



 1.  GCC >= 4.8 install $ brew install gcc 

 2.     - $ npm install -g node-gyp 

 3.   Argon2 $ npm install argon2 

 4.   import * as ARGON from 'argon2'; ARGON.generateSalt().then( (salt: string) => {  ARGON.hash('some-user-password', salt)    .then((hash : string) => {       console.log('Successfully created Argon2 hash:', hash);       // TODO: store the hash in the user database  }); }); argon2.verify( 'previously-created-argon-hash-here', 'some-user-password').then(() => {  console.log('Successful password supplied!');  // TODO: log the user in }).catch(() => {  console.log('Invalid password supplied!'); }); 

Obfuscation


L'obfuscation vous permet de modifier le code afin qu'il ne puisse pas être analysé en composants. Après tout, les attaquants - et pas seulement eux - utilisent très souvent la rétro-ingénierie: le programmeur prend un fichier JS et commence à analyser les sources. Ainsi, il peut apprendre les méthodes utilisées ou comprendre le mécanisme de travail d'un script particulier afin d'implémenter du code malveillant. Ou utilisez ces mécanismes pour pirater une application Web et mener une attaque furtive.


Les pirates informatiques n'ont pas de problèmes. Tout d'abord, ils effectuent l'exploration de la ressource, déterminent les vulnérabilités et attaquent le vecteur. Par exemple, ils manipulent des données ou exploitent des vulnérabilités contenues dans des protocoles de transport. Le vecteur d'attaque peut viser les vulnérabilités d'un système d'exploitation particulier; il y en a beaucoup dans n'importe quel système UNIX. Mais les vulnérabilités ne peuvent être utilisées que si l'administrateur a des politiques de sécurité mal configurées, par exemple, des URL mal définies qui sortent.


Ainsi, pour la reconnaissance, l'ingénierie inverse est utilisée. Il est impossible de l'exclure complètement, mais cela peut être très difficile. Pour cela, divers obfuscateurs sont utilisés, dans mon cas - javascript-obfuscator. Sur cette base, un plugin pour webpack est créé - webpack-obfuscator. Également pour webpack créé obfuscator-loader. Ce package a des paramètres recommandés pour différents niveaux de paranoïaques: faible, moyen et élevé, ils peuvent être trouvés sur le site officiel. Si vous utilisez cet obfuscateur, n'oubliez pas qu'il fonctionne très mal avec le mécanisme de minification intégré au webpack. N'utilisez pas la minification et l'obfuscation ensemble, sinon l'obfuscateur peut complètement casser le code du script.


De plus, l'obfuscateur augmente le volume du script et son chargement. Ici, vous devez décider par vous-même: soit vous améliorez la sécurité, la stabilité et la fiabilité, mais vous perdez en commodité et en vitesse; soit se soucier de la vitesse, mais oublier la sécurité, suivre toutes les directives.


Journalisation et surveillance des menaces


Il existe une menace telle que l'utilisation de packages avec des vulnérabilités déjà connues. Des analyseurs de menaces tels que npm audit, Snyk et LGTM vous aideront dans de telles situations. Npm audit est un utilitaire standard intégré à npm, mais vous devez constamment appeler cette commande ou proposer des béquilles. Par conséquent, je vous conseille d'utiliser Snyk. Ce projet possède sa propre base de données avec des vulnérabilités. Lorsque vous démarrez le test, Snyk accède à cette base de données et télécharge en toute confidentialité le rapport dans votre projet Snyk, qui n'est pas accessible aux tiers. Certes, vous ne pouvez vérifier votre projet gratuitement que 300 fois, et lorsque vous vérifiez chaque pré-validation, ces 300 tentatives gratuites se terminent très rapidement. Par conséquent, il est préférable d'exécuter un test pour les hooks de pré-push ou de pré-fusion.


L'homme est la vulnérabilité la plus importante de tout système. Par conséquent, assurez-vous de vérifier le projet avant de commencer à créer l'application, car même le code source peut contenir quelque chose de malveillant. C'est bien quand une seule personne a accès au projet, mais nous travaillons généralement en équipe. Et si une sorte de «bien intentionné» apparaissait qui décidait de quitter «magnifiquement» l'entreprise et de laisser une marque? Il faut également garder cela à l'esprit.


Je recommande d'utiliser le package Snyk dès le début du projet et de lancer l'analyse à partir de la console. Tout est simple ici: après l'installation, définissez le login et le mot de passe du compte, et le test lui-même peut être effectué comme ceci:


  • Après avoir installé la dépendance npm i snyk —D et spécifié «snyk»: true dans package.json, exécutez:

 ./node_modules/.bin/snyk wizard --dev 

  • Dans package.json, ajoutez des scripts et des paramètres:

 { ... "scripts": {  ...  "test": "npm run test:snyk && npm run test:jest",  ...  "test:snyk": "snyk test --dev",  ...  "prepare": "npm run prepare:snyk",  "prepare:snyk": "snyk protect" }, "husky": {  "hooks": {   "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",   "pre-commit": "npm run test:snyk && npm run lint && npm run test:jest",   "pre-push": [    "npm run test:snyk",    "npm run lint",    "npm run test:jest",    "npm run build:production"   ],   ...  } }, "snyk": true } 

Ci-dessus, nous avons examiné une vérification locale des menaces de sécurité. Pour vérifier les packages pour les menaces connues, je recommande également d'utiliser LGTM. Utilisez ce projet en conjonction avec GitHub ou Bitbucket (jusqu'à ce que vous l'ayez essayé, ce n'était pas nécessaire), et le code sera vérifié immédiatement à chaque push.


Surveillance des applications


Dans le domaine du Front-end, les outils sont déjà bien établis; des outils pour tous les goûts sont disponibles pour la journalisation et le suivi de la partie client. Les plus célèbres sont Sentry, TrackJS et InsightOps. Sentry Server peut être déployé sur ses serveurs physiques. Par exemple, dans nos deux projets, nous avons utilisé un serveur distinct, qui était entièrement configuré pour enregistrer le fonctionnement des applications. Nous sommes allés à l'URL et y avons déposé tous les journaux. Si une erreur se produit dans l'application, elle est enveloppée dans un bloc try catch et envoyée au serveur Sentry via les méthodes du package raven. Tout est simple et pratique. Si vous voyez des URL obscures dans Sentry que vous n'avez pas enregistrées, si vous voyez des incorporations ou des messages obscurs, alors ils essaient de vous pirater. Dans ma pratique, cela arrivait régulièrement. Par exemple, l'un des projets - un service pour contourner les bloqueurs de publicités et les antivirus - essayait constamment de contrecarrer, de casser.


Pour la surveillance, je recommande également d'utiliser Grafana. Il est important de considérer un système de critères et d'indicateurs qui sera contrôlé par le système. Nous avons suivi le trafic, le retour de la publicité, le degré de rendu des publicités, le nombre de bannières provenant de Yandex, etc. (projets dans Rambler Group). Nous devions comprendre comment Yandex fonctionne avec nos demandes, car il s'agit d'un service tiers, ce qui signifie qu'il doit être surveillé, car s'il échoue, le projet entier peut s'effondrer complètement.


Si vous surveillez toutes les communications avec des services tiers, vous trouverez très rapidement toute erreur. L'histoire vient de ma pratique: nous avons vu que de Yandex, les réponses publicitaires ont brusquement cessé de venir. Il s'est avéré qu'il y avait des dysfonctionnements techniques et l'ensemble du réseau publicitaire a connu une forte baisse. Et ce n'est pas Yandex qui nous a informés en premier, mais nous les avons appelés et leur avons demandé de voir ce qui se passait avec leurs services.


Quelle est la meilleure façon de surveiller? Prenez une petite URL, écrivez les paramètres GET et envoyez une demande GET à cette URL. Côté serveur, traitez cette URL, écrivez le journal dans la base de données et augmentez la surveillance à Grafana. Tout est simple.


C’est tout. À l'avenir, j'essaierai de continuer à écrire sur le thème de la protection des applications Web contre les menaces. À tous ceux qui ont lu jusqu'au bout - je souhaite la sécurité à vos projets)))


Liste des sources de lecture sur le sujet:


www.owasp.org/index.php/Main_Page


tproger.ru/translations/webapp-security


S. Hawks. Application Single Page encore plus rapide: sécurité


Seacord, Robert C. Norme de codage sécurisé CERT C / Robert C. Seacord. - 2008


Chetan Karande. Sécurisation des applications de nœuds - 2017


Steven Palmer. Les vulnérabilités des applications Web détectent, exploitent et préviennent - 2011


Robert Shimonski, Sean-Philip Oriyano. Attaques côté client et défense - 2012


Marcus Pinto, Dafydd Stuttard. Manuel du pirate d'applications Web: recherche et exploitation des failles de sécurité, 2e édition - 2011


Karl Duuna. Sécurisez votre application Web Node.js - 2015

Source: https://habr.com/ru/post/fr445932/


All Articles