Menu Search Me

Web Security

Created by lucas88 on 2020-12-18

Same Origin Policy, CORS

Two URLs have the same origin if the protocol, port (if specified), and host are the same for both.

about:blank and javascript: URL

Scripts executed from pages with an about:blank or javascript: URL inherit the origin of the document containing that URL, since these types of URLs do not contain information about an origin server. For example, about:blank is often used as a URL of new, empty popup windows into which the parent script writes content (e.g. via the mechanism). If this popup also contains JavaScript, that script would inherit the same origin as the script that created it.

Internet explorer

Internet Explorer has two major exceptions to the same-origin policy, these exceptions are nonstandard and unsupported in any other browser.

1.   Trust Zones: If both domains are in the highly trusted zone (e.g. corporate intranet domains), then the same-origin limitations are not applied.

2.   Port: IE doesn't include port into same-origin checks. Therefore, and are considered the same origin and no restrictions are applied.

Changing origin

Assume a script from the document at executes the following:

document.domain = "";

Afterward, the page can pass the same-origin check with

However, could not set document.domain to, since that is not a superdomain of

Cross-origin network access

The same-origin policy controls interactions between two different origins, such as when you use XMLHttpRequest or an <img> element. These interactions are typically placed into three categories:

       Cross-origin writes are typically allowed. Examples are links, redirects, and form submissions. Some HTTP requests require preflight.

       Cross-origin embedding is typically allowed. (Examples are listed below.)

       Cross-origin reads are typically disallowed, but read access is often leaked by embedding. For example, you can read the dimensions of an embedded image, the actions of an embedded script, or the availability of an embedded resource.

Here are some examples of resources which may be embedded cross-origin:

       JavaScript with <script src=" "></script>. Error details for syntax errors are only available for same-origin scripts.

       CSS applied with <link rel="stylesheet" href=" ">. Due to the relaxed syntax rules of CSS, cross-origin CSS requires a correct Content-Type header. Restrictions vary by browser: Internet Explorer, Firefox, Chrome , Safari (scroll down to CVE-2010-0051) and Opera.

       Images displayed by <img>.

       Media played by <video> and <audio>.

       External resources embedded with <object> and <embed>.

       Fonts applied with @font-face. Some browsers allow cross-origin fonts, others require same-origin.

       Anything embedded by <iframe>. Sites can use the X-Frame-Options header to prevent cross-origin framing.

Use CORS to allow cross-origin network access (reads)

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources.

CORS also relies on a mechanism by which browsers make a preflight request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. Preflighted" requests uses the OPTIONS method. Note that not all http get/post requests will need preflight requests.

Here is an example request with the origin header, which shows that the invocation is coming from https://foo.example:

GET /resources/public-data/ HTTP/1.1

Host: bar.other

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-us,en;q=0.5

Accept-Encoding: gzip,deflate

Connection: keep-alive

Origin: https://foo.example

Here is an example response:

HTTP/1.1 200 OK

Date: Mon, 01 Dec 2008 00:23:53 GMT

Server: Apache/2

Access-Control-Allow-Origin: *

Keep-Alive: timeout=2, max=100

Connection: Keep-Alive

Transfer-Encoding: chunked

Content-Type: application/xml


[ XML Data ]

In the response, the server sends back an Access-Control-Allow-Origin header with Access-Control-Allow-Origin: *, which means that the resource can be accessed by any origin. The response can also be more restrictive, as in Access-Control-Allow-Origin: https://foo.example.

Cross-origin script API access

Cross-origin read/write access to some methods/properties of JavaScript Window and Location objects are allowed. Levels of access vary by browser types.

Cross-origin data storage access

Access to data stored in the browser such as Web Storage and IndexedDB are separated by origin. Each origin gets its own separate storage, and JavaScript in one origin cannot read from or write to the storage belonging to another origin.

Cross-origin cookie access

Cookies use a separate definition of origins. A page can set a cookie for its own domain or any parent domain, as long as the parent domain is not a public suffix.

