Serwis, który dba o to aby nasza aplikacja była odporna na ataki XSS usuwając niebezpieczny kod (ang. sanitizing).
Pisząc aplikację w Angularze często korzystamy z dynamicznego podstawiania wartości w takich miejscach jak link lub wykorzystując atrybut innerHtml. Miejsca te mogą być potencjalnymi miejsca ataku. DomSanitizer pomaga nam w utrzymaniu bezpiecznej aplikacji.

Atak XSS
Na początku wyjaśnijmy sobie czym jest atak XSS (skrót od ang. Cross-site scripting). Polega na przesłaniu do aplikacji złośliwego kodu (najczęściej Javascript), który wykona się po w przeglądarce innego użytkownika. Atakujący może to zrobić za pomocą przesłania odpowiednio przygotowanego komentarza, którego próba odczytu w przeglądarce innego użytkownika może spowodować szkody.
Jak działa DomSanitizer
Wyobraźmy sobie sytuację, w której dajemy użytkownikowi możliwość umieszczania linków do swojego portfolio lub profili w social media. Link może być odpowiednio przygotowany tak aby wykonywał kod Javascript, który wykona się po stronie tego kto kliknie w link. Aby temu zapobiec Angular podczas umieszczania dynamicznych wartości w [href] doda frazę unsafe przy niebezpiecznym kodzie Javascript. Po kliknięciu w link nie zostanie uruchomiony żaden kod Javascript.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
public link = `javascript:alert('test')`;
}
<a [href]="link">Link</a>
Wynikowym kodem, który ukaże się w przeglądarce jest:
<a href="unsafe:javascript:alert('test')">Link</a>
Możemy ten proces wywołać sami wywołując metodę sanitize z serwisu DomSanitizer.
import { Component, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<a [href]="link">Link</a>`,
})
export class AppComponent {
public link: string;
constructor(private sanitizer: DomSanitizer) {
this.link = this.sanitizer.sanitize(SecurityContext.URL, 'javascript:alert(1)');
}
}
Zaufany kod
Są sytuacje, w których chcemy użyć potencjalnie niebezpiecznego kodu w naszej aplikacji. Żeby to zrobić możemy skorzystać z serwisu DomSanitizer.
import { DomSanitizer } from '@angular/platform-browser';
constructor(private sanitizer: DomSanitizer) {
}
Serwis dostarcza kilku funkcji dla różnych kontekstów wywołań niebezpiecznego kodu.
Oznacz HTML jako bezpieczny
Użyj DomSanitizer.bypassSecurityTrustHtml, aby oznaczyć HTML jako bezpieczny do użycia.
import { Component } from '@angular/core';
import { DomSanitizer, SafeValue } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<div [innerHTML]="html"></div>`
})
export class AppComponent {
public html: SafeValue;
constructor(private sanitizer: DomSanitizer) {
this.html = this.sanitizer.bypassSecurityTrustHtml(`<svg width="100" height="100"><circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /></svg>`);
}
}
Oznacz styl jako bezpieczny
Użyj DomSanitizer.bypassSecurityTrustStyle, aby oznaczyć styl jako bezpieczny do użycia.
import { Component } from '@angular/core';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<div [style]="style"></div>`,
})
export class AppComponent {
public style: SafeStyle;
constructor(private sanitizer: DomSanitizer) {
this.style = this.sanitizer.bypassSecurityTrustStyle('color: white; display: block;');
}
}
Oznacz kod Javascript jako bezpieczny
Użyj DomSanitizer.bypassSecurityTrustScript, aby oznaczyć kod Javascript jako bezpieczny do użycia.
import { Component } from '@angular/core';
import { DomSanitizer, SafeScript } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: ``,
})
export class AppComponent {
public script: SafeScript;
constructor(private sanitizer: DomSanitizer) {
this.script = this.sanitizer.bypassSecurityTrustScript('alert(1)');
}
}
Oznacz URL jako bezpieczny
Użyj DomSanitizer.bypassSecurityTrustUrl, aby oznaczyć url jako bezpieczny do użycia.
import { Component } from '@angular/core';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<a [href]="url">Safe url</a>`,
})
export class AppComponent {
public url: SafeUrl;
constructor(private sanitizer: DomSanitizer) {
this.url = this.sanitizer.bypassSecurityTrustUrl("https://www.youtube.com/embed/dQw4w9WgXcQ");
}
}
Oznacz źródło jako bezpieczne
Użyj DomSanitizer.bypassSecurityTrustResourceUrl, aby oznaczyć url, który będzie źródłem np. dla iframe jako bezpieczny do użycia.
import { Component } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Component({
selector: 'app-root',
template: `<iframe [src]="iframe"></iframe>`,
})
export class AppComponent {
public iframe: SafeResourceUrl;
constructor(private sanitizer: DomSanitizer) {
this.iframe = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.youtube.com/embed/dQw4w9WgXcQ");
}
}
Podsumowanie
Nawet w większej aplikacji użycie serwisu DomSanitizer jest rzadkie, ponieważ większość operacji zwiększających bezpieczeństwo naszej aplikacji jest robione przez Angulara w tle. Częściej użyjemy go w przypadku chęci ominięcia tych operacji – używając metod z przedrostkiem bypass.
Oznaczajmy kod jako bezpieczny z rozwagą, a w momentach w których nie jesteśmy pewni treści używajmy metody sanitize aby możliwie jak najlepiej zabezpieczyć naszą aplikację.