Angular 7 DOM消毒混合内容

时间:2018-12-06 15:37:14

标签: angular iframe xss sanitization

我需要提供诸如codepen.io之类的私人服务。用户必须能够创建包含脚本,样式,内联脚本和内联样式的混合内容(是的,具有很多漏洞的XSS不安全内容)。

Service screenshot

我的服务具有iframe和monaco代码编辑器。 如何在没有Angular XSS防御和消毒的情况下将用户生成的html,样式和脚本插入iframe?

我该如何使用Angular 7?

可能存在将用户生成的内容手动标记为已清理内容的方法吗?

重要的代码段。

view.component.html

<iframe id="view" [srcdoc]="resultPage | safe: 'html'"></iframe>

view.component.ts

@Component({
  selector: 'app-view',
  templateUrl: './view.component.html',
  styleUrls: ['./view.component.scss']
})
export class ViewComponent implements OnInit {

  resultPage = '';

  _task: Task;
  set task(value: Task) {
    this._task = value;
    if (value) {
      this.refreshPage();
    }
  }
  get task() {
    return this._task;
  }

  constructor(private store: Store<RootStoreState.State>) { }

  ngOnInit() {
    this.store.pipe(select(selectSelectedTask))
      .subscribe((task) => {
        this.task = task;
      });
  }

  refreshPage() {
    if (!this.task) {return; }
    const htmlFile = this.task.files.find((item) => item.language === 'html')
    const cssFile = this.task.files.find((item) => item.language === 'css')
    const jsFile = this.task.files.find((item) => item.language === 'js')
    let html = htmlFile ? htmlFile.content : null;
    if (!html) {
      return;
    }
    let css = cssFile ? cssFile.content : null;
    let js = jsFile ? jsFile.content : null;
    html = this.insertCss(html, css);
    this.resultPage = html;
  }

  insertCss(html: string, css: string): string {
    const cssPlaceholder = `<style>${css}</style>`;
    const closedHead = html.indexOf('</head>');
    if (closedHead > -1) {
      html.replace('</head>', cssPlaceholder + '</head>');
      console.log(1, html);
      return html;
    }
    const openedBody = html.indexOf('<body>');
    if (openedBody > -1) {
      html.replace('<body>', '<body>' + cssPlaceholder);
      console.log(2, html);
      return html;
    }
    html += css;
    console.log(3, html);
    return html;
  }

}

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。我发现了以下解决方法。

我没有使用angular提供的srcdoc directive,而是创建了一个自定义指令来将srcdoc attribute的{​​{1}}设置为

这是代码

srcdoc.directive.ts

iframe element

按如下所示使用它作为组件html

import { Directive, Input, ElementRef, Renderer2, OnChanges, SimpleChanges } from "@angular/core";

@Directive({
  selector : '[app-srcdoc]'
})
export class SrcdocDirective implements OnChanges{
  // add data binding to directive itself
  @Input("app-srcdoc") source:string;
 
  constructor(private elementRef:ElementRef,private renderer:Renderer2) {}

  // update the srcdoc attribute whenever the binding changes
  ngOnChanges(changes: SimpleChanges): void {
    this.renderer.setAttribute(this.elementRef.nativeElement,"srcdoc",changes.source.currentValue);
  }

}

答案 1 :(得分:0)

尝试使用DomSanitizer

  

调用任何bypassSecurityTrust ... API会禁用Angular内置的传入值清除