Cette page décrit les protections intégrées d'Angular contre les vulnérabilités et attaques courantes des applications web, comme les attaques de cross-site scripting. Elle ne traite pas de la sécurité au niveau applicatif, comme l'authentification et l'autorisation.
Pour plus d'informations sur les attaques et les mesures de protection décrites ci-dessous, consultez le guide de l'Open Web Application Security Project (OWASP).
Signaler des vulnérabilités
Angular fait partie du programme de récompenses pour les vulnérabilités des logiciels open source de Google. Pour les vulnérabilités d'Angular, soumettez votre rapport sur https://bughunters.google.com.
Pour plus d'informations sur la manière dont Google traite les problèmes de sécurité, consultez la philosophie de sécurité de Google.
Bonnes pratiques
Voici quelques bonnes pratiques pour garantir la sécurité de votre application Angular.
- Restez à jour avec les dernières versions des libraries Angular - Les libraries Angular reçoivent des mises à jour régulières, et ces mises à jour peuvent corriger des failles de sécurité découvertes dans des versions précédentes. Consultez le change log d'Angular pour les mises à jour liées à la sécurité.
- Ne modifiez pas votre copie d'Angular - Les versions privées et personnalisées d'Angular ont tendance à prendre du retard sur la version actuelle et peuvent ne pas inclure d'importants correctifs et améliorations de sécurité. Partagez plutôt vos améliorations d'Angular avec la communauté en ouvrant une pull request.
- Évitez les API Angular signalées dans la documentation comme « Security Risk » - Pour plus d'informations, consultez la section Faire confiance aux valeurs sûres de cette page.
Prévenir le cross-site scripting (XSS)
Le cross-site scripting (XSS) permet à des attaquants d'injecter du code malveillant dans des pages web. Ce code peut alors, par exemple, voler des données utilisateur et des identifiants de connexion, ou effectuer des actions en se faisant passer pour l'utilisateur. C'est l'une des attaques les plus courantes sur le web.
Pour bloquer les attaques XSS, vous devez empêcher le code malveillant d'entrer dans le Document Object Model (DOM).
Par exemple, si des attaquants parviennent à vous faire insérer une balise <script> dans le DOM, ils peuvent exécuter du code arbitraire sur votre site web.
L'attaque ne se limite pas aux balises <script> : de nombreux éléments et propriétés du DOM permettent l'exécution de code, par exemple <img alt="" onerror="..."> et <a href="javascript:...">.
Si des données contrôlées par un attaquant entrent dans le DOM, attendez-vous à des vulnérabilités de sécurité.
Le modèle de sécurité d'Angular contre le cross-site scripting
Pour bloquer systématiquement les failles XSS, Angular considère par défaut toutes les valeurs comme non fiables. Lorsqu'une valeur est insérée dans le DOM depuis un binding de template ou une interpolation, Angular assainit et échappe les valeurs non fiables. Si une valeur a déjà été assainie en dehors d'Angular et est considérée comme sûre, indiquez-le à Angular en marquant la valeur comme étant de confiance.
Contrairement aux valeurs destinées au rendu, les templates Angular sont considérés par défaut comme dignes de confiance et doivent être traités comme du code exécutable. Ne créez jamais de templates en concaténant des saisies utilisateur et de la syntaxe de template. Cela permettrait à des attaquants d'injecter du code arbitraire dans votre application. Pour éviter ces vulnérabilités, utilisez toujours le compilateur de templates Ahead-Of-Time (AOT) par défaut dans vos déploiements de production.
Une couche de protection supplémentaire peut être apportée par l'utilisation de la Content Security Policy et des Trusted Types. Ces fonctionnalités de la plateforme web opèrent au niveau du DOM, qui est l'endroit le plus efficace pour prévenir les problèmes XSS. À ce niveau, elles ne peuvent pas être contournées par d'autres API de plus bas niveau. C'est pourquoi il est fortement recommandé de tirer parti de ces fonctionnalités. Pour cela, configurez la Content Security Policy de l'application et activez l'application obligatoire des Trusted Types.
Assainissement et contextes de sécurité
L'assainissement consiste à inspecter une valeur non fiable pour la transformer en une valeur qu'il est sûr d'insérer dans le DOM. Dans de nombreux cas, l'assainissement ne modifie pas du tout la valeur. L'assainissement dépend d'un contexte. Par exemple, une valeur inoffensive en CSS est potentiellement dangereuse dans une URL.
Angular définit les contextes de sécurité suivants :
| Contextes de sécurité | Détails |
|---|---|
| HTML | Utilisé lorsqu'une valeur est interprétée comme du HTML, par exemple lors d'un binding sur innerHtml. |
| Style | Utilisé lors d'un binding de CSS sur la propriété style. |
| URL | Utilisé pour les propriétés d'URL, comme <a href>. |
| Resource URL | Une URL chargée et exécutée comme du code, par exemple dans <script src>. |
Angular assainit les valeurs non fiables pour le HTML et les URL. Il est impossible d'assainir les URL de ressource, car elles contiennent du code arbitraire. En mode développement, Angular affiche un avertissement dans la console lorsqu'il doit modifier une valeur pendant l'assainissement.
Exemple d'assainissement
Le template suivant lie la valeur de htmlSnippet. Une fois en l'interpolant dans le contenu d'un élément, et une fois en la liant à la propriété innerHTML d'un élément :
inner-html-binding.component.html
<h3>Binding innerHTML</h3>
<p>Bound value:</p>
<p class="e2e-inner-html-interpolated">{{ htmlSnippet }}</p>
<p>Result of binding to innerHTML:</p>
<p class="e2e-inner-html-bound" [innerHTML]="htmlSnippet"></p>
Le contenu interpolé est toujours échappé : le HTML n'est pas interprété et le navigateur affiche les chevrons dans le contenu textuel de l'élément.
Pour que le HTML soit interprété, liez-le à une propriété HTML comme innerHTML.
Sachez que lier à innerHTML une valeur qu'un attaquant pourrait contrôler provoque normalement une vulnérabilité XSS.
Par exemple, on pourrait exécuter du JavaScript de la manière suivante :
inner-html-binding.component.ts (class)
export class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
Angular reconnaît la valeur comme non sûre et l'assainit automatiquement, ce qui supprime l'élément script tout en conservant le contenu sûr, comme l'élément <b>.
Utilisation directe des API du DOM et appels explicites d'assainissement
À moins d'imposer les Trusted Types, les API du DOM intégrées au navigateur ne vous protègent pas automatiquement des vulnérabilités de sécurité.
Par exemple, document, le nœud accessible via ElementRef et de nombreuses API tierces contiennent des méthodes non sûres.
De même, si vous interagissez avec d'autres libraries qui manipulent le DOM, vous ne bénéficierez probablement pas du même assainissement automatique qu'avec les interpolations Angular.
Évitez d'interagir directement avec le DOM et utilisez plutôt les templates Angular lorsque c'est possible.
Dans les cas où c'est inévitable, utilisez les fonctions d'assainissement intégrées d'Angular.
Assainissez les valeurs non fiables avec la méthode DomSanitizer.sanitize et le SecurityContext approprié.
Cette fonction accepte aussi les valeurs marquées comme étant de confiance à l'aide des fonctions bypassSecurityTrust, et ne les assainit pas, comme décrit ci-dessous.
Faire confiance aux valeurs sûres
Il arrive que des applications aient réellement besoin d'inclure du code exécutable, d'afficher une <iframe> depuis une URL donnée ou de construire des URL potentiellement dangereuses.
Pour empêcher l'assainissement automatique dans ces situations, indiquez à Angular que vous avez inspecté une valeur, vérifié comment elle a été créée et vous êtes assuré qu'elle est sûre.
Soyez prudent.
Si vous faites confiance à une valeur potentiellement malveillante, vous introduisez une vulnérabilité de sécurité dans votre application.
En cas de doute, faites appel à un expert en revue de sécurité.
Pour marquer une valeur comme étant de confiance, injectez DomSanitizer et appelez l'une des méthodes suivantes :
bypassSecurityTrustHtmlbypassSecurityTrustScriptbypassSecurityTrustStylebypassSecurityTrustUrlbypassSecurityTrustResourceUrl
N'oubliez pas que la sûreté d'une valeur dépend du contexte : choisissez donc le bon contexte pour l'usage prévu de la valeur.
Imaginez que le template suivant doive lier une URL à un appel javascript:alert(...) :
bypass-security.component.html (URL)
<h4>An untrusted URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
<h4>A trusted URL:</h4>
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
Normalement, Angular assainit automatiquement l'URL, désactive le code dangereux et, en mode développement, consigne cette action dans la console.
Pour l'éviter, marquez la valeur de l'URL comme une URL de confiance avec l'appel bypassSecurityTrustUrl :
bypass-security.component.ts (trust-url)
private sanitizer = inject(DomSanitizer);
constructor() {
// javascript: URLs are dangerous if attacker controlled.
// Angular sanitizes them in data binding, but you can
// explicitly tell Angular to trust this value:
this.dangerousUrl = 'javascript:alert("Hi there")';
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);

