Les fondamentaux pour sécuriser une (application) MEAN ?

Magazine
Marque
MISC
Numéro
101
|
Mois de parution
janvier 2019
|
Domaines


Résumé
MEAN est un socle technique composé de MongoDB, Express, Angular et Node.js. Ces quatre composants ont un point commun : le JavaScript ! La connaissance de cet unique langage de programmation vous permet désormais de créer une application web dynamique et moderne. Ce socle technique est donc largement utilisé par les développeurs « full stack » et c’est ainsi que de nombreuses applications MEAN viennent s’installer progressivement dans les SI des entreprises. Mais voilà ! Ce socle technique est-il suffisant pour développer des applications sécurisées qui seront amenées à manipuler des données sensibles (carte bancaire, santé…) ?

Body

1. Architecture MEAN

L’architecture d’une application développée avec le socle MEAN est relativement simple. Elle est composée de 2 grandes parties :

  • le front-end : Angular ;
  • le back-end : Express, Node.js et MongoDB.

Article 1 - Architecture MEAN

Figure 1

1.1 Angular

Angular est le framework de Google pour développer des applications web monopage (SPA = Single Page Application). Une application Angular est constituée de fichiers statiques (HTML, CSS et JS) que l’utilisateur doit télécharger depuis un serveur HTTP.

REACT est une alternative à Angular. Dans ce cas, le socle technique est appelé « MERN ».

1.2 Node.js

Node.js est un environnement d’exécution JavaScript offrant de nombreux outils aux développeurs, dont NPM (Node Package Manager). Le composant principal est le moteur JavaScript « V8 » créé par Google pour Chrome/Chromium. Les performances de ce moteur, parfois supérieures à PHP, permettent désormais de l’utiliser en entreprise.

JavaScript, TypeScript, ECMAScript, CoffeeScript… Il y a de quoi s’y perdre !

Il faut savoir que le standard ECMAScript définit les bases d’un langage de script (types, boucles, conditions…). Pour être conforme, un langage de script doit a minima implémenter les bases indiquées dans la norme.

Le JavaScript n’est qu’une implémentation par Mozilla du standard. Mais il y a beaucoup d’autres implémentations : TypeScript par Microsoft, ActionScript par Adobe.

1.3 Express

Express est un framework de développement pour Node.js. Il permet de développer rapidement en JavaScript des applications web. Express et Node.js constituent la première partie du backend.

Un guide officiel décrivant les bonnes pratiques de sécurité est disponible sur le site de l’éditeur [1].

Depuis février 2016, ce framework est soutenu par la Fondation Node.js [7] avec une forte contribution de la part d’IBM via StrongLoop.

1.4 MongoDB

MongoDB est une base de données NoSQL orientée document. La menace d’injection est toujours présente puisque « NoSQL » ne signifie malheureusement pas « No Injection » [2].

En complément, un ODM (Object Data Model), tel que Mongoose, est souvent utilisé pour simplifier l’accès à la base de données. Il permet également de prendre en charge des fonctions de chiffrement des données ou signature des données.

En comptant bien, l’architecture MEAN contient 3 composants (Angular + Express / Node.js + MongoDB). Nous pourrions rapidement en conclure que cette architecture est conforme à l’architecture « 3 tiers », la référence dans le domaine de la sécurité.

Mais voilà, 3 tiers ne signifie pas 3 composants, mais 3 pare-feux avec 3 zones réseau : présentation, métier et données.

La confusion est induite par l’application Angular qui constitue le front-end et s’exécute dans le navigateur de l’utilisateur. En termes de sécurité, seul le back-end sera pris en compte avec 2 zones réseaux : application (Express et Node.js) et données (MongoDB).

2. Express

Avant d’aller plus loin, il est nécessaire de comprendre certains concepts fondamentaux indispensables à la compréhension de la suite du dossier.

Express est un framework minimaliste qui permet de définir un pipeline pour traiter des requêtes HTTP. Ces requêtes sont traitées par des middlewares qui enrichissent au fur et à mesure la requête (objet req) et/ou la réponse HTTP (objet res).

Article 1 - Express Pipeline

Figure 2

