【荐】Angular如何防御XSS攻击

推荐文章

Dor Moshe
How Angular Protects Us From XSS Attacks?

推荐理由

XSS攻击是比较常见的网站攻击方式,Angular框架也考虑到了这点,专门做了一些处理。本文就Angular如何防御XSS攻击做了简单介绍。

文章概要

P.S. 本文不完全是原文的概要,顺便添加了笔者想表达的点,使得更加完整。

XSS是指用户通过给网站注入恶意代码,导致其他用户操作网站时,受到该代码攻击产生危害的行为。攻击通常是在用户输入内容,style,href,src等标签属性中进行。

Angular中可以插入html片段,绑定style,src,href属性等,这些是XSS攻击的潜在来源:

1
2
3
4
5
6
7
8
9
10
11
// 插入html
<div [innerHTML]=’value’></div>
// 绑定style
<div [style]=’value’></div>
// 绑定href
<a [href]=’value’></a>
// 绑定src
<script [src]=’value’></script>

但是,Angular非常友好,默认情况下启动了XSS攻击的防御。所以,我们不需要担心。

问题是,当我们不需要XSS的时候,如何怎么解除Angular自带的过滤呢?

Angular给我们提供的一个叫DomSanitizer的服务,提供的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export enum SecurityContext { NONE, HTML, STYLE, SCRIPT, URL, RESOURCE_URL }
export abstract class DomSanitizer implements Sanitizer {
// 过滤恶意代码,可设置过滤类型
abstract sanitize(context: SecurityContext, value: SafeValue|string|null): string|null;
// 跳过html的检查
abstract bypassSecurityTrustHtml(value: string): SafeHtml;
// 跳style的检查
abstract bypassSecurityTrustStyle(value: string): SafeStyle;
// 跳过script的检查
abstract bypassSecurityTrustScript(value: string): SafeScript;
// 跳过style的检查
abstract bypassSecurityTrustUrl(value: string): SafeUrl;
// 跳过url的检查
abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl;
}

举个具体的应用例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// html
<h4>An untrusted URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
<h4>A trusted URL:</h4>
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
// js
import { DomSanitizer } from '@angular/platform-browser';
@Component({
...
})
export class DemoComponent {
constructor(private sanitizer: DomSanitizer) {
}
this.dangerousUrl = 'javascript:alert("Hi there")';
// 人为信任该url
this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
}

应用效果如下:

image

另外,可以将该功能做成pipe,方便使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { DomSanitizer } from '@angular/platform-browser';
/**
* 去掉xss保护,默认为安全的html
*/
@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe {
constructor(private sanitizer:DomSanitizer){}
transform(html: string) {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
}

最后,要提醒一句,当你决定解除XSS检查的时候,请谨慎操作。

延伸阅读

Angular安全指南

本文首发知乎野草。如有不当之处,欢迎指正。