Si vous devez convertir une saisie utilisateur en valeur de confiance, utilisez une méthode du composant.
Le template suivant permet aux utilisateurs de saisir un identifiant de vidéo YouTube et de charger la vidéo correspondante dans une <iframe>.
L'attribut <iframe src> relève du contexte de sécurité Resource URL, car une source non fiable peut, par exemple, introduire en douce des téléchargements de fichiers que des utilisateurs non avertis pourraient exécuter.
Pour l'éviter, appelez une méthode du composant afin de construire une URL de vidéo de confiance, ce qui amène Angular à autoriser le binding sur <iframe src> :
bypass-security.component.html (iframe)
<h4>Resource URL:</h4>
<p>Showing: {{ dangerousVideoUrl }}</p>
<p>Trusted:</p>
<iframe
class="e2e-iframe-trusted-src"
width="640"
height="390"
[src]="videoUrl"
title="trusted video url"
></iframe>
<p>Untrusted:</p>
<iframe
class="e2e-iframe-untrusted-src"
width="640"
height="390"
[src]="dangerousVideoUrl"
title="unTrusted video url"
></iframe>
bypass-security.component.ts (trust-video-url)
updateVideoUrl(id: string) {
// Appending an ID to a YouTube URL is safe.
// Always make sure to construct SafeValue objects as
// close as possible to the input data so
// that it's easier to check if the value is safe.
this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
this.videoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
Politique de sécurité du contenu (Content Security Policy)
La Content Security Policy (CSP) est une technique de défense en profondeur pour prévenir le XSS.
Pour activer la CSP, configurez votre serveur web pour qu'il renvoie un en-tête HTTP Content-Security-Policy approprié.
Pour en savoir plus sur la Content Security Policy, consultez le guide Web Fundamentals sur le site Google Developers.
La politique minimale requise pour une toute nouvelle application Angular est la suivante :
default-src 'self'; style-src 'self' 'nonce-randomNonceGoesHere'; script-src 'self' 'nonce-randomNonceGoesHere';
Lorsqu'il sert votre application Angular, le serveur doit inclure un nonce généré aléatoirement dans l'en-tête HTTP de chaque requête.
Vous devez fournir ce nonce à Angular pour que le framework puisse effectuer le rendu des éléments <style>.
Vous pouvez définir le nonce pour Angular de l'une des manières suivantes :
- Définissez l'attribut
ngCspNoncesur l'élément racine de l'application, sous la forme<app ngCspNonce="randomNonceGoesHere"></app>. Utilisez cette approche si vous disposez d'un templating côté serveur capable d'ajouter le nonce à la fois à l'en-tête et àindex.htmllors de la construction de la réponse. - Fournissez le nonce avec le jeton d'injection
CSP_NONCE. Utilisez cette approche si vous avez accès au nonce à l'exécution et souhaitez pouvoir mettre en cacheindex.html.
import {CSP_NONCE} from '@angular/core';
import {bootstrapApplication} from '@angular/platform-browser';
import {AppComponent} from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
{
provide: CSP_NONCE,
useValue: globalThis.myRandomNonceValue,
},
],
});
Nonces uniques
Assurez-vous toujours que les nonces que vous fournissez sont uniques pour chaque requête et qu'ils ne sont ni prévisibles ni devinables. Si un attaquant peut prédire les futurs nonces, il peut contourner les protections offertes par la CSP.
Il est généralement déconseillé de générer un nonce sur le serveur d'origine lorsque vous utilisez un CDN, car les réponses sont fréquemment mises en cache. Si le serveur génère un nonce et que le CDN met en cache cette réponse HTML, chaque visiteur suivant reçoit la même valeur « unique », ce qui permet à un attaquant de découvrir cette valeur statique et de contourner les protections de la CSP.
Pour préserver l'intégrité « à usage unique » d'un nonce, celui-ci devrait idéalement être généré au niveau de la couche Edge (par exemple, le CDN) juste avant que le contenu ne soit livré à l'utilisateur.
Note : Si vous souhaitez intégrer en ligne le CSS critique de votre application, vous ne pouvez pas utiliser le jeton CSP_NONCE ; privilégiez alors l'option security.autoCsp dans la configuration du workspace ou définissez l'attribut ngCspNonce sur l'élément racine de l'application.
Si vous ne pouvez pas générer de nonces dans votre projet, vous pouvez autoriser les styles inline en ajoutant 'unsafe-inline' à la section style-src de l'en-tête CSP.
| Sections | Détails |
|---|---|
default-src 'self'; |
Permet à la page de charger toutes les ressources dont elle a besoin depuis la même origine. |
style-src 'self' 'nonce-randomNonceGoesHere'; |
Permet à la page de charger les styles globaux depuis la même origine ('self') et les styles insérés par Angular avec le nonce-randomNonceGoesHere. |
script-src 'self' 'nonce-randomNonceGoesHere'; |
Permet à la page de charger du JavaScript depuis la même origine ('self') et les scripts insérés par Angular CLI avec le nonce-randomNonceGoesHere. Requis uniquement lorsque vous activez l'intégration en ligne du CSS critique ou l'intégrité des sous-ressources (qui injecte une import map pour valider les chunks importés dynamiquement), qui ajoutent toutes deux des scripts inline à index.html. |
Angular lui-même n'a besoin que de ces paramètres pour fonctionner correctement. À mesure que votre projet grandit, vous devrez peut-être étendre vos paramètres CSP pour prendre en charge des fonctionnalités supplémentaires propres à votre application.
Hébergement statique sans nonce par réponse
Si votre environnement d'hébergement ou votre CDN peut remplacer un jeton de substitution dans le HTML mis en cache au niveau de l'edge (par exemple avec SSI, ESI ou une edge function), vous pouvez générer index.html avec un placeholder dans ngCspNonce (comme <app ngCspNonce="__CSP_NONCE__"></app>) et le remplacer par un nonce unique à chaque réponse.
Si vous déployez votre application sur un hébergeur statique qui sert index.html tel quel, sans transformation à l'edge, ne codez pas en dur un nonce statique. Utilisez plutôt l'une des approches suivantes :
Hacher les scripts inline avec autoCsp
Définissez l'option security.autoCsp à true dans la configuration du workspace.
Au moment du build, Angular CLI calcule un hash de chaque script inline de index.html, y compris les scripts ajoutés par l'intégration en ligne du CSS critique et par l'intégrité des sous-ressources.
La CLI remplace les éléments <script src> par un script loader haché et ajoute une balise <meta> au début de <head> :
script-src 'strict-dynamic' 'sha256-...' https: 'unsafe-inline'; object-src 'none'; base-uri 'self';
Comme les hashes ne dépendent que du contenu des scripts, index.html reste valide pour chaque visiteur et peut être mis en cache.
Les navigateurs qui prennent en charge les hashes et 'strict-dynamic' ignorent les sources de repli https: et 'unsafe-inline'.
La politique générée par autoCsp présente les limites suivantes :
- Elle ne couvre que les scripts. Vous devez configurer
style-srcséparément. - Les navigateurs ignorent certaines directives, comme
frame-ancestors,report-urietsandbox, lorsqu'elles apparaissent dans une balise<meta>. Envoyez ces directives dans un en-tête HTTPContent-Security-Policy. - Lorsqu'une page a plusieurs politiques, le navigateur les applique toutes. Si vous envoyez aussi un en-tête CSP, omettez à la fois
script-srcetdefault-srcde cet en-tête afin qu'ils ne bloquent pas les scripts inline hachés. - Vous ne pouvez pas utiliser
autoCspavec le rendu côté serveur (SSR).
Éviter les scripts inline
Angular CLI n'ajoute des scripts inline à index.html que pour l'intégration en ligne du CSS critique et pour l'intégrité des sous-ressources (qui émet une import map transportant les métadonnées d'intégrité des imports dynamiques de modules).
Si vous définissez optimization.styles.inlineCritical à false et laissez subresourceIntegrity désactivé, index.html ne contient aucun script inline. Vous pouvez alors configurer un en-tête Content-Security-Policy avec script-src 'self'.
Note : Désactiver l'intégration en ligne du CSS critique peut ralentir le rendu initial de votre application, et désactiver l'intégrité des sous-ressources supprime les vérifications d'intégrité des scripts.
Configurer les styles pour l'hébergement statique
Angular insère des éléments <style> pour les styles des composants à l'exécution, et l'intégration en ligne du CSS critique ajoute un élément <style> à index.html.
Ni autoCsp ni la désactivation des scripts inline ne couvrent ces styles. Sans nonce par réponse, autorisez-les en ajoutant 'unsafe-inline' à style-src.
Par exemple, si votre build évite les scripts inline, configurez votre hébergeur pour qu'il envoie l'en-tête suivant :
default-src 'self'; style-src 'self' 'unsafe-inline';
Si vous utilisez autoCsp, envoyez style-src 'self' 'unsafe-inline' dans l'en-tête HTTP, sans default-src ni script-src.
Le code de votre application et les libraries tierces peuvent nécessiter des directives supplémentaires dans les deux cas.
Rendre obligatoire l'usage des Trusted Types
Il est recommandé d'utiliser les Trusted Types pour aider à protéger vos applications contre les attaques de cross-site scripting. Les Trusted Types sont une fonctionnalité de la plateforme web qui peut vous aider à prévenir les attaques de cross-site scripting en imposant des pratiques de codage plus sûres. Les Trusted Types peuvent aussi faciliter l'audit du code de l'application.
Trusted Types
Les Trusted Types ne sont peut-être pas encore disponibles dans tous les navigateurs ciblés par votre application. Si votre application compatible Trusted Types s'exécute dans un navigateur qui ne les prend pas en charge, les fonctionnalités de l'application sont préservées. Votre application reste protégée contre le XSS grâce au DomSanitizer d'Angular. Consultez caniuse.com/trusted-types pour connaître la prise en charge actuelle par les navigateurs.
Pour imposer les Trusted Types dans votre application, vous devez configurer le serveur web de votre application pour qu'il émette des en-têtes HTTP avec l'une des politiques Angular suivantes :
| Politiques | Détail |
|---|---|
angular |
Cette politique est utilisée dans du code interne à Angular ayant fait l'objet d'une revue de sécurité, et elle est requise pour qu'Angular fonctionne lorsque les Trusted Types sont imposés. Toutes les valeurs de template inline et tout contenu assaini par Angular sont considérés comme sûrs par cette politique. |
angular#bundler |
Cette politique est utilisée par le bundler d'Angular CLI lors de la création des fichiers de chunks chargés en lazy loading. |
angular#unsafe-bypass |
Cette politique est utilisée par les applications qui utilisent l'une des méthodes du DomSanitizer d'Angular contournant la sécurité, comme bypassSecurityTrustHtml. Toute application qui utilise ces méthodes doit activer cette politique. |
angular#unsafe-jit |
Cette politique est utilisée par le compilateur Just-In-Time (JIT). Vous devez activer cette politique si votre application interagit directement avec le compilateur JIT ou s'exécute en mode JIT à l'aide de platform browser dynamic. |
angular#unsafe-upgrade |
Cette politique est utilisée par le package @angular/upgrade. Vous devez activer cette politique si votre application est une application hybride AngularJS. |
Vous devez configurer les en-têtes HTTP pour les Trusted Types aux emplacements suivants :
- L'infrastructure de production qui sert l'application
- Angular CLI (
ng serve), à l'aide de la propriétéheadersdu fichierangular.json, pour le développement local et les tests de bout en bout - Karma (
ng test), à l'aide de la propriétécustomHeadersdu fichierkarma.config.js, pour les tests unitaires
Voici un exemple d'en-tête configuré spécifiquement pour les Trusted Types et Angular :
Content-Security-Policy: trusted-types angular; require-trusted-types-for 'script';
Un exemple d'en-tête configuré spécifiquement pour les Trusted Types et les applications Angular qui utilisent l'une des méthodes du DomSanitizer d'Angular contournant la sécurité :
Content-Security-Policy: trusted-types angular angular#unsafe-bypass; require-trusted-types-for
'script';
Voici un exemple d'en-tête configuré spécifiquement pour les Trusted Types et les applications Angular utilisant le JIT :
Content-Security-Policy: trusted-types angular angular#unsafe-jit; require-trusted-types-for
'script';
Voici un exemple d'en-tête configuré spécifiquement pour les Trusted Types et les applications Angular qui chargent des modules en lazy loading :
Content-Security-Policy: trusted-types angular angular#bundler; require-trusted-types-for 'script';
Contributions de la communauté
Pour en savoir plus sur le dépannage des configurations Trusted Types, la ressource suivante peut être utile :
Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types
Utiliser le compilateur de templates AOT
Le compilateur de templates AOT empêche toute une catégorie de vulnérabilités appelées injections de template, et améliore grandement les performances de l'application. Le compilateur de templates AOT est le compilateur utilisé par défaut par les applications Angular CLI, et vous devez l'utiliser dans tous vos déploiements de production.
Une alternative au compilateur AOT est le compilateur JIT, qui compile les templates en code de template exécutable dans le navigateur, à l'exécution. Angular fait confiance au code des templates : générer dynamiquement des templates et les compiler, en particulier des templates contenant des données utilisateur, contourne donc les protections intégrées d'Angular. C'est un anti-pattern de sécurité. Pour savoir comment construire dynamiquement des formulaires de manière sûre, consultez le guide Formulaires dynamiques.
Protection XSS côté serveur
Le HTML construit sur le serveur est vulnérable aux attaques par injection. Injecter du code de template dans une application Angular revient à injecter du code exécutable dans l'application : cela donne à l'attaquant le contrôle total de l'application. Pour l'éviter, utilisez sur le serveur un langage de templating qui échappe automatiquement les valeurs afin de prévenir les vulnérabilités XSS. Ne créez pas de templates Angular côté serveur à l'aide d'un langage de templating. Cela comporte un risque élevé d'introduire des vulnérabilités d'injection de template.
Vulnérabilités au niveau HTTP
Angular intègre une prise en charge permettant d'aider à prévenir deux vulnérabilités HTTP courantes : la falsification de requête intersites (CSRF ou XSRF) et l'inclusion de script intersites (XSSI). Ces deux vulnérabilités doivent être traitées principalement côté serveur, mais Angular fournit des utilitaires qui facilitent l'intégration côté client.
Falsification de requête intersites
Dans une falsification de requête intersites (CSRF ou XSRF), un attaquant incite l'utilisateur à visiter une autre page web (comme evil.com) contenant du code malveillant. Cette page web envoie secrètement une requête malveillante au serveur web de l'application (comme example-bank.com).
Supposons que l'utilisateur soit connecté à l'application sur example-bank.com.
L'utilisateur ouvre un e-mail et clique sur un lien vers evil.com, qui s'ouvre dans un nouvel onglet.
La page evil.com envoie immédiatement une requête malveillante à example-bank.com.
Il s'agit peut-être d'une requête de virement depuis le compte de l'utilisateur vers celui de l'attaquant.
Le navigateur envoie automatiquement avec cette requête les cookies de example-bank.com, y compris le cookie d'authentification.
Si le serveur de example-bank.com ne dispose pas de protection XSRF, il ne peut pas distinguer une requête légitime provenant de l'application de la requête falsifiée provenant de evil.com.
Pour l'éviter, l'application doit s'assurer qu'une requête utilisateur provient bien de la véritable application, et non d'un autre site. Le serveur et le client doivent coopérer pour déjouer cette attaque.
Dans une technique anti-XSRF courante, le serveur de l'application envoie un jeton d'authentification créé aléatoirement dans un cookie. Le code client lit le cookie et ajoute un en-tête de requête personnalisé contenant le jeton à toutes les requêtes suivantes. Le serveur compare la valeur du cookie reçu à celle de l'en-tête de requête et rejette la requête si les valeurs sont absentes ou ne correspondent pas.
Cette technique est efficace parce que tous les navigateurs implémentent la same-origin policy (politique de même origine).
Seul le code du site web sur lequel les cookies sont définis peut lire les cookies de ce site et définir des en-têtes personnalisés sur les requêtes envoyées à ce site.
Cela signifie que seule votre application peut lire ce jeton de cookie et définir l'en-tête personnalisé.
Le code malveillant de evil.com ne le peut pas.
Sécurité XSRF/CSRF de HttpClient
HttpClient prend en charge un mécanisme courant utilisé pour prévenir les attaques XSRF. Lors de l'exécution de requêtes HTTP, un intercepteur lit un jeton depuis un cookie, par défaut XSRF-TOKEN, et le définit comme en-tête HTTP, X-XSRF-TOKEN. Comme seul le code qui s'exécute sur votre domaine peut lire le cookie, le backend peut être certain que la requête HTTP provient de votre application cliente et non d'un attaquant.
Par défaut, un intercepteur envoie cet en-tête sur toutes les requêtes modifiantes (comme POST) vers des URL relatives et de même origine, mais pas sur les requêtes GET ou HEAD.
Pourquoi ne pas protéger les requêtes GET ?
La protection CSRF n'est nécessaire que pour les requêtes susceptibles de modifier l'état du backend. Par nature, les attaques CSRF franchissent les frontières de domaine, et la same-origin policy du web empêche une page malveillante de récupérer les résultats de requêtes GET authentifiées.
Pour en tirer parti, votre serveur doit définir un jeton dans un cookie de session lisible par JavaScript, appelé XSRF-TOKEN, soit au chargement de la page, soit lors de la première requête GET. Lors des requêtes suivantes, le serveur peut vérifier que le cookie correspond à l'en-tête HTTP X-XSRF-TOKEN, et donc être sûr que seul du code s'exécutant sur votre domaine a pu envoyer la requête. Le jeton doit être unique pour chaque utilisateur et vérifiable par le serveur ; cela empêche le client de fabriquer ses propres jetons. Pour plus de sécurité, définissez le jeton comme un condensé du cookie d'authentification de votre site, avec un sel.
Pour éviter les collisions dans les environnements où plusieurs applications Angular partagent le même domaine ou sous-domaine, donnez à chaque application un nom de cookie unique.
HttpClient ne prend en charge que la partie client du mécanisme de protection XSRF
Votre service backend doit être configuré pour définir le cookie de votre page et pour vérifier que l'en-tête est présent sur toutes les requêtes concernées. Sans cela, la protection par défaut d'Angular est inefficace.
Configurer des noms de cookie et d'en-tête personnalisés
Si votre service backend utilise des noms différents pour le cookie ou l'en-tête du jeton XSRF, utilisez withXsrfConfiguration pour remplacer les valeurs par défaut.
Ajoutez-le à l'appel provideHttpClient comme suit :
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withXsrfConfiguration({
cookieName: 'CUSTOM_XSRF_TOKEN',
headerName: 'X-Custom-Xsrf-Header',
}),
),
],
};
Désactiver la protection XSRF
Si le mécanisme de protection XSRF intégré ne fonctionne pas pour votre application, vous pouvez le désactiver avec la fonctionnalité withNoXsrfProtection :
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient(withNoXsrfProtection())],
};
Pour plus d'informations sur la CSRF selon l'Open Web Application Security Project (OWASP), consultez Cross-Site Request Forgery (CSRF) et Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet. L'article de l'université Stanford Robust Defenses for Cross-Site Request Forgery est une source riche en détails.
Voir aussi la conférence de Dave Smith sur le XSRF à AngularConnect 2016.
Inclusion de script intersites (XSSI)
L'inclusion de script intersites, également appelée vulnérabilité JSON, peut permettre au site web d'un attaquant de lire les données d'une API JSON.
L'attaque fonctionne sur les anciens navigateurs en remplaçant les constructeurs d'objets JavaScript intégrés, puis en incluant une URL d'API à l'aide d'une balise <script>.
Cette attaque ne réussit que si le JSON renvoyé est exécutable en tant que JavaScript.
Les serveurs peuvent prévenir une attaque en préfixant toutes les réponses JSON pour les rendre non exécutables, par convention avec la chaîne bien connue ")]}',\n".
La library HttpClient d'Angular reconnaît cette convention et supprime automatiquement la chaîne ")]}',\n" de toutes les réponses avant de poursuivre l'analyse.
Pour plus d'informations, consultez la section XSSI de cet article du blog Google sur la sécurité web.
Prévenir la falsification de requête côté serveur (SSRF)
Angular inclut une validation stricte des en-têtes Host, Forwarded, X-Forwarded-Host, X-Forwarded-Proto, X-Forwarded-Prefix et X-Forwarded-Port dans le pipeline de traitement des requêtes, afin de prévenir la falsification de requête côté serveur (SSRF) basée sur les en-têtes.
Les règles de validation sont les suivantes :
Host,X-Forwarded-Hostet le paramètrehostde l'en-têteForwardedsont validés par rapport à une liste d'autorisation stricte et ne peuvent pas contenir de séparateurs de chemin.- L'en-tête
X-Forwarded-Portdoit être numérique. - L'en-tête
X-Forwarded-Protoet le paramètreprotode l'en-têteForwardeddoivent valoirhttpouhttps. - L'en-tête
X-Forwarded-Prefixdoit commencer par/et ne contenir que des caractères alphanumériques, des tirets et des underscores, séparés par des barres obliques simples. - Par défaut, l'en-tête
Forwardedet tous les en-têtesX-Forwarded-*sont considérés comme non fiables et sont supprimés de la requête. Pour les conserver, ils doivent être explicitement autorisés via la configuration detrustProxyHeaders.
Les en-têtes invalides déclenchent un log d'erreur, et les en-têtes de proxy non autorisés sont supprimés de la requête. Les requêtes avec des noms d'hôte non reconnus aboutissent à une réponse 400 Bad Request.
Note : La plupart des fournisseurs cloud et des fournisseurs de CDN effectuent automatiquement la validation de ces en-têtes avant même qu'une requête n'atteigne l'origine de l'application. Ce filtrage inhérent réduit considérablement la surface d'attaque en pratique.
Configurer les hôtes autorisés
Pour autoriser des noms d'hôte spécifiques, vous devez les ajouter à la liste d'autorisation. C'est essentiel pour garantir que votre application fonctionne correctement et de manière sûre une fois déployée. Les motifs prennent en charge les wildcards pour une correspondance flexible des noms d'hôte.
Vous pouvez configurer l'option allowedHosts dans votre angular.json :
{
// ...
"projects": {
"your-project-name": {
// ...
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"security": {
"allowedHosts": [
"example.com",
"*.example.com" // allows all subdomains of example.com
]
}
// ... other options
}
}
}
}
}
}
Vous pouvez aussi configurer allowedHosts lors de l'initialisation du moteur de l'application :
const appEngine = new AngularAppEngine({
allowedHosts: ['example.com', '*.trusted-example.com'],
});
const nodeAppEngine = new AngularNodeAppEngine({
allowedHosts: ['example.com', '*.trusted-example.com'],
});
Pour la variante Node.js AngularNodeAppEngine, vous pouvez aussi fournir la variable d'environnement NG_ALLOWED_HOSTS (liste séparée par des virgules) pour autoriser des hôtes.
export NG_ALLOWED_HOSTS="example.com,*.trusted-example.com"
Important : Vous pouvez utiliser * comme valeur dans allowedHosts pour autoriser tous les noms d'hôte, mais c'est généralement déconseillé et cela présente un risque de sécurité. Accepter n'importe quel en-tête host peut exposer votre application à des attaques par injection d'en-tête host et à des attaques de falsification de requête côté serveur (SSRF). Cette configuration ne doit être utilisée que lorsque la validation des en-têtes Host et X-Forwarded-Host est effectuée dans une autre couche, comme un load balancer ou un reverse proxy. Pour une meilleure sécurité, nous recommandons d'utiliser une liste explicite d'hôtes autorisés chaque fois que possible. Consultez GHSA-x288-3778-4hhx pour plus de détails.
Configurer les en-têtes de proxy de confiance
Par défaut, Angular ignore l'en-tête standard Forwarded et tous les en-têtes X-Forwarded-*. Si votre application se trouve derrière un reverse proxy de confiance (comme un load balancer) qui définit ces en-têtes, vous pouvez configurer Angular pour qu'il leur fasse confiance.
Si l'en-tête Forwarded est de confiance, ses paramètres host et proto sont extraits et prennent le pas sur les en-têtes x-forwarded-host et x-forwarded-proto correspondants.
Vous pouvez configurer trustProxyHeaders lors de l'initialisation du moteur de l'application :
const appEngine = new AngularAppEngine({
trustProxyHeaders: ['forwarded'], // Trust the standard Forwarded header
});
const appEngine = new AngularAppEngine({
trustProxyHeaders: ['x-forwarded-host', 'x-forwarded-proto'], // Trust non-standard headers
});
const nodeAppEngine = new AngularNodeAppEngine({
trustProxyHeaders: true, // Trust standard Forwarded and all X-Forwarded-* headers
});
Pour la variante Node.js AngularNodeAppEngine, vous pouvez aussi fournir la variable d'environnement NG_TRUST_PROXY_HEADERS (avec comme valeur une liste d'en-têtes séparés par des virgules) pour autoriser l'utilisation de ces en-têtes.
export NG_TRUST_PROXY_HEADERS="X-FORWARDED-HOST,X-FORWARDED-PREFIX"
Important : N'activez trustProxyHeaders que si votre application se trouve derrière un proxy de confiance qui valide strictement ou remplace ces en-têtes. Sinon, des attaquants peuvent usurper ces en-têtes pour provoquer des attaques de falsification de requête côté serveur (SSRF).
Auditer les applications Angular
Les applications Angular doivent suivre les mêmes principes de sécurité que les applications web classiques, et doivent être auditées comme telles. Les API propres à Angular qui doivent être auditées lors d'une revue de sécurité, comme les méthodes bypassSecurityTrust, sont signalées dans la documentation comme sensibles du point de vue de la sécurité.