Un middleware est un module développé pour effectuer une petite fonctionnalité. Par défaut, le framework Express contient quelques middlewares de base comme le routeur. Ils sont inclus nativement dans le framework. En complément, Express propose des middlewares additionnels que vous pouvez installer (exemple : express-session ou express-cookie).

Mais vous trouverez également de nombreux middlewares réalisés par des sociétés ou des particuliers, c’est notamment le cas de PassportJS. Avant d’utiliser un middleware, il est important de réaliser quelques points de contrôles : est-il toujours maintenu ? Y a-t-il des bogues de sécurité connus et non corrigés ? Utilise-t-il des frameworks avec une vulnérabilité connue ? ...

Pour démarrer rapidement un nouveau pipeline Express avec les principaux middlewares, il suffit d’utiliser l’outil Express Generator. Il crée automatiquement la structure minimum nécessaire au fonctionnement d’une application avec notamment :

  • le dossier « Routes » contenant la logique de routage ;
  • le dossier « Views » contenant les vues en fonction du moteur de rendu choisi (jade, pug…) ;
  • le fichier « app.js » contenant le code principal de l’application.

Cette structure se conforme aisément au standard MVC (Model / View / Controller) pour structurer le code :

Article 1 - Express MVC

Figure 3

Le concept MVC (Model / View / Controller) est une manière de structurer le code source d’une application (Design Pattern). Il y a bien trois parties, mais ce n’est pas pour autant une architecture 3 tiers.

Vous voilà maintenant familiarisés avec Express ! Nous pouvons maintenant aborder la sécurité d’Express et les middlewares liés à la sécurité.

3. HTTPS Express

L’utilisation du protocole HTTPS est une mesure fondamentale qu’une application Express se doit d’implémenter. Pour cela, deux options s’offrent à vous :

  • une terminaison TLS portée par une passerelle (reverse proxy) devant l’application ;
  • une terminaison TLS portée directement par l’application.

À noter que ces deux solutions ne sont pas incompatibles entre elles et il est tout à fait envisageable de les combiner. Quelle que soit la solution retenue, il vous faudra un nom de domaine et un certificat pour dérouler la suite de l’article. Pour tester, un certificat auto-signé et une entrée dans le fichier host feront l’affaire.

3.1 Solution 1 : Terminaison TLS par proxy

Dans cette configuration, l’architecture sera la suivante :

Article 1 - proxy nginx

Figure 4

3.1.1 Étape 1 : Configurer Nginx

La configuration ci-dessous permettra de transférer les en-têtes HTTP « X-forwarded-* » à l’application Express :

server {

  listen *:443;

  server_name proxy.example.com;

  # TLS settings

  ssl on;

  ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;

  ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

  # modern configuration. tweak to your needs.

  ssl_protocols TLSv1.2;

  ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AE$

  ssl_prefer_server_ciphers on;

  location / {

    # HTTPS Headers

    proxy_set_header X-Forwarded-Host $host;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header X-Forwarded-Proto $scheme;

    # Express App

    proxy_pass http://app.example.com:3000/;

  }

}

3.1.2 Étape 2 : Configurer l’application

Par défaut, une application Express ne fonctionnera pas de manière optimale derrière un proxy. Par exemple, les entêtes HTTP ne seront pas pris en compte et un « secure cookie » ne pourra être transmis avec le protocole HTTP. Pour y remédier, il faut activer l’option « trust proxy » en indiquant l’adresse IP des proxies [3].

Les modifications à apporter dans le fichier app.js sont :

app.set('trust proxy', process.env.PROXY);

Ainsi, le trust proxy sera activé uniquement pour les requêtes venant des adresses IP des proxies mentionnées dans la liste. Les requêtes provenant d’autres sources ne sont pas bloquées pour autant.

L’activation du « trust proxy » a pour effet :

  • la valeur de req.hostname est définie à partir de l’en-tête « X-Forwarded-Host » ;
  • la valeur de req.protocol est définie à partir de l’en-tête « X-Forwarded-Proto », lui-même défini par le proxy. Ainsi, le proxy peut indiquer à l’application que le protocole utilisé est HTTPS alors que l’application est en HTTP ;
  • les valeurs de req.ip et req.ips sont définies avec la liste des adresses IP présentes dans l’en-tête « X-Forwarded-For ». Req.ip contient la première adresse IP de la liste. L’option Trust Proxy est indispensable pour générer correctement les traces dans votre SIEM.