Firefox and Chrome use the Public Suffix List to determine if a domain is a public suffix. Internet Explorer uses its own internal method to determine if a domain is a public suffix.

The browser will make a cookie available to the given domain including any sub-domains, no matter which protocol (HTTP/HTTPS) or port is used.

When you set a cookie, you can limit its availability using the Domain, Path, Secure, and HttpOnly flags. When you read a cookie, you cannot see from where it was set. Even if you use only secure https connections, any cookie you see may have been set using an insecure connection.

Content Security Policy

Same Origin Policy allow cross-origin execution of JavaScript scripts from different origins. This may cause security issues such as XSS. For example, the Google +1 button at the bottom of this page loads and executes code from which is different from this page's origin. We trust that code, but we can't expect the browser to figure out on its own that code from is awesome, while code from probably isn't. The browser happily downloads and executes any code a page requests, regardless of source.

Instead of blindly trusting everything that a server delivers, CSP defines the Content-Security-Policy HTTP header, which allows you to create an allowlist of sources of trusted content, and instructs the browser to only execute or render resources from those sources.

Since we trust to deliver valid code, and we trust ourselves to do the same, let's define a policy that only allows script to execute when it comes from one of those two sources:

Content-Security-Policy: script-src 'self'

While script resources are the most obvious security risks, CSP provides a rich set of policy directives that enable fairly granular control over the resources that a page is allowed to load. You've already seen script-src, so the concept should be clear.

Let's quickly walk through the rest of the resource directives. The list below represents the state of the directives as of level 2. A level 3 spec has been published, but is largely unimplemented in the major browsers.

       base-uri restricts the URLs that can appear in a page's <base> element.

       child-src lists the URLs for workers and embedded frame contents. For example: child-src would enable embedding videos from YouTube but not from other origins.

       connect-src limits the origins that you can connect to (via XHR, WebSockets, and EventSource).

       font-src specifies the origins that can serve web fonts. Google's web fonts could be enabled via font-src

       form-action lists valid endpoints for submission from <form> tags.

       frame-ancestors specifies the sources that can embed the current page. This directive applies to <frame>, <iframe>, <embed>, and <applet> tags. This directive can't be used in <meta> tags and applies only to non-HTML resources.

       frame-src was deprecated in level 2, but is restored in level 3. If not present it still falls back to child-src as before.

       img-src defines the origins from which images can be loaded.

       media-src restricts the origins allowed to deliver video and audio.

       object-src allows control over Flash and other plugins.

       plugin-types limits the kinds of plugins a page may invoke.

       report-uri specifies a URL where a browser will send reports when a content security policy is violated. This directive can't be used in <meta> tags.

       style-src is script-src's counterpart for stylesheets.

       upgrade-insecure-requests instructs user agents to rewrite URL schemes, changing HTTP to HTTPS. This directive is for websites with large numbers of old URL's that need to be rewritten.

       worker-src is a CSP Level 3 directive that restricts the URLs that may be loaded as a worker, shared worker, or service worker. As of July 2017, this directive has limited implementations.

Cross-site script inclusion (XSSI)

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 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 prevent an attack by prefixing all JSON responses to make them non-executable, by convention, using the well-known string ")]}',\n".

Angular's HttpClient library recognizes this convention and automatically strips the string ")]}',\n" from all responses before further parsing.

For more information, see the XSSI section of this Google web security blog post.

Angular Security

Angular's cross-site scripting security model

To systematically block XSS bugs, Angular treats all values as untrusted by default. When a value is inserted into the DOM from a template, via property, attribute, style, class binding, or interpolation, Angular sanitizes and escapes untrusted values.

Angular templates are the same as executable code: HTML, attributes, and binding expressions (but not the values bound) in templates are trusted to be safe. This means that applications must prevent values that an attacker can control from ever making it into the source code of a template. Never generate template source code by concatenating user input and templates. To prevent these vulnerabilities, use the offline template compiler, also known as template injection.

