docs(security): hide TOC for Dart; other minor copyedits (#3017)
This commit is contained in:
parent
a74f8fb3b1
commit
0dfd37e5a9
@ -1,20 +1,17 @@
|
|||||||
<!--#docregion -->
|
<!--#docregion -->
|
||||||
<h3>Bypass Security Component</h3>
|
<h3>Bypass Security Component</h3>
|
||||||
|
|
||||||
<!--#docregion dangerous-url -->
|
<!--#docregion URL -->
|
||||||
<h4>An untrusted URL:</h4>
|
<h4>An untrusted URL:</h4>
|
||||||
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
|
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
|
||||||
<h4>A trusted URL:</h4>
|
<h4>A trusted URL:</h4>
|
||||||
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
|
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
|
||||||
<!--#enddocregion dangerous-url -->
|
<!--#enddocregion URL -->
|
||||||
|
|
||||||
<!--#docregion iframe-videoid -->
|
<!--#docregion iframe -->
|
||||||
<h4>Resource URL:</h4>
|
<h4>Resource URL:</h4>
|
||||||
<p><label>Showing: <input (input)="updateVideoUrl($event.target.value)"></label></p>
|
<p><label>Showing: <input (input)="updateVideoUrl($event.target.value)"></label></p>
|
||||||
<p>Trusted:</p>
|
<p>Trusted:</p>
|
||||||
<iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl"></iframe>
|
<iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl"></iframe>
|
||||||
<p>Untrusted:</p>
|
<p>Untrusted:</p>
|
||||||
<iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl"></iframe>
|
<iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl"></iframe>
|
||||||
<!--#enddocregion iframe-videoid -->
|
|
||||||
|
|
||||||
<!--#enddocregion -->
|
|
||||||
|
@ -6,7 +6,7 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'inner-html-binding',
|
selector: 'inner-html-binding',
|
||||||
templateUrl: 'inner-html-binding.component.html',
|
templateUrl: 'inner-html-binding.component.html',
|
||||||
})
|
})
|
||||||
// #docregion inner-html-controller
|
// #docregion class
|
||||||
export class InnerHtmlBindingComponent {
|
export class InnerHtmlBindingComponent {
|
||||||
// For example, a user/attacker-controlled value from a URL.
|
// For example, a user/attacker-controlled value from a URL.
|
||||||
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
|
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
|
||||||
|
@ -8,17 +8,19 @@ block includes
|
|||||||
|
|
||||||
For more information about the attacks and mitigations described below, see [OWASP Guide Project](https://www.owasp.org/index.php/Category:OWASP_Guide_Project).
|
For more information about the attacks and mitigations described below, see [OWASP Guide Project](https://www.owasp.org/index.php/Category:OWASP_Guide_Project).
|
||||||
|
|
||||||
.l-main-section
|
+ifDocsFor('ts')
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
# Contents:
|
||||||
|
|
||||||
|
* [Reporting vulnerabilities](#report-issues).
|
||||||
|
* [Best practices](#best-practices).
|
||||||
|
* [Preventing cross-site scripting (XSS)](#xss).
|
||||||
|
* [Trusting safe values](#bypass-security-apis).
|
||||||
|
* [HTTP-Level vulnerabilities](#http).
|
||||||
|
* [Auditing Angular applications](#code-review).
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
# Contents:
|
|
||||||
|
|
||||||
* [Reporting vulnerabilities](#report-issues).
|
|
||||||
* [Best practices](#best-practices).
|
|
||||||
* [Preventing cross-site scripting (XSS)](#xss).
|
|
||||||
* [Trusting safe values](#bypass-security-apis).
|
|
||||||
* [HTTP-Level vulnerabilities](#http).
|
|
||||||
* [Auditing Angular applications](#code-review).
|
|
||||||
|
|
||||||
Try the <live-example></live-example> of the code shown in this page.
|
Try the <live-example></live-example> of the code shown in this page.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
@ -103,15 +105,17 @@ h2#xss Preventing cross-site scripting (XSS)
|
|||||||
a value that an attacker might control into `innerHTML` normally causes an XSS
|
a value that an attacker might control into `innerHTML` normally causes an XSS
|
||||||
vulnerability. For example, code contained in a `<script>` tag is executed:
|
vulnerability. For example, code contained in a `<script>` tag is executed:
|
||||||
|
|
||||||
+makeExcerpt('app/inner-html-binding.component.ts ()', 'inner-html-controller')
|
+makeExcerpt('app/inner-html-binding.component.ts', 'class')
|
||||||
|
|
||||||
:marked
|
block html-sanitization
|
||||||
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the `<script>`
|
:marked
|
||||||
tag but keeps safe content such as the text content of the `<script>` tag, or the `<b>` element.
|
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the `<script>`
|
||||||
|
tag but keeps safe content such as the text content of the `<script>` tag, or the `<b>` element.
|
||||||
|
|
||||||
|
figure.image-display
|
||||||
|
img(src='/resources/images/devguide/security/binding-inner-html.png'
|
||||||
|
alt='A screenshot showing interpolated and bound HTML values')
|
||||||
|
|
||||||
figure.image-display
|
|
||||||
img(src='/resources/images/devguide/security/binding-inner-html.png'
|
|
||||||
alt='A screenshot showing interpolated and bound HTML values')
|
|
||||||
:marked
|
:marked
|
||||||
### Avoid direct use of the DOM APIs
|
### Avoid direct use of the DOM APIs
|
||||||
|
|
||||||
@ -144,136 +148,138 @@ figure.image-display
|
|||||||
the server. Do not generate Angular templates on the server side using a templating language; doing this
|
the server. Do not generate Angular templates on the server side using a templating language; doing this
|
||||||
carries a high risk of introducing template-injection vulnerabilities.
|
carries a high risk of introducing template-injection vulnerabilities.
|
||||||
|
|
||||||
.l-main-section
|
block bypass-security-apis
|
||||||
h2#bypass-security-apis Trusting safe values
|
.l-main-section
|
||||||
:marked
|
h2#bypass-security-apis Trusting safe values
|
||||||
Sometimes applications genuinely need to include executable code, display an `<iframe>` from some
|
:marked
|
||||||
URL, or construct potentially dangerous URLs. To prevent automatic sanitization in any of these
|
Sometimes applications genuinely need to include executable code, display an `<iframe>` from some
|
||||||
situations, you can tell Angular that you inspected a value, checked how it was generated, and made
|
URL, or construct potentially dangerous URLs. To prevent automatic sanitization in any of these
|
||||||
sure it will always be secure. But **be careful**! If you trust a value that might be malicious, you
|
situations, you can tell Angular that you inspected a value, checked how it was generated, and made
|
||||||
are introducing a security vulnerability into your application. If in doubt, find a professional
|
sure it will always be secure. But **be careful**! If you trust a value that might be malicious, you
|
||||||
security reviewer.
|
are introducing a security vulnerability into your application. If in doubt, find a professional
|
||||||
|
security reviewer.
|
||||||
|
|
||||||
You can mark a value as trusted by injecting `DomSanitizer` and calling one of the
|
You can mark a value as trusted by injecting `DomSanitizer` and calling one of the
|
||||||
following methods:
|
following methods:
|
||||||
|
|
||||||
* `bypassSecurityTrustHtml`
|
* `bypassSecurityTrustHtml`
|
||||||
* `bypassSecurityTrustScript`
|
* `bypassSecurityTrustScript`
|
||||||
* `bypassSecurityTrustStyle`
|
* `bypassSecurityTrustStyle`
|
||||||
* `bypassSecurityTrustUrl`
|
* `bypassSecurityTrustUrl`
|
||||||
* `bypassSecurityTrustResourceUrl`
|
* `bypassSecurityTrustResourceUrl`
|
||||||
|
|
||||||
Remember, whether a value is safe depends on context, so you need to choose the right context for
|
Remember, whether a value is safe depends on context, so you need to choose the right context for
|
||||||
your intended use of the value. Imagine that the following template needs to bind a URL to a
|
your intended use of the value. Imagine that the following template needs to bind a URL to a
|
||||||
`javascript:alert(...)` call:
|
`javascript:alert(...)` call:
|
||||||
|
|
||||||
+makeExcerpt('app/bypass-security.component.html ()', 'dangerous-url')
|
+makeExcerpt('app/bypass-security.component.html', 'URL')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Normally, Angular automatically sanitizes the URL, disables the dangerous code, and
|
Normally, Angular automatically sanitizes the URL, disables the dangerous code, and
|
||||||
in development mode, logs this action to the console. To prevent
|
in development mode, logs this action to the console. To prevent
|
||||||
this, you can mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` call:
|
this, you can mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` call:
|
||||||
|
|
||||||
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-url')
|
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-url')
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/security/bypass-security-component.png'
|
img(src='/resources/images/devguide/security/bypass-security-component.png'
|
||||||
alt='A screenshot showing an alert box created from a trusted URL')
|
alt='A screenshot showing an alert box created from a trusted URL')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
If you need to convert user input into a trusted value, use a
|
If you need to convert user input into a trusted value, use a
|
||||||
controller method. The template below allows users to enter a YouTube video ID and load the
|
controller method. The template below allows users to enter a YouTube video ID and load the
|
||||||
corresponding video in an `<iframe>`. The `<iframe src>` attribute is a resource URL security
|
corresponding video in an `<iframe>`. The `<iframe src>` attribute is a resource URL security
|
||||||
context, because an untrusted source can, for example, smuggle in file downloads that unsuspecting users
|
context, because an untrusted source can, for example, smuggle in file downloads that unsuspecting users
|
||||||
could execute. So call a method on the controller to construct a trusted video URL, that causes
|
could execute. So call a method on the controller to construct a trusted video URL, that causes
|
||||||
Angular to then allow binding into `<iframe src>`:
|
Angular to then allow binding into `<iframe src>`:
|
||||||
|
|
||||||
+makeExcerpt('app/bypass-security.component.html ()', 'iframe-videoid')
|
+makeExcerpt('app/bypass-security.component.html', 'iframe')
|
||||||
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-video-url')
|
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-video-url')
|
||||||
|
|
||||||
.l-main-section
|
block http
|
||||||
h2#http HTTP-level vulnerabilities
|
.l-main-section
|
||||||
:marked
|
h2#http HTTP-level vulnerabilities
|
||||||
Angular has built-in support to help prevent two common HTTP vulnerabilities, cross-site request
|
:marked
|
||||||
forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily
|
Angular has built-in support to help prevent two common HTTP vulnerabilities, cross-site request
|
||||||
on the server side, but Angular ships helpers to make integration on the client side easier.
|
forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily
|
||||||
|
on the server side, but Angular ships helpers to make integration on the client side easier.
|
||||||
|
|
||||||
h3#xsrf Cross-site request forgery
|
h3#xsrf Cross-site request forgery
|
||||||
:marked
|
:marked
|
||||||
In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting
|
In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting
|
||||||
a different web page (e.g. `evil.com`) with malignant code that secretly sends a malicious request
|
a different web page (e.g. `evil.com`) with malignant code that secretly sends a malicious request
|
||||||
to your application's web server (e.g. `example-bank.com`).
|
to your application's web server (e.g. `example-bank.com`).
|
||||||
|
|
||||||
Assume the user is logged into the application at `example-bank.com`.
|
Assume the user is logged into the application at `example-bank.com`.
|
||||||
The user opens an email and clicks a link to `evil.com` which opens in a new tab.
|
The user opens an email and clicks a link to `evil.com` which opens in a new tab.
|
||||||
|
|
||||||
The `evil.com` page immediately sends a malicious request to `example-bank.com`.
|
The `evil.com` page immediately sends a malicious request to `example-bank.com`.
|
||||||
Perhaps it's a request to transfer money from the user's account to the attacker's account.
|
Perhaps it's a request to transfer money from the user's account to the attacker's account.
|
||||||
The browser automatically sends the `example-bank.com` cookies (including the authentication cookie) with this request.
|
The browser automatically sends the `example-bank.com` cookies (including the authentication cookie) with this request.
|
||||||
|
|
||||||
The `example-bank.com` server, if it lacks XSRF protection, can't tell the difference between a legitimate request from the application
|
The `example-bank.com` server, if it lacks XSRF protection, can't tell the difference between a legitimate request from the application
|
||||||
and the forged request from `evil.com`.
|
and the forged request from `evil.com`.
|
||||||
|
|
||||||
To prevent this, the application must ensure that a user request originates from the real
|
To prevent this, the application must ensure that a user request originates from the real
|
||||||
application, not from a different site.
|
application, not from a different site.
|
||||||
The server and client must cooperate to thwart this attack.
|
The server and client must cooperate to thwart this attack.
|
||||||
|
|
||||||
In a common anti-XSRF technique, the application server sends a randomly
|
In a common anti-XSRF technique, the application server sends a randomly
|
||||||
generated authentication token in a cookie.
|
generated authentication token in a cookie.
|
||||||
The client code reads the cookie and adds a custom request header with the token in all subsequent requests.
|
The client code reads the cookie and adds a custom request header with the token in all subsequent requests.
|
||||||
The server compares the received cookie value to the request header value and rejects the request if the values are missing or don't match.
|
The server compares the received cookie value to the request header value and rejects the request if the values are missing or don't match.
|
||||||
|
|
||||||
This technique is effective because all browsers implement the _same origin policy_. Only code from the website
|
This technique is effective because all browsers implement the _same origin policy_. Only code from the website
|
||||||
on which cookies are set can read the cookies from that site and set custom headers on requests to that site.
|
on which cookies are set can read the cookies from that site and set custom headers on requests to that site.
|
||||||
That means only your application can read this cookie token and set the custom header. The malicious code on `evil.com` can't.
|
That means only your application can read this cookie token and set the custom header. The malicious code on `evil.com` can't.
|
||||||
|
|
||||||
Angular's `http` has built-in support for the client-side half of this technique in its `XSRFStrategy`.
|
Angular's `http` has built-in support for the client-side half of this technique in its `XSRFStrategy`.
|
||||||
The default `CookieXSRFStrategy` is turned on automatically.
|
The default `CookieXSRFStrategy` is turned on automatically.
|
||||||
Before sending an HTTP request, the `CookieXSRFStrategy` looks for a cookie called `XSRF-TOKEN` and
|
Before sending an HTTP request, the `CookieXSRFStrategy` looks for a cookie called `XSRF-TOKEN` and
|
||||||
sets a header named `X-XSRF-TOKEN` with the value of that cookie.
|
sets a header named `X-XSRF-TOKEN` with the value of that cookie.
|
||||||
|
|
||||||
The server must do its part by setting the
|
The server must do its part by setting the
|
||||||
initial `XSRF-TOKEN` cookie and confirming that each subsequent state-modifying request
|
initial `XSRF-TOKEN` cookie and confirming that each subsequent state-modifying request
|
||||||
includes a matching `XSRF-TOKEN` cookie and `X-XSRF-TOKEN` header.
|
includes a matching `XSRF-TOKEN` cookie and `X-XSRF-TOKEN` header.
|
||||||
|
|
||||||
XSRF/CSRF tokens should be unique per user and session, have a large random value generated by a
|
XSRF/CSRF tokens should be unique per user and session, have a large random value generated by a
|
||||||
cryptographically secure random number generator, and should expire in a day or two.
|
cryptographically secure random number generator, and should expire in a day or two.
|
||||||
|
|
||||||
Your server may use a different cookie or header name for this purpose.
|
Your server may use a different cookie or header name for this purpose.
|
||||||
An Angular application can customize cookie and header names by providing its own `CookieXSRFStrategy` values.
|
An Angular application can customize cookie and header names by providing its own `CookieXSRFStrategy` values.
|
||||||
code-example(language="typescript").
|
code-example(language="typescript").
|
||||||
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }
|
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }
|
||||||
:marked
|
:marked
|
||||||
Or you can implement and provide an entirely custom `XSRFStrategy`:
|
Or you can implement and provide an entirely custom `XSRFStrategy`:
|
||||||
|
|
||||||
code-example(language="typescript").
|
code-example(language="typescript").
|
||||||
{ provide: XSRFStrategy, useClass: MyXSRFStrategy }
|
{ provide: XSRFStrategy, useClass: MyXSRFStrategy }
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
For information about CSRF at the Open Web Application Security Project (OWASP), see
|
For information about CSRF at the Open Web Application Security Project (OWASP), see
|
||||||
<a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29" target="_blank">Cross-Site Request Forgery (CSRF)</a> and
|
<a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29" target="_blank">Cross-Site Request Forgery (CSRF)</a> and
|
||||||
<a href="https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet" target="_blank">Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet</a>.
|
<a href="https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet" target="_blank">Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet</a>.
|
||||||
The Stanford University paper
|
The Stanford University paper
|
||||||
<a href="https://seclab.stanford.edu/websec/csrf/csrf.pdf" target="_blank">Robust Defenses for Cross-Site Request Forgery</a> is a rich source of detail.
|
<a href="https://seclab.stanford.edu/websec/csrf/csrf.pdf" target="_blank">Robust Defenses for Cross-Site Request Forgery</a> is a rich source of detail.
|
||||||
|
|
||||||
See also Dave Smith's easy-to-understand
|
See also Dave Smith's easy-to-understand
|
||||||
<a href="https://www.youtube.com/watch?v=9inczw6qtpY" target="_blank" title="Cross Site Request Funkery Securing Your Angular Apps From Evil Doers">talk on XSRF at AngularConnect 2016</a>.
|
<a href="https://www.youtube.com/watch?v=9inczw6qtpY" target="_blank" title="Cross Site Request Funkery Securing Your Angular Apps From Evil Doers">talk on XSRF at AngularConnect 2016</a>.
|
||||||
|
|
||||||
h3#xssi Cross-site script inclusion (XSSI)
|
h3#xssi Cross-site script inclusion (XSSI)
|
||||||
:marked
|
:marked
|
||||||
Cross-site script inclusion, also known as JSON vulnerability, can allow an attacker's website to
|
Cross-site script inclusion, also known as JSON vulnerability, can allow an attacker's website to
|
||||||
read data from a JSON API. The attack works on older browsers by overriding native JavaScript
|
read data from a JSON API. The attack works on older browsers by overriding native JavaScript
|
||||||
object constructors, and then including an API URL using a `<script>` tag.
|
object constructors, and then including an API URL using a `<script>` tag.
|
||||||
|
|
||||||
This attack is only successful if the returned JSON is executable as JavaScript. Servers can
|
This attack is only successful if the returned JSON is executable as JavaScript. Servers can
|
||||||
prevent an attack by prefixing all JSON responses to make them non-executable, by convention, using the
|
prevent an attack by prefixing all JSON responses to make them non-executable, by convention, using the
|
||||||
well-known string `")]}',\n"`.
|
well-known string `")]}',\n"`.
|
||||||
|
|
||||||
Angular's `Http` library recognizes this convention and automatically strips the string
|
Angular's `Http` library recognizes this convention and automatically strips the string
|
||||||
`")]}',\n"` from all responses before further parsing.
|
`")]}',\n"` from all responses before further parsing.
|
||||||
|
|
||||||
For more information, see the XSSI section of this [Google web security blog
|
For more information, see the XSSI section of this [Google web security blog
|
||||||
post](https://security.googleblog.com/2011/05/website-security-for-webmasters.html).
|
post](https://security.googleblog.com/2011/05/website-security-for-webmasters.html).
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
h2#code-review Auditing angular applications
|
h2#code-review Auditing angular applications
|
||||||
|
Loading…
x
Reference in New Issue
Block a user