Les effets mentionnés ci-dessus ne sont valables que pour les adresses IP indiquées. Pour les requêtes venant d’autres adresses IP, les valeurs ne seront pas modifiées.

3.2 Solution 2 : Terminaison TLS par l’application

Par défaut, une application Express utilise le module HTTP pour créer le serveur qui recevra les requêtes. Mais il est très simple de modifier une application Express pour utiliser le module HTTPS de Node.js.

Par exemple, pour une application créée avec Express Generator, il faut modifier le script de lancement de l’application (bin/www) comme ceci :

/**

* Module dependencies.

*/

var fs = require('fs');

var https = require('https');

/**

* Create HTTP(s) server.

*/

// HTTPS setup

var options = {

  // Private key

  key: fs.readFileSync('./tls/key.pem'),

  // Certificate

  cert: fs.readFileSync('./tls/cert.pem'),

  // Protocol : only TLS 1.2

  secureProtocol: 'TLSv1_2_method',

  // Cipher Suites

ciphers:"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",

};

// Create HTTPS server

var server = https.createServer(options, app);

Dans la section Module dependencies, il faut ajouter les 2 modules nécessaires :

  • fs pour lire les fichiers contenant la clé et le certificat ;
  • https pour remplacer le module http.

Dans la section Create HTTP(s) server, il faut configurer le protocole TLS : clé privée, certificat et les options de chiffrement. Dans l’exemple ci-dessus, les suites de chiffrement sont conformes au profil « modern » défini par Mozilla [4].

4. Session Express

Express vous propose deux solutions pour conserver les informations relatives à l’utilisateur :

  • Express Session : les informations sont conservées sur le serveur dans une base de données ;
  • Cookie Session : les informations sont conservées dans un cookie.

4.1 Express Session

Le middleware « Express-Session » permet de conserver les données, liées à la session en cours, sur le back-end. Un cookie de session nommé « connect.sid » contiendra seulement l’identifiant de la session.

La suite de cet article décrit la réalisation du prototype, disponible sur GitHub. Pour le stockage des sessions, ce prototype utilise Redis, une base de données clé/valeur réputée pour sa rapidité. Le middleware « connect-redis » sera donc nécessaire.

4.1.1 Étape 1 : Installer les middlewares

$ npm install --save  express-session connect-redis

4.1.2 Étape 2 : Configurer l’application

Éditer le fichier app.js pour y ajouter le code ci-dessous :

// Loading middleware

const Session = require('express-session');

const RedisStore = require('connect-redis')(Session);

// Session store setup

const SessionStore = new RedisStore({

    host: process.env.REDISHOST,

    port: process.env.REDISPORT,

    pass: process.env.REDISPASSWORD

  });

// Express Session middleware setup

app.use(Session({

    store: SessionStore,

    secret: process.env.COOKIESECRET,

    resave: false,

    saveUninitialized: false,

    cookie:{path: '/', httpOnly: true, secure: true, maxAge: 600000, sameSite: 'strict'}

}));

Le paramètre Secret est indispensable, car les cookies de session sont obligatoirement signés. La structure d’un cookie est la suivante après avoir effectué un décodage HTML :

Article 1 - Cookie

Figure 5

Ainsi, même si une personne malveillante « devine » l’identifiant de session d’un utilisateur, elle ne pourra pas créer un cookie valide, car elle ne connaît pas le secret nécessaire à la création de la signature.

Le paramètre saveUninitialized est un booléen dont la signification est la suivante :

  • true : la session sera créée pour tout visiteur ce qui peut monopoliser des ressources inutilement sur le serveur ;
  • false : la session (et le cookie) sera créée uniquement lorsque l’application initialisera la session en y enregistrant une donnée.

4.2 Cookie Session

Le middleware « cookie-session » est une alternative au middleware précédent. Aucune information ne sera stockée sur le back-end puisque toutes les données de la session seront stockées dans le cookie. Attention toutefois à ne pas y stocker trop d’informations, car la taille des cookies est limitée à 4 Ko.

4.2.1 Étape 1 : Installer les middlewares

$ npm install --save cookie-session

4.2.2 Étape 2 : Configurer le middleware

// Configure middleware