Sanitization and security contexts

Sanitization is the inspection of an untrusted value, turning it into a value that's safe to insert into the DOM. In many cases, sanitization doesn't change a value at all. Sanitization depends on context: a value that's harmless in CSS is potentially dangerous in a URL.

Angular defines the following security contexts:

HTML is used when interpreting a value as HTML, for example, when binding to innerHtml.

Style is used when binding CSS into the style property.

URL is used for URL properties, such as <a href>.

Resource URL is a URL that will be loaded and executed as code, for example, in <script src>.

Angular sanitizes untrusted values for HTML, styles, and URLs; sanitizing resource URLs isn't possible because they contain arbitrary code. In development mode, Angular prints a console warning when it has to change a value during sanitization.

Sanitization example

The following template binds the value of htmlSnippet, once by interpolating it into an element's content, and once by binding it to the innerHTML property of an element:



<h3>Binding innerHTML</h3>

<p>Bound value:</p>

<p class="e2e-inner-html-interpolated">{{htmlSnippet}}</p>

<p>Result of binding to innerHTML:</p>

<p class="e2e-inner-html-bound" [innerHTML]="htmlSnippet"></p>

Interpolated content is always escaped by Angular the HTML isn't interpreted and the browser displays angle brackets in the element's text content.

For the HTML to be interpreted, bind it to an HTML property such as innerHTML. But binding a value that an attacker might control into innerHTML normally causes an XSS vulnerability. For example, code contained in a <script> tag is executed:

src/app/inner-html-binding.component.ts (class)

export class InnerHtmlBindingComponent {

// For example, a user/attacker-controlled value from a URL.

htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';


Angular recognizes the value bound to innerHTML as unsafe and automatically sanitizes it, which removes the <script> tag but keeps safe content such as the <b> element.

Direct use of the DOM APIs and explicit sanitization calls

The built-in browser DOM APIs don't automatically protect you from security vulnerabilities. For example, document, the node available through ElementRef, and many third-party APIs contain unsafe methods. In the same way, if you interact with other libraries that manipulate the DOM, you likely won't have the same automatic sanitization as with Angular interpolations. Avoid directly (or use unsafe 3rd party libraries) interacting with the DOM and instead use Angular templates where possible.

For cases where this is unavoidable, use the built-in Angular sanitization functions. Sanitize untrusted values with the DomSanitizer.sanitize method and the appropriate SecurityContext. That function also accepts values that were marked as trusted using the bypassSecurityTrust... functions, and will not sanitize them.

abstract class DomSanitizer implements Sanitizer {

abstract sanitize(context: SecurityContext, value: string | SafeValue): string | null

abstract bypassSecurityTrustHtml(value: string): SafeHtml

abstract bypassSecurityTrustStyle(value: string): SafeStyle

abstract bypassSecurityTrustScript(value: string): SafeScript

abstract bypassSecurityTrustUrl(value: string): SafeUrl

abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl }

Example Usage

import { Pipe, PipeTransform } from '@angular/core';


constructor(protected sanitizer: DomSanitizer) {}


let bypassedValue:any = null;

let sanitizedValue:string = null;

//suppose value is trusted html, bypass Angular sanitization

bypassedValue = this.sanitizer.bypassSecurityTrustHtml(value);

//suppose value is trusted style, bypass Angular sanitization

bypassedValue = this.sanitizer.bypassSecurityTrustStyle(value);

//suppose value is trusted script, bypass Angular sanitization

bypassedValue = this.sanitizer.bypassSecurityTrustScript(value);

//suppose value is trusted url, bypass Angular sanitization

bypassedValue = this.sanitizer.bypassSecurityTrustUrl(value);

//suppose value is trusted resource url, bypass Angular sanitization

bypassedValue = this.sanitizer.bypassSecurityTrustResourceUrl(value);

//suppose value is not trusted html, sanitize it

sanitizedValue = this.sanitizer.sanitize(SecurityContext.HTML, value);

Burp Suite