Hướng dẫn angular innerhtml security - bảo mật bên trong html góc cạnh

Hướng dẫn angular innerhtml security - bảo mật bên trong html góc cạnh

Trong bài viết này, tôi sẽ giới thiệu cho các bạn những tính năng bảo vệ được tích hợp trong Angular nhằm chống lại những lỗ hổng bảo mật và những cuộc tấn công phổ biến trên các ứng dụng web ví dụ như Cross-site scripting attacks (XSS). Nó không bao gồm bảo mật ở tầng ứng dụng, ví dụ như authentication (người dùng này là ai) và authorization (người dùng này có thể làm những gì).

Ngăn chặn cross-site scripting (XSS)

Nhắc lại một chút kiến thức cho các bạn nhớ, Cross-site scripting (XSS) là một trong những loại lỗ hổng bảo mật máy tính phổ biến nhất trong các ứng dụng web. XSS cho phép những kẻ tấn công inject các mã code độc vào trang web của bạn. Những mã code đó có thể ăn cắp dữ liệu của người dùng (cụ thể như dữ liệu đăng nhập) hoặc thực hiện những hành động giả mạo người dụng.

Hướng dẫn angular innerhtml security - bảo mật bên trong html góc cạnh

Để chặn những tấn công XSS này, bạn phải ngăn chặn những mã code độc hại khỏi sự xâm nhập vào DOM (Document Object Model). Ví dụ, nếu những kẻ tấn công có thể đánh lừa bạn chèn một thẻ tag Syntax'; } 1 và

export class InnerHtmlBindingComponent {
  // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
  htmlSnippet = 'Template  Syntax';
}
2. Nếu dữ liệu được kiểm soát bởi những kẻ tấn công vào DOM, một lỗ hổng bảo mật đã được hình thành.

Mô hình bảo mật XSS của Angular

Để chặn những tấn công XSS một cách có hệ thống, Angular mặc định sẽ xử lý tất cả những giá trị không đáng tin cậy. Khi một giá trị được chèn vào DOM từ một template, thông qua các property, attribute, style, class binding hay interpolation, Angular sẽ sanitizes(khử độc) và escape những giá trị không đáng tin cậy.

Những Angular template giống như những đoạn code có thể thực thi: HTML, attributes, và binding expression (nhưng không phải là các giá trị ràng buộc) trong template là đáng tin cậy và an toàn. Điều này có nghĩa là ứng dụng phải ngăn chặn các giá trị mà một kẻ tấn công có thể điều khiển từ lúc đưa nó vào mã nguồn của một template. Không bao giờ tạo ra mã nguồn template bằng cách nối các user input và template với nhau. Để ngăn chặn những lỗ hổng bảo mật này, sử dụng

export class InnerHtmlBindingComponent {
  // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
  htmlSnippet = 'Template  Syntax';
}
4, hay còn được gọi là
export class InnerHtmlBindingComponent {
  // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
  htmlSnippet = 'Template  Syntax';
}
5.

Sanitization và bối cảnh an ninh

export class InnerHtmlBindingComponent {
  // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
  htmlSnippet = 'Template  Syntax';
}
6 như đã nhắc đến ở trên, là kiểm tra các giá trị không đáng tin cậy, biến nó thành một giá trị an toàn trước khi chèn nó vào DOM. Trong nhiều trường hợp, sanitization không làm thay đổi giá trị nào cả. Sanitization phụ thuộc vào ngữ cảnh: một giá trị vô hại trong CSS có khả năng gây nguy hiểm trong một URL.

Angular định nghĩa những bối cảnh an ninh sau đây:

  • HTML được sử dụng khi thông dịch một giá trị như HTML, ví dụ, khi binding vào
    export class InnerHtmlBindingComponent {
      // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
      htmlSnippet = 'Template  Syntax';
    }
    
    7.
  • Style được sử dụng khi binding CSS vào
    export class InnerHtmlBindingComponent {
      // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
      htmlSnippet = 'Template  Syntax';
    }
    
    8 property.
  • URL được sử dụng cho URL property, ví dụ
    export class InnerHtmlBindingComponent {
      // Ví dụ,  một giá trị bị một kẻ tấn công kiểm soát từ một URL.
      htmlSnippet = 'Template  Syntax';
    }
    
    9.
  • Resource URL là một URL sẽ được tải và thực thi như các đoạn mã, ví dụ, trong

    An untrusted URL:

    Click me

    A trusted URL:

    Click me

    0.