app.use(cookieSession({

  name: 'session',

  keys: new Keygrip([process.env.COOKIESECRET], 'SHA256', 'base64'),

 

  // Cookie Options

  path: '/',

  httpOnly: true,

  secure: true,

  signed: true,

  maxAge: 600000, // 10 minutes

  sameSite: 'strict'

}));

Ce middleware ainsi configuré génère deux cookies à l’initialisation de la session :

  • session : ce cookie contient toutes les données de la session au format JSON et encodé en base64 ;
  • session.sig : ce cookie contient la signature du cookie de session. L’algorithme utilisé est le SHA256 encodé en base 64. L’algorithme par défaut est le SHA1.

5. CSRF

Une application MEAN se doit de se protéger contre les attaques de type CSRF [5]. Il est donc important de bloquer les requêtes qui seraient initiées à l’insu de l’utilisateur depuis un site internet malveillant.

La solution la plus efficace est d’utiliser l’attribut samesite sur l’ensemble de vos cookies et en particulier le cookie de session. C’est ce qui a été réalisé dans les prototypes précédents.

Même si largement supporté par les navigateurs [6], l’attribut samesite n’est pas encore validé par l’IETF. Pour garantir une protection avec les navigateurs ne supportant pas l’attribut samesite, il faudra implémenter une solution à base de jeton anti-csrf sur le back-end et le front-end.

5.1 Back-end

Au niveau du back-end, Express propose le middleware « CSurf » qui permet de générer des jetons anti-CSRF et d’en contrôler la validité.

Pour chaque requête entrante, le middleware génère un jeton qui sera ajouté à la réponse sous l’une des formes suivantes :

  • dans un cookie généralement nommé « XSRF-TOKEN » ;
  • dans un champ caché d’un formulaire ;
  • dans une balise HTML meta.

La structure des jetons est la suivante :

Article 1 - TokenCSRF

Figure 6

Le secret utilisé pour signer le jeton doit être unique par utilisateur. Ainsi, un jeton généré pour un utilisateur ne pourra pas être utilisé pour valider une requête d’un autre utilisateur. Néanmoins, cela nécessite de conserver les secrets soit dans la session de l’utilisateur, soit dans un cookie nommé par défaut « _csrf ».

5.2 Front-end

Les applications web développées avec Angular supportent nativement les jetons anti-csrf. Le fonctionnement est le suivant :

  1. L’application web reçoit, du back-end, un cookie nommé « XSRF-TOKEN » contenant une valeur aléatoire. Ce cookie ne doit pas être en « HTTPonly », car l’application web doit être en mesure de le lire.
  2. Pour chaque requête HTTP demandant la modification des données (POST, PUT, DELETE…), le front-end récupère la valeur du cookie et l’injecte dans l’en-tête HTTP nommé « X-XSRF-TOKEN ».

Si les jetons anti-csrf étaient nativement supportés avec les premières versions d’Angular (module HTTP), les versions plus récentes (module HTTPClient) devront explicitement l’activer en important le module HttpClientXsrfModule.

Conclusion

Le socle technique MEAN ne vous assure pas une application sécurisée. Les développeurs doivent prendre connaissance des risques auxquels est exposée leur application. Ils devront alors implémenter les mesures adéquates au cours du développement. Et comme vous avez pu le constater tout au long de cet article, ce n’est pas si facile.

Express propose de nombreux middlewares pour assurer certaines fonctions de sécurité. Mais cela ne permet pas de couvrir l’ensemble des fonctions de sécurité, comme l’authentification, et vous devrez faire appel à des modules tiers : PassportJS, Helmet, Kraken, Node-ESAPI…

Références

[1] https://expressjs.com/en/advanced/best-practice-security.html

[2] https://www.owasp.org/index.php/Testing_for_NoSQL_injection

[3] https://expressjs.com/en/guide/behind-proxies.html

[4] https://wiki.mozilla.org/Security/Server_Side_TLS

[5] https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

[6] https://caniuse.com/#feat=same-site-cookie-attribute

[7] https://nodejs.org/en/blog/announcements/foundation-express-news/


Sur le même sujet

Contournement de l'API Google Play Billing

Magazine
Marque
MISC
Numéro
106
|
Mois de parution
novembre 2019
|
Domaines
Résumé

