Devoxx 2017 : Retour sur « Building Secure Angular Applications »

J’ai eu la chance de participer cette année à la 6ème édition du Devoxx France. Je vous propose dans cet article de revenir sur une des conférences que j’ai particulièrement appréciée dont le thème était "Building Secure Angular Applications" présentée par Philippe De Ryck. Philippe De Ryck est expert en sécurité, a un doctorat en sécurité web côté client et est l'auteur du livre "Primer on client-side web security". Il est par ailleurs membre de l'organisation SecAppDev.org.

De plus en plus d'applications utilisent aujourd'hui les frameworks AngularJS et Angular 2 pour le développement du front-end. Philippe De Ryck nous a donc présenté comment sécuriser ces applications en 4 parties :

  • Que faire contre le cross-site scripting (XSS)
  • Se protéger contre le code non-vérifié récupéré via d'autres serveurs
  • Reprendre le contrôle avec le Content Security Policy (CSP)
  • Sandboxer le code non-vérifié intégré dans une iframe

Cross-Site Scripting en Angular

Dans une attaque de type Cross-Site Scripting(XSS), du code malveillant est injecté dans les pages de votre application par exemple via un champ de saisie. À l'origine, uniquement du Javascript était injecté mais aujourd'hui du CSS, du HTML ou encore du SVG peut être injecté dans vos pages.

Dès le moment où l'on peut ouvrir une popup en injectant <script>alert('XSS')</script>, votre page est susceptible de subir une attaque de type XSS. En effet, aujourd'hui des logiciels comme BeEF (The Browser Exploitation Project), permettent d'injecter des scripts JS et de profiter des failles XSS.

Les traditionnelles méthodes pour se défendre contre ce type d'attaques consistent à échapper les caractères spéciaux des paramètres passés. En Angular, les variables passées dans les pages HTML via le binding encodent le contenu par défaut. Mais Angular est flexible et on peut passer du code HTML à l'aide de l'attribut innerHTML. Le Sanitizer d'Angular protège nos pages de cette méthode d'injection mais il est possible de le contourner à l'aide de méthodes comme bypassSecurityTrustHTML() ou encore bypassSecurityTrustScript.

L'échappement des données bindées et le Sanitizer d'Angular nous protègent de l'injection de contenu malveillant par XSS. Cependant, Angular est aussi assez souple pour passer à travers ses protections donc pour se protéger des attaques XSS, n'essayez pas d'outrepasser la sécurité, Angular fera le reste pour vous !

 

Code non-vérifié récupéré sur d'autres serveurs

On a besoin pour nos applications de récupérer du code stocké sur d'autres serveurs pour utiliser des frameworks ou mettre des pubs par exemple.

Si du code malveillant est renvoyé à la place du code attendu, celui-ci sera exécuté dans votre application. Par exemple, pour récupérer Angular, vous pouvez appeler un CDN via https://un-cdn.com/angular/2.0.0.js.  Pour vérifier que le fournisseur n'est pas compromis ou que le code n'a pas été modifié, vous pouvez utiliser le SRI (SubResource Integrity). Il permet d'ajouter un attribut integrity avec comme valeur le checksum associé au script; ainsi le navigateur vérifiera le checksum avant d'inclure le script. De nombreux CDN permettent aujourd'hui d'obtenir la balise script permettant l'ajout de librairies avec le SRI inclus. Sinon on peut le récupérer facilement via des sites qui proposent de générer le hash SRI.

SRI permet donc de s'assurer du code externe que l'on charge dans notre application.

 

Reprendre le contrôle avec CSP

Le Content Security Policy (CSP) est un système de sécurité fourni par les navigateurs. Ce système est fourni par le serveur dans l'entête d'une réponse HTTP ou dans un tag meta. Les scripts externes ne sont chargés que s'ils sont explicitement whitelistés et les "inline" scripts sont bloqués et ne seront pas exécutes.

Ce mécanisme est très strict et va donc bloquer par exemple tous les appels aux CDN permettant de charger les librairies dont nous avons besoin pour notre application. Nous pouvons alors décider de whitelister les CDN nécessaires comme ceci :

Content-Security-Policy: script-src 'self' https://cdnjs.cloudflare.com

Cependant, whitelister des adresses externes est dangereux car certaines d'entre-elles permettent de bypasser le CSP. La solution est donc d'utiliser l'attribut nonce sur nos balises scripts en lui fournissant une valeur random et de l'indiquer dans le CSP.

<script nonce="SuperRandom"...
Content-Security-Policy: script-src 'self' 'nonce-SuperRandom'

Une autre difficulté est lorsque l'on a besoin d'inclure des composants externes comme par exemple un flux Twitter. La valeur strict-dynamic va permettre de propager la confiance fourni par une balise avec nonce pour tous ce qu'on va y mettre (par exemple un flux Twitter).

Content-Security-Policy: script-src 'self' 'nonce-SuperRandom' 'strict-dynamic'

Seuls les navigateurs Chrome et Firefox prennent en compte le strict-dynamic. Pour les autres navigateurs, whitelister chaque URL est alors nécessaire.

 

Sandboxer le code d'une iframe

Pour sécuriser le code inclus dans une iframe, il existe l'attribut sandbox pour la balise iframe. Cet attribut bloque énormément de choses par défaut : Origine unique, pas d'exécution de scripts, pas de soumission de formulaires, pas de navigation externe ou de popups, pas de fullscreen, pas d'autoplay,... Cependant, on peut fournir des valeurs à cet attribut lui permettant d'être plus souple comme "allow-scripts".

Pour envoyer un message à une iframe sandboxée, il faut utiliser l'origine "*" :

let frame = <HTMLIFrameElement>document.getElementById("frame");
frame.contentWindow.postMessage("The Message", "*");

Pour recevoir un message, il faut bien faire attention à l'origine de celui-ci :

let self = this;
window.addEventListener("message", function(event) {
    if(event.origin ==="http://localhost:4200") {
        self.data = event.data;
    }
});

Tous les navigateurs fournissent aujourd'hui ce mécanisme d'iframe sandboxée.

 

En conclusion, ces quatre éléments peuvent vous permettre facilement de sécuriser le front-end de vos applications AngularJS et Angular 2.

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.