Angular khử độc những giá trị không đáng tin cậy cho HTML, các styles, và các URLs; khử độc những resource URLs là không thể bởi vì chúng chứa những mà code tùy ý. Trong development mode, Angular in ra một console warning khi nó phải thay đổi một giá trị trong quá trình khử độc.

Một số ví dụ về sanitization

Template dưới đây bind giá trị của thuộc tính

An untrusted URL:

Click me

A trusted URL:

Click me

1, một lần bằng cách interpolating nó vào nội dung của element, một lần bằng cách binding nó vào thuộc tính

An untrusted URL:

Click me

A trusted URL:

Click me

2 của element, và ta thu được kết quả như sau:

# src/app/inner-html-binding.component.html

Binding innerHTML

Bound value:

{{htmlSnippet}}

Result of binding to innerHTML:

Những interpolated content sẽ luôn được escape - HTML sẽ không được thông dịch và browser sẽ vẫn hiển thị các

An untrusted URL:

Click me

A trusted URL:

Click me

3 trong nội dung của element.

Để HTML được thông dịch, bind nó vào trong một HTML property như

An untrusted URL:

Click me

A trusted URL:

Click me

2. Tuy nhiên, bind một giá trị mà một kẻ tấn công có thể kiểm soát vào

An untrusted URL:

Click me

A trusted URL:

Click me

2 thường gây ra một lỗ hổng bảo mật XSS. Ví dụ, đoạn code chứa trong thẻ tag Syntax'; }

Angular sẽ nhận biết giá trị không an toàn và tự động khử độc nó, loại bỏ thẻ tag

  • constructor(private sanitizer: DomSanitizer) {
      // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
      // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
      // nói cho Angular rằng bạn tin tưởng chúng:
      this.dangerousUrl = 'javascript:alert("Hi there")';
      this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
    }
    
    5
  • constructor(private sanitizer: DomSanitizer) {
      // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
      // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
      // nói cho Angular rằng bạn tin tưởng chúng:
      this.dangerousUrl = 'javascript:alert("Hi there")';
      this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
    }
    
    6
  • constructor(private sanitizer: DomSanitizer) {
      // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
      // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
      // nói cho Angular rằng bạn tin tưởng chúng:
      this.dangerousUrl = 'javascript:alert("Hi there")';
      this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
    }
    
    7
  • constructor(private sanitizer: DomSanitizer) {
      // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
      // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
      // nói cho Angular rằng bạn tin tưởng chúng:
      this.dangerousUrl = 'javascript:alert("Hi there")';
      this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
    }
    
    8
  • constructor(private sanitizer: DomSanitizer) {
      // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
      // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
      // nói cho Angular rằng bạn tin tưởng chúng:
      this.dangerousUrl = 'javascript:alert("Hi there")';
      this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
    }
    
    9

Hãy nhớ rằng, một giá trị an toàn hay không còn tùy thuộc vào ngữ cảnh, vì vậy hãy chọn một ngữ cảnh phù hợp cho mục đích sử dụng giá trị của bạn. Tưởng tượng rằng template dưới đây cần bind một URL vào một

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

0 như sau:

An untrusted URL:

Click me

A trusted URL:

Click me

Thông thường, Angular sẽ tự động khử độc các URL, vô hiệu hóa những đoạn mã nguy hiểm, và trong development mode, log những hành động này vào console. Để ngăn chặn điều này, đánh dấu giá trị của URL đó như một URL đáng tin cậy bằng cách sử dụng

constructor(private sanitizer: DomSanitizer) {
  // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
  // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
  // nói cho Angular rằng bạn tin tưởng chúng:
  this.dangerousUrl = 'javascript:alert("Hi there")';
  this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
}
8 như sau:

constructor(private sanitizer: DomSanitizer) {
  // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
  // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
  // nói cho Angular rằng bạn tin tưởng chúng:
  this.dangerousUrl = 'javascript:alert("Hi there")';
  this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
}

Hướng dẫn angular innerhtml security - bảo mật bên trong html góc cạnh

Nếu bạn cần convert user input thành các giá trị tin cậy, sử dụng một controller method. Template dưới đây cho phép user nhập một Youtube video ID và load video tương ứng trong một thẻ