D'après le blog [INVESP], le montant global des paiements dits « in-app » représentait environ 37 milliards de dollars (USD) en 2017 pour les applications mobiles (Android et Apple). Ce montant représente quasiment la moitié des revenus générés par les applications mobiles (48,2%), dépassant les revenus générés par les régies publicitaires (14%), ainsi que l'achat d'applications (37,8%). Il est donc important que la sécurité de ces paiements soit correctement implémentée afin d'éviter un manque à gagner pour les développeurs des applications. Dans le cadre de cet article, nous avons passé en revue 50 applications Android afin d'étudier le fonctionnement de l'API Google Play Billing et d'identifier les vulnérabilités liées à une mauvaise implémentation. Nous détaillerons en exemple des applications vulnérables.

Introduction au dossier : éprouver la sécurité des applications mobiles

Magazine
Marque
MISC
Numéro
106
|
Mois de parution
novembre 2019
|
Domaines
Résumé

Il serait difficile de vous convaincre qu’aujourd’hui les applications mobiles ne représentent qu’une part minime de nos usages « numériques », et qu’il n’y a aucun risque de sécurité associé. La réalité est en effet bien différente, et dans le domaine des statistiques de la démesure, le volume de smartphones vendus a de quoi impressionner : plus d’un milliard par an depuis 2015.

L’intégration du « Privacy by Design » et de la SSI dans la gestion de projets en mode V ou Agile

Magazine
Marque
MISC
Numéro
106
|
Mois de parution
novembre 2019
|
Domaines
Résumé

L’analyse de l’actualité ne cesse de nous alerter sur la très faible prise en compte de la sécurité native dans un grand nombre de projets et plus particulièrement sur la sous-estimation de l’intégration des exigences de protection de la vie privée.Les articles 25 du RGPD « Protection des données dès la conception et protection des données par défaut » et 32 « Sécurité du traitement », formalisent l’obligation pour le responsable du traitement de prendre en compte les exigences juridiques et techniques pendant toutes les phases des projets de la conception jusqu’à la fin de vie du système cible.Nous nous attacherons à identifier les principaux acteurs concernés et leurs modes de concertation dans les gestions de projets en V ou Agile.Nous chercherons à souligner les points d’attention et d’amélioration dans les deux méthodes.

Élévation de privilèges sur macOS avec CVE-2018-4193

Magazine
Marque
MISC
Numéro
106
|
Mois de parution
novembre 2019
|
Domaines
Résumé

Cet article explique comment exploiter la CVE-2018-4193, une élévation de privilèges affectant les versions de macOS inférieures à 10.13.5, en moins de 10 secondes. Les différents prérequis nécessaires à la compréhension de l’exploit seront détaillés de sorte qu’aucune connaissance préalable de macOS ne soit nécessaire, ce qui permet d’aborder l’exploitation de vulnérabilités dans les démons macOS en général.

Par le même auteur

Contrôle d’identité avec Passport

Magazine
Marque
MISC
Numéro
101
|
Mois de parution
janvier 2019
|
Domaines
Résumé
On ne plaisante pas avec un contrôle d’identité ! Il en va de même en sécurité applicative où l’authentification est une fonctionnalité primordiale à mettre en œuvre. Mais quand il faut s’y mettre, le développeur sera confronté à de nombreuses problématiques et se posera beaucoup de questions sans y trouver de réponses, faute d’avoir un expert en sécurité applicative à sa disposition.Tout au long de cet article, vous suivrez pas à pas le questionnement d’un développeur back end accompagné d’un expert sécurité pour l’aider dans son raisonnement.

Les fondamentaux pour sécuriser une (application) MEAN ?

Magazine
Marque
MISC
Numéro
101
|
Mois de parution
janvier 2019
|
Domaines
Résumé
MEAN est un socle technique composé de MongoDB, Express, Angular et Node.js. Ces quatre composants ont un point commun : le JavaScript ! La connaissance de cet unique langage de programmation vous permet désormais de créer une application web dynamique et moderne. Ce socle technique est donc largement utilisé par les développeurs « full stack » et c’est ainsi que de nombreuses applications MEAN viennent s’installer progressivement dans les SI des entreprises. Mais voilà ! Ce socle technique est-il suffisant pour développer des applications sécurisées qui seront amenées à manipuler des données sensibles (carte bancaire, santé…) ?