# Angular ## La Checklist Checklist [à partir d'ici](https://lsgeurope.com/post/angular-security-checklist). * [ ] Angular est considéré comme un framework côté client et n'est pas censé fournir une protection côté serveur * [ ] Le sourcemap pour les scripts est désactivé dans la configuration du projet * [ ] Les entrées utilisateur non fiables sont toujours interpolées ou nettoyées avant d'être utilisées dans les modèles * [ ] L'utilisateur n'a aucun contrôle sur les modèles côté serveur ou côté client * [ ] Les entrées utilisateur non fiables sont nettoyées en utilisant un contexte de sécurité approprié avant d'être considérées comme fiables par l'application * [ ] Les méthodes `BypassSecurity*` ne sont pas utilisées avec des entrées non fiables * [ ] Les entrées utilisateur non fiables ne sont pas transmises aux classes Angular telles que `ElementRef`, `Renderer2` et `Document`, ou à d'autres points d'injection JQuery/DOM ## Qu'est-ce que Angular Angular est un framework **puissant** et **open-source** maintenu par **Google**. Il utilise **TypeScript** pour améliorer la lisibilité du code et le débogage. Avec des mécanismes de sécurité solides, Angular prévient les vulnérabilités côté client courantes telles que les **XSS** et les **redirections ouvertes**. Il peut également être utilisé côté serveur, ce qui rend les considérations de sécurité importantes des **deux côtés**. ## Architecture du framework Pour mieux comprendre les bases d'Angular, passons en revue ses concepts essentiels. Un projet Angular commun ressemble généralement à : ```bash my-workspace/ ├── ... #workspace-wide configuration files ├── src │ ├── app │ │ ├── app.module.ts #defines the root module, that tells Angular how to assemble the application │ │ ├── app.component.ts #defines the logic for the application's root component │ │ ├── app.component.html #defines the HTML template associated with the root component │ │ ├── app.component.css #defines the base CSS stylesheet for the root component │ │ ├── app.component.spec.ts #defines a unit test for the root component │ │ └── app-routing.module.ts #provides routing capability for the application │ ├── lib │ │ └── src #library-specific configuration files │ ├── index.html #main HTML page, where the component will be rendered in │ └── ... #application-specific configuration files ├── angular.json #provides workspace-wide and project-specific configuration defaults └── tsconfig.json #provides the base TypeScript configuration for projects in the workspace ``` Selon la documentation, chaque application Angular a au moins un composant, le composant racine (`AppComponent`) qui connecte une hiérarchie de composants avec le DOM. Chaque composant définit une classe qui contient les données et la logique de l'application, et est associé à un modèle HTML qui définit une vue à afficher dans un environnement cible. Le décorateur `@Component()` identifie la classe immédiatement en dessous comme un composant, et fournit le modèle et les métadonnées spécifiques au composant. L'`AppComponent` est défini dans le fichier `app.component.ts`. Les NgModules Angular déclarent un contexte de compilation pour un ensemble de composants dédié à un domaine d'application, un flux de travail, ou un ensemble de capacités étroitement liées. Chaque application Angular a un module racine, conventionnellement nommé `AppModule`, qui fournit le mécanisme de démarrage qui lance l'application. Une application contient généralement de nombreux modules fonctionnels. L'`AppModule` est défini dans le fichier `app.module.ts`. Le NgModule `Router` Angular fournit un service qui vous permet de définir un chemin de navigation parmi les différents états d'application et hiérarchies de vues dans votre application. Le `RouterModule` est défini dans le fichier `app-routing.module.ts`. Pour les données ou la logique qui ne sont pas associées à une vue spécifique, et que vous souhaitez partager entre les composants, vous créez une classe de service. La définition de la classe de service est immédiatement précédée du décorateur `@Injectable()`. Le décorateur fournit les métadonnées qui permettent à d'autres fournisseurs d'être injectés en tant que dépendances dans votre classe. L'injection de dépendances (DI) vous permet de maintenir vos classes de composants légères et efficaces. Elles ne récupèrent pas de données depuis le serveur, ne valident pas les saisies utilisateur, ou ne journalisent pas directement dans la console ; elles délèguent de telles tâches aux services. ## Configuration des sourcemap Le framework Angular traduit les fichiers TypeScript en code JavaScript en suivant les options du fichier `tsconfig.json`, puis construit un projet avec la configuration `angular.json`. En examinant le fichier `angular.json`, nous avons observé une option pour activer ou désactiver un sourcemap. Selon la documentation Angular, la configuration par défaut a un fichier sourcemap activé pour les scripts et n'est pas masqué par défaut: ```json "sourceMap": { "scripts": true, "styles": true, "vendor": false, "hidden": false } ``` Généralement, les fichiers sourcemap sont utilisés à des fins de débogage car ils cartographient les fichiers générés à leurs fichiers d'origine. Par conséquent, il n'est pas recommandé de les utiliser en environnement de production. Lorsque les sourcemaps sont activés, cela améliore la lisibilité et facilite l'analyse des fichiers en reproduisant l'état d'origine du projet Angular. Cependant, s'ils sont désactivés, un examinateur peut toujours analyser manuellement un fichier JavaScript compilé en recherchant des modèles anti-sécurité. De plus, un fichier JavaScript compilé avec un projet Angular peut être trouvé dans les outils de développement du navigateur → Sources (ou Debugger et Sources) → \[id].main.js. Selon les options activées, ce fichier peut contenir la ligne suivante à la fin `//# sourceMappingURL=[id].main.js.map` ou non, si l'option **hidden** est définie sur **true**. Cependant, si le sourcemap est désactivé pour les **scripts**, les tests deviennent plus complexes et nous ne pouvons pas obtenir le fichier. De plus, le sourcemap peut être activé pendant la construction du projet comme `ng build --source-map`. ## Liaison de données La liaison fait référence au processus de communication entre un composant et sa vue correspondante. Elle est utilisée pour transférer des données vers et depuis le framework Angular. Les données peuvent être transmises de diverses manières, telles que par des événements, interpolation, propriétés, ou par le mécanisme de liaison bidirectionnelle. De plus, les données peuvent également être partagées entre des composants liés (relation parent-enfant) et entre deux composants non liés en utilisant la fonctionnalité Service. Nous pouvons classer la liaison par flux de données : * Source de données vers cible de vue (inclut _interpolation_, _propriétés_, _attributs_, _classes_ et _styles_); peut être appliqué en utilisant `[]` ou `{{}}` dans le modèle; * Cible de vue vers source de données (inclut _événements_); peut être appliqué en utilisant `()` dans le modèle; * Bidirectionnelle; peut être appliqué en utilisant `[()]` dans le modèle. La liaison peut être appelée sur des propriétés, des événements, des attributs, ainsi que sur tout membre public d'une directive source : | TYPE | CIBLE | EXEMPLES | | --------- | -------------------------------------------------------- | -------------------------------------------------------------------- | | Propriété | Propriété de l'élément, Propriété du composant, Propriété de la directive | \ | | Événement | Événement de l'élément, Événement du composant, Événement de la directive | \ ``` * Pour définir la propriété d'un élément DOM, vous pouvez utiliser la méthode `Renderer2.setProperty()` et déclencher une attaque XSS : ```tsx //app.component.ts import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { public constructor ( private renderer2: Renderer2 ){} @ViewChild("img") img!: ElementRef; setProperty(){ this.renderer2.setProperty(this.img.nativeElement, 'innerHTML', ''); } } //app.component.html ``` Au cours de nos recherches, nous avons également examiné le comportement d'autres méthodes `Renderer2`, telles que `setStyle()`, `createComment()` et `setValue()`, par rapport aux injections XSS et CSS. Cependant, nous n'avons pas pu trouver de vecteurs d'attaque valides pour ces méthodes en raison de leurs limitations fonctionnelles. #### jQuery jQuery est une bibliothèque JavaScript rapide, petite et riche en fonctionnalités qui peut être utilisée dans le projet Angular pour aider à manipuler les objets DOM HTML. Cependant, comme on le sait, les méthodes de cette bibliothèque peuvent être exploitées pour provoquer une vulnérabilité XSS. Afin de discuter de la manière dont certaines méthodes jQuery vulnérables peuvent être exploitées dans les projets Angular, nous avons ajouté cette sous-section. * La méthode `html()` récupère le contenu HTML du premier élément dans l'ensemble des éléments correspondants ou définit le contenu HTML de chaque élément correspondant. Cependant, par conception, tout constructeur ou méthode jQuery qui accepte une chaîne HTML peut potentiellement exécuter du code. Cela peut se produire par l'injection de balises `"); }); } } //app.component.html

some text here

``` * La méthode `jQuery.parseHTML()` utilise des méthodes natives pour convertir la chaîne en un ensemble de nœuds DOM, qui peuvent ensuite être insérés dans le document. ```tsx jQuery.parseHTML(data [, context ] [, keepScripts ]) ``` Comme mentionné précédemment, la plupart des API jQuery qui acceptent des chaînes HTML exécuteront des scripts inclus dans le HTML. La méthode `jQuery.parseHTML()` ne lance pas de scripts dans le HTML analysé à moins que `keepScripts` ne soit explicitement défini sur `true`. Cependant, il est toujours possible dans la plupart des environnements d'exécuter des scripts de manière indirecte ; par exemple, via l'attribut ``. ```tsx //app.component.ts import { Component, OnInit } from '@angular/core'; import * as $ from 'jquery'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { ngOnInit() { $("button").on("click", function() { var $palias = $("#palias"), str = "", html = $.parseHTML(str), nodeNames = []; $palias.append(html); }); } } //app.component.html

some text

```