constructor(private sanitizer: DomSanitizer) {
  // javascript: URLs sẽ là nguy hiểm nếu như bị kẻ tấn công kiểm soát
  // Angular sẽ khử độc chúng trong data binding, nhưng bạn có thể
  // nói cho Angular rằng bạn tin tưởng chúng:
  this.dangerousUrl = 'javascript:alert("Hi there")';
  this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
}
4. Thuộc tính

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

3 là một resource URL security context, bởi vì một nguồn không đáng tin cậy có thể bất hợp pháp trong file download mà người dùng không nghi ngờ có thể được thực thi. Do vậy, gọi một method trong controller để xây dựng một video URL đáng tin cậy, mà Angular cho phép binding vào

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

3:

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

constructor() {
    this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
    this.videoUrl =
      this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}

Các bạn có thể xem code demo ở link sau đây

Những lỗ hổng bảo mật ở tầng HTTP

Angular đã tích hợp sẵn những công cụ giúp ngăn chặn 2 lỗ hổng bảo mật phổ biến trên HTTP, đó là

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

5 và

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

6. Cả hai trong số đó đều phải được ngăn chặn chủ yếu ở server side, tuy nhiên Angular cung cấp những hỗ trợ giúp cho việc tích hợp nó ở client side một cách dễ dàng hơn.

Cross-site request forgery (CSRF hay XSRF)

Trong một

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

7, kẻ tấn công đánh lừa người dùng vào một trang web khác (ví dụ

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

8) với những mã code độc hại, bí mật gửi những request độc hại đến web server của ứng dụng (ví dụ 1 trang web ngân hàng nào đó

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

9).

Giả sử người dùng đã đăng nhập thành công vào trang web của ngân hàng

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

9. Sau đó người dùng mở 1 email và click vào đường dẫn đến

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

8, mở một tab mới.

Trang web

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

8 ngay lập tức gửi một request độc hại tới

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

9. Có thể đó là một request chuyển tiền từ tài khoản người dùng đến tài khoản của kẻ tấn công. Trình duyệt sẽ tự động gửi những cookies từ

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

9 (bao gồm cookie cho việc xác thực) kèm theo những request đó.
Hướng dẫn angular innerhtml security - bảo mật bên trong html góc cạnh

Nếu như server của

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

9 thiếu những sự bảo vệ từ XSRF, nó sẽ không thể phân biệt được một request hợp pháp từ ừng dụng với một yêu cầu giả mạo từ

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

8.

Để ngăn chặn điều này, ứng dụng phải đảm bảo rằng request của người dùng bắt nguồn từ chính ứng dụng đó chứ không phải từ một trang web khác. Server và client phải hợp tác với nhau để ngăn chặn những tấn công.

Trong những kĩ thuật chống XSRF phổ biến, server của ứng dụng gửi một token xác thực được tạo ngẫu nhiên trong một cookie. Phía client sẽ đọc cookie đó và thêm một custom request header với token đó trong những request sau đó. Server sẽ so sánh giá trị cookie gửi đi với cookie nhận được trong request header và sẽ từ chối những request nếu như nó thiếu cookie hoặc cookie không đúng.

Kĩ thuật này hiệu quả bởi vì tất cả các trình duyệt đều implement same origin policy. Chỉ những trang web mà cookies được thiết lập mới có thể đọc được những cookies đó từ trang web đó và thiết lập một custom header trong request tới trang web đó. Nó có nghĩa là chỉ ứng dụng của bạn mới có thể đọc được những cookie token này và set custom header. Những mã code độc hại trên

Resource URL:

Showing: {{dangerousVideoUrl}}

Trusted:

Untrusted:

8 thì không thể làm điều đó.

Thư viện

constructor() {
    this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
    this.videoUrl =
      this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
8 của Angular đã tích hợp sẵn hỗ trợ cho phía client một nửa của kĩ thuật này. Bạn có thể đọc kĩ hơn ở đây HttpClient.

Cross-site script inclusion (XSSI)

constructor() {
    this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
    this.videoUrl =
      this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
9 được biết đến như một lỗ hổng về JSON, nó có thể cho phép trang web của kẻ tấn công đọc được dữ liệu từ một JSON API. Những cuộc tấn công này được thực hiện trên những trình duyệt cũ hơn bằng cách override native Javascript object constructor, sau đóinclude một API URL sử dụng một thẻ