Sunteți pe pagina 1din 170

Getting

Single Page Application Security


Right
Philippe De Ryck

iMinds-DistriNet, KU Leuven

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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/

#Devoxx #SecureSPA @PhilippeDeRyck


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/

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


Traditional Web Applications
Create New Task

Description: POST newItem.php


Cooking
Parse request
Deadline: 25/02/2015

Add to List Store data

Retrieve all data


Overview
Deadline Task
Generate HTML
25/02/2015 Cooking <html>
30/03/2015 B-day party
</html>
Send response
Add New

#Devoxx #SecureSPA @PhilippeDeRyck


Traditional Web Applications
Create New Task

Description: POST newItem.php


Cooking
Parse request
Deadline: 25/02/2015

Add to List Store data

Retrieve all data


Overview
Deadline Task
Generate HTML
25/02/2015 Cooking <html>
30/03/2015 B-day party
</html>
Send response
Add New

#Devoxx #SecureSPA @PhilippeDeRyck


Traditional Web Applications
Create New Task

Description: Cooking
Parse request
Deadline: 25/02/2015

Add to List Store data

Retrieve all data


Overview
Deadline
Deadline Task
Task
Generate HTML
30/03/2015
25/02/2015 B-day party
Cooking
25/02/2015
30/03/2015 Cooking
B-day party Send response
GET sortBy?col=Task
Add New
<table> Sorting API

</table>

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Applications

Overview
Create New Task
Parse request
Deadline
Deadline Task
Task POST /items/
Description: Cooking
25/02/2015
30/03/2015 Cooking
B-day party
Deadline:
30/03/2015
25/02/2015
25/02/2015
B-day party
Cooking Store data
OK
Add
AddtoNew
List
Send response

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Application Architecture
Client-Side Static Application
Application
Files Storage Backend
Default Browser
Security Policies API
Client-Enforced
JavaScript APIs
Security Policies
Server-Controlled
Security Policies Static Application
Files Storage Backend
Client-Side Data
Storage API
Client-Enforced
Session Data Security Policies

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Application Architecture
Client-Side Static Application
Application
Files Storage Backend
Default Browser
Security Policies API
Client-Enforced
JavaScript APIs
Security Policies
Server-Controlled
Security Policies Static Application
Files Storage Backend
Client-Side Data
Storage API
Client-Enforced
Session Data Security Policies

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Application Architecture
Client-Side Static Application
Application
Files Storage Backend
Default Browser
Security Policies API
Client-Enforced
JavaScript APIs
Security Policies
Server-Controlled
Security Policies Static Application
Files Storage Backend
Client-Side Data
Storage API
Client-Enforced
Session Data Security Policies

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Application Architecture
Cookie Security flags
Client-Side Static Application
Application
Files
X-Frame-Options Storage Backend
Default Browser
Security Policies API
Content Security Policy
Client-Enforced
JavaScript APIs
Security Policies
Cross-Origin Resource Sharing
Server-Controlled
Security Policies HTTP Strict Transport Security
Static Application
Files Storage Backend
Client-Side Data
Storage HTTP Public Key Pinning
API
Client-Enforced
Subresource Integrity
Session Data Security Policies

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Application Architecture
Client-Side Static Application
Application
Files Storage Backend
Default Browser
Security Policies API
Client-Enforced
JavaScript APIs
Security Policies
Server-Controlled
Security Policies Static Application
Files Storage Backend
Client-Side Data
Storage API
Client-Enforced
Session Data Security Policies 17

#Devoxx #SecureSPA @PhilippeDeRyck


Web Security has Become Complex

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

#Devoxx #SecureSPA @PhilippeDeRyck


Web Security has Become Complex

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

#Devoxx #SecureSPA @PhilippeDeRyck


The Web Security Landscape

20
#Devoxx #SecureSPA @PhilippeDeRyck
Presentation Overview
Session Management

Cross-Site Scripting (XSS)

Content Security Policy (CSP)

Cross-Origin Resource Sharing (CORS)

#Devoxx #SecureSPA @PhilippeDeRyck


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)

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


Cookies Make HTTP Stateful
Some-shop.com
Go to some-shop.com
Hello stranger 1
3a99a4d1e8f496
Login as Philippe Logged_in: false
true
Hello Philippe User: Philippe
Show orders Admin: true
List of orders

Go to some-shop.com 2
7ad3e9f78bc808
Hello stranger Logged_in: false
true
Login as NotPhilippe User: NotPhilippe
Hello NotPhilippe Admin: false

Set-Cookie: sessionid=1; Expires=Wed, 09 Jun 2021 10:18:14 GMT;


Domain=some-shop.com; Secure; HttpOnly

Cookie: sessionid=1

#Devoxx #SecureSPA @PhilippeDeRyck


But Isnt REST Stateless?
Client-Side Static Application
Application
Files Storage Backend
Default Browser
Security Policies API
Client-Enforced
JavaScript APIs
Security Policies
Server-Controlled
Security Policies Static Application
Files Storage Backend
Client-Side Data
Storage API
Client-Enforced
Session Data Security Policies

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
Client-Side Sessions with Cookies
Some-shop.com
Go to some-shop.com
Hello stranger
false
Logged_in: true Login as Philippe Logged_in: false
true
User: Philippe Hello Philippe User: Philippe
Admin: true Show orders Admin: true
List of orders

Go to some-shop.com
Logged_in: false
true Hello stranger Logged_in: false
true
User: NotPhilippe Login as NotPhilippe User: NotPhilippe
Admin: false Hello NotPhilippe Admin: false

Very similar to server-side sessions if(!req.session.Admin) {


// throw error
Data is simply stored in a different place }
else {
Transparent to the application // Do admin stuff
}

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
Cross-Site Request Forgery
Login as Philippe
Hello Philippe
Show orders
List of orders
some-shop.com
Change email address
Sure thing, Philippe

Show latest blog post


Latest blog post
hackedblog.com

The server is confused about the intentions of the user


Malicious sites trigger unintended requests from the users browser
Browser happily attaches the cookies, which contain session info

Well-known attack, but requires explicit action to prevent


#Devoxx #SecureSPA @PhilippeDeRyck
CSRF in the Wild

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

#Devoxx #SecureSPA @PhilippeDeRyck


CSRF in the Wild

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

#Devoxx #SecureSPA @PhilippeDeRyck


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

Account details page


Account details
t Change email address
Sure thing, Philippe
t some-shop.com
Change email address
CSRF token sadness L TOKEN-BASED APPROACH

Show latest blog post <form action=submit.php>


Latest blog post
hackedblog.com <input type=hidden
name=token
value=qasfj8j12ads />

</form>

#Devoxx #SecureSPA @PhilippeDeRyck


CSRF Defense 2: Origin Header
Check the origin header sent by the browser
Automatically added to state-changing requests (POST/PUT/DELETE)

Change email address


Origin: http://some-shop.com

Sure thing, Philippe


some-shop.com
Change email address
Origin: http://hackedblog.com
Stranger danger! L
Show latest blog post
Latest blog post
hackedblog.com

#Devoxx #SecureSPA @PhilippeDeRyck


CSRF Defense 3: Transparent Tokens
Compare a cookie value against a header value
Browsers cookie policies prevent illegitimate access

First request

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

Cookie: session= some-shop.com


Cookie: CSRF-Token=123
X-CSRF-Token: 123

Only the JS code on the page can


copy cookie value into header

#Devoxx #SecureSPA @PhilippeDeRyck


CSRF Defense 3: Transparent Tokens
Well-suited CSRF defense for stateless APIs
Supported by numerous libraries for various frameworks
TRANSPARENT TOKENS

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

#Devoxx #SecureSPA @PhilippeDeRyck


CSRF Defense 3: Transparent Tokens
Well-suited CSRF defense for stateless APIs
Supported by numerous libraries for various frameworks
EMBERJS INITIALIZER
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]);
}
}
})}};

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
Tokens as an Alternative to Cookies
Login as Philippe
Hello Philippe
Show orders
List of orders
some-shop.com
Change email address
Dude, wheres your token?

Show latest blog post


Latest blog post
hackedblog.com

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 theyre not automatically attached

#Devoxx #SecureSPA @PhilippeDeRyck


http://jwt.io/

#Devoxx #SecureSPA @PhilippeDeRyck


JSON Web Token
A JWT just looks like a blob of data
Contains three sections of base64-encoded data

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaXN0cmluZXQuY3Mua3VsZXV2Z
W4uYmUiLCJleHAiOjI0MjUwNzgwMDAwMDAsIm5hbWUiOiJwaGlsaXBwZSIsImFkbWluIjp0cnV
lfQ.dIi1OguZ7K3ADFnPOsmX2nEpF2Asq89g7GTuyQuN3so

{
HMACSHA256(
"iss": distrinet.cs
{ base64UrlEncode(header)
.kuleuven.be",
"alg": "HS256", + "." +
"exp": 1425078000000,
"typ": "JWT" base64UrlEncode(payload),
"name": "philippe",
} secret
"admin": true
)
}
Header Payload Signature
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


Client-Side Sessions with JWT
HANDLING JWT TOKENS
function 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;
}
}

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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 servers public key
Fixed by depending on config instead of algorithm
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
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)

#Devoxx #SecureSPA @PhilippeDeRyck


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)

#Devoxx #SecureSPA @PhilippeDeRyck


XSS Illustrated
<html><body> </body></html>

Show Reviews
Reviews page
reviews

Add review
Thanks for the review!

I can really recommend product X. It is awesome!


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

#Devoxx #SecureSPA @PhilippeDeRyck


The Consequences of XSS Are Severe

#Devoxx #SecureSPA @PhilippeDeRyck


Apache.org Compromise
1. Report bug with obscured URL
2. Admin opens link,
containing reflected XSS attack
compromising their session
http://tinyurl.com/XXXXXXX

4. Attacker changes upload


3. Attacker disable notifications
path to location that can
for a hosted project
execute JSP files

6. Attacker browses and copies


5. Attacker added new bug filesystem through JSP. Installs
reports with JSP attachments backdoor JSP with webserver
privileges

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

#Devoxx #SecureSPA @PhilippeDeRyck


Apache.org Compromise
7. Attacker installs JAR to
collect passwords on login

8. Triggered logins by sending 9. One of the passwords


out password reset mails matched an SSH account with
full sudo access

10. The accessible machine 11. From the subversion


had user home folders, with machine, privilege escalation
cached subversion credentials was unsuccessful

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

#Devoxx #SecureSPA @PhilippeDeRyck


What Is XSS Exactly?
XSS leads to the execution of attacker-controlled code in the
context of the vulnerable application in the victims browser

The payload of an XSS attack is provided by the attacker


Malicious code, that can load additional code files if desired

The victims browser parsing the payload triggers the attack


The browser will trigger the execution of the attackers code

The malicious code runs within the applications context


The attackers code has the same privileges as the application code
#Devoxx #SecureSPA @PhilippeDeRyck
Stored XSS
<html><body> </body></html>

Show Reviews
Reviews page
reviews

Add review
Thanks for the review!

I can really recommend product X. It is awesome!


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

#Devoxx #SecureSPA @PhilippeDeRyck


Reflected XSS
<html><body><h1> </h1><p> </p></body></html>

Show Product (id=1, name= )


Product page
products

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>

#Devoxx #SecureSPA @PhilippeDeRyck


DOM-Based XSS
permalink.innerHTML = '<a href="' + <html><body><p>
window.location.hash.split('#')[1] +
'.php">Link to product</a>; </p></body></html>

Get page with all products


Product page
products

Hey, checkout product X. It is awesome!


<a href=http://some-shop.org/allproducts.php#1
><script>alert(Never gonna let you down!)</script>

#Devoxx #SecureSPA @PhilippeDeRyck


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>

#Devoxx #SecureSPA @PhilippeDeRyck


But Preventing XSS Seems Hard

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

#Devoxx #SecureSPA @PhilippeDeRyck


Can JS MVC Frameworks Help?
Create New Task

Description: Cooking
Parse request
Deadline: 25/02/2015

Add to List Store data

Retrieve all data


Overview
Deadline
Deadline Task
Task
Generate HTML
30/03/2015
25/02/2015 B-day party
Cooking
25/02/2015
30/03/2015 Cooking
B-day party Send response
GET /tasks?sortBy=name
Add New
Sorting API
[{},{}]

#Devoxx #SecureSPA @PhilippeDeRyck


Server-Side Template Composition
JavaScript MVC frameworks change how the DOM works
Extensions through elements, attributes, etc.
New interfaces
Often in combination with templating
EXTENDING THE DOM

<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>

#Devoxx #SecureSPA @PhilippeDeRyck


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

KNOCKOUT.JS EXAMPLE

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

#Devoxx #SecureSPA @PhilippeDeRyck


Mustache Security

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

#Devoxx #SecureSPA @PhilippeDeRyck


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/

#Devoxx #SecureSPA @PhilippeDeRyck


Mustache Security Examples
KENDOUI EXAMPLE

<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>

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

#Devoxx #SecureSPA @PhilippeDeRyck


Mustache Security Examples
ANGULARJS EXAMPLE (< 1.2)

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

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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


Single Page Applications

Overview
Create New Task
Parse request
Deadline
Deadline Task
Task POST /items/
Description: Cooking
25/02/2015
30/03/2015 Cooking
B-day party
Deadline:
30/03/2015
25/02/2015
25/02/2015
B-day party
Cooking Store data
OK
Add
AddtoNew
List
Send response

#Devoxx #SecureSPA @PhilippeDeRyck


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?

#Devoxx #SecureSPA @PhilippeDeRyck


Example Case User-Provided Images
ANGULARJS TEMPLATE

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

USER INPUT

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

RENDERED HTML

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

#Devoxx #SecureSPA @PhilippeDeRyck


Example Case User-Provided Images
ANGULARJS TEMPLATE

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

USER INPUT

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

RENDERED HTML

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

#Devoxx #SecureSPA @PhilippeDeRyck


Example Case User-Provided Images
ANGULARJS TEMPLATE

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

USER INPUT

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

RENDERED HTML

Error: [$sce:unsafe] Attempting to use


an unsafe value in a safe context.

#Devoxx #SecureSPA @PhilippeDeRyck


Dammit

#Devoxx #SecureSPA @PhilippeDeRyck


Check Documentation

#Devoxx #SecureSPA @PhilippeDeRyck


Go to StackOverflow

#Devoxx #SecureSPA @PhilippeDeRyck


And you Find This Little Gem

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

#Devoxx #SecureSPA @PhilippeDeRyck


Example Case User-Provided Images
ANGULARJS TEMPLATE

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

USER INPUT

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

RENDERED HTML

#Devoxx #SecureSPA @PhilippeDeRyck


#Devoxx #SecureSPA @PhilippeDeRyck
Example Case User-Provided Images
ANGULARJS TEMPLATE

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

USER INPUT

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

RENDERED HTML

#Devoxx #SecureSPA @PhilippeDeRyck


How Did That Happen?

#Devoxx #SecureSPA @PhilippeDeRyck


Strict Contextual Escaping
AngularJS tries to protect you from injection attacks
Let it, its really good at it!

ng-bind will never produce HTML


ANGULARJS TEMPLATE
<textarea ng-model=x></textarea>
<div ng-bind=x"></div>
GENERATED HTML

<div ng-bind=x">
&lt;img src=http://some-shop.com/coolcar.png"
onerror=alert(1) /&gt;
</div>

#Devoxx #SecureSPA @PhilippeDeRyck


Strict Contextual Escaping
AngularJS tries to protect you from injection attacks
Let it, its really good at it!

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


ANGULARJS TEMPLATE
<textarea ng-model=x></textarea>
<div ng-bind-html=x"></div>
GENERATED HTML

Error: [$sce:unsafe] Attempting to use


an unsafe value in a safe context.

#Devoxx #SecureSPA @PhilippeDeRyck


Strict Contextual Escaping
AngularJS tries to protect you from injection attacks
Let it, its really good at it!

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


Enable automatic sanitization with ngSanitize
Removes dangerous features from content

#Devoxx #SecureSPA @PhilippeDeRyck


Example Case User-Provided Images
ANGULARJS TEMPLATE

<textarea ng-model=x></textarea>
<div ng-bind-html=x></div>
ANGULARJS CODE

angular.module(test, [ngSanitize])
USER INPUT

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

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

#Devoxx #SecureSPA @PhilippeDeRyck


Strict Contextual Escaping
AngularJS tries to protect you from injection attacks
Let it, its 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
#Devoxx #SecureSPA @PhilippeDeRyck
Strict Contextual Escaping - trustAsHtml

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

#Devoxx #SecureSPA @PhilippeDeRyck


Strict Contextual Escaping - trustAsHtml
ANGULARJS TEMPLATE

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

ANGULARJS CODE

angular.module(test,[])
.filter("i_really_know_my_security",
['$sce', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
}]);

#Devoxx #SecureSPA @PhilippeDeRyck


And We Can Do The Same for EmberJS
EMBERJS TEMPLATE

{{input type=text value=x}}


<div>{{x}}</div>

USER INPUT

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

RENDERED HTML

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

#Devoxx #SecureSPA @PhilippeDeRyck


And We Can Do The Same for EmberJS

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

#Devoxx #SecureSPA @PhilippeDeRyck


And We Can Do The Same for EmberJS
EMBERJS TEMPLATE

{{input type=text value=x}}


<div>{{{x}}}</div>

USER INPUT

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

RENDERED HTML

#Devoxx #SecureSPA @PhilippeDeRyck


And We Can Do The Same for EmberJS
EMBERJS TEMPLATE

{{input type=text value=x}}


<div>{{{x}}}</div>

USER INPUT

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

RENDERED HTML

#Devoxx #SecureSPA @PhilippeDeRyck


And We Can Do The Same for EmberJS
EMBERJS TEMPLATE & CONTROLLER
{{input type=text value=x}}
<div>{{y}}</div>

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

USER INPUT

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

RENDERED HTML

#Devoxx #SecureSPA @PhilippeDeRyck


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
EMBERJS TEMPLATE
{{input type=text value=x}}
<div>{{sanitize-purify x}}</div>
EMBERJS SANITIZE HELPER
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);

#Devoxx #SecureSPA @PhilippeDeRyck


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


#Devoxx #SecureSPA @PhilippeDeRyck
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)

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
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)

#Devoxx #SecureSPA @PhilippeDeRyck


EmberJS Developers already Know CSP

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


Introducing CSP by Example
XSS WITH INLINE SCRIPTS
<h1>You searched for<script>alert(XSS);</script></h1>

XSS WITH REMOTE SCRIPTS


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

XSS WITH EVAL


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

#Devoxx #SecureSPA @PhilippeDeRyck


Introducing CSP by Example
EXAMPLE POLICY
Content-Security-Policy:
default-src 'self';

EXAMPLE POLICY
Content-Security-Policy:
default-src 'self';
script-src self
https://cdnjs.cloudflare.com;

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


Introducing CSP by Example

EXAMPLE POLICY
Content-Security-Policy:
default-src 'self';
script-src self
https://cdnjs.cloudflare.com;
style-src self
https://cdnjs.cloudflare.com//bootstrap.min.css;

104
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


CSP is the Security Policy of the Future

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

#Devoxx #SecureSPA @PhilippeDeRyck


A Quick Overview of CSPs 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

#Devoxx #SecureSPA @PhilippeDeRyck


A Quick Overview of CSPs 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

#Devoxx #SecureSPA @PhilippeDeRyck


Revisiting the CSP Example

EXAMPLE POLICY
Content-Security-Policy:
default-src 'self';
script-src self
https://cdnjs.cloudflare.com;
style-src self
https://cdnjs.cloudflare.com//bootstrap.min.css;

#Devoxx #SecureSPA @PhilippeDeRyck


Obeying CSPs Content Restrictions
EXTERNALIZED SCRIPT
function run() {
alert('booh!');
}
document.addEventListener('DOMContentReady',
function () {
document.getElementById('myLink')
.addEventListener('click', run);
});
INLINE SCRIPT

<script>
function run() { EXTERNALIZED SCRIPT
alert(booh!');
} <script src="myscript.js"></script>
</script> <a href="#" id="myLink">...</a>

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

#Devoxx #SecureSPA @PhilippeDeRyck


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
EXAMPLE POLICY
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;

#Devoxx #SecureSPA @PhilippeDeRyck


Lifting Content Restrictions in CSP
CSP Level 2 supports nonces and hashes
Inline script and style blocks can be allowed

EXAMPLE POLICY WITH A NONCE


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

EXAMPLE USE OF A NONCE


<script nonce=RANDOM></script>

#Devoxx #SecureSPA @PhilippeDeRyck


Lifting Content Restrictions in CSP
CSP Level 2 supports nonces and hashes
Inline script and style blocks can be allowed

EXAMPLE POLICY WITH A NONCE


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

EXAMPLE USE OF A NONCE


<script nonce=a8qzj1r></script>

#Devoxx #SecureSPA @PhilippeDeRyck


CSP is the Security Policy of the Future

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

#Devoxx #SecureSPA @PhilippeDeRyck


CSP Examples
Goal: Load no external resources
EXAMPLE POLICY
Content-Security-Policy:
default-src self;

Goal: Only allow HTTPS content


EXAMPLE POLICY
Content-Security-Policy:
default-src https: unsafe-inline unsafe-eval;

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


EmberJS Enables CSP by Default
Taken care of by ember-cli-content-security-policy
CSP policy can be updated through environment.js

UPDATING THE EMBERJS CSP POLICY


ENV.contentSecurityPolicyHeader = "Content-Security-Policy"
ENV.contentSecurityPolicy = {
'default-src': "'none'",
'script-src': "'self https://",

}

#Devoxx #SecureSPA @PhilippeDeRyck


EmberJS Enables CSP by Default
EMBERJS DEFAULT CSP POLICY
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;

119
#Devoxx #SecureSPA @PhilippeDeRyck
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
CSP-COMPLIANT ANGULARJS
<html ng-app ng-csp> </html>

#Devoxx #SecureSPA @PhilippeDeRyck


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
$element.onclick = function($event) {
$event[view][alert](1)
}

Technically, not inline, and no eval()

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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

CSPs reporting mode is great to start building a policy


#Devoxx #SecureSPA @PhilippeDeRyck
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

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

#Devoxx #SecureSPA @PhilippeDeRyck


CSP Violation Report Example
EXAMPLE VIOLATION REPORT
{
"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"
}
}

#Devoxx #SecureSPA @PhilippeDeRyck


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
REPORT-ONLY POLICY
Content-Security-Policy-Report-Only:
default-src 'self';
report-uri http://some-shop.com/csp-report.cgi

#Devoxx #SecureSPA @PhilippeDeRyck


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)

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


Web Applications Did not Rely on APIs
Create New Task

Description: POST newItem.php


Cooking
Parse request
Deadline: 25/02/2015

Add to List Store data

Retrieve all data


Overview
Deadline Task
Generate HTML
25/02/2015 Cooking <html>
30/03/2015 B-day party
</html>
Send response
Add New

#Devoxx #SecureSPA @PhilippeDeRyck


And Browsers Would Get Mad

#Devoxx #SecureSPA @PhilippeDeRyck


But Things Started to Change
Developers wanted to share data across applications
E.g. Google services, Facebooks 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 browsers back
Using server-side proxies
Using JSONP

#Devoxx #SecureSPA @PhilippeDeRyck


Server-Side Proxies

Load page

XHR: Load content


from websec.be Load page

www.example.com www.websec.be

#Devoxx #SecureSPA @PhilippeDeRyck


JSONP JSON with Padding
<script src=http://www.websec.be/data?callback=showUsers>
</script>

www.example.com
Load page

Load script
from websec.be

www.websec.be

showUsers([{"id": 1, "name": "Philippe"},


{"id": 2, "name": "NotPhilippe"}]);

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
Simply Allowing XHR across Origins
www.example.com
Load page

XHR: load users


profile from websec.be

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

// Access the profile data


alert(xhr.responseText);

#Devoxx #SecureSPA @PhilippeDeRyck


Simply Allowing XHR across Origins
www.example.com
Load page

XHR: load users


profile from websec.be

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

// Access the profile data


alert(xhr.responseText);

#Devoxx #SecureSPA @PhilippeDeRyck


Simply Allowing XHR across Origins
www.example.com
Load page

XHR: load users


profile from websec.be

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

// Access the profile data


alert(xhr.responseText);

#Devoxx #SecureSPA @PhilippeDeRyck


Simply Allowing XHR across Origins
www.example.com
Load page

XHR: load users


profile from websec.be

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

// Access the response data


alert(xhr.getAllResponseHeaders());

#Devoxx #SecureSPA @PhilippeDeRyck


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

CORS allows the server to tell the browser that a


resource can be accessed by a specific origin

The browser enforces these checks on the XHR call


If everything is OK, access to the resource (response) is granted
Otherwise, access is denied

#Devoxx #SecureSPA @PhilippeDeRyck


Simple CORS Example

www.example.com
Load page

XHR: load users profile from websec.be


Origin: http://www.example.com

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

#Devoxx #SecureSPA @PhilippeDeRyck


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 users credentials


Not intended to protect the server from malicious requests
#Devoxx #SecureSPA @PhilippeDeRyck
Simple CORS Example with Credentials
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.websec.be/profile', false);
xhr.withCredentials = true;
xhr.send();

www.example.com
Load page

XHR: load users profile from websec.be


Origin: http://www.example.com
Cookie: PHPSESSID=1a2b3c4d5e6f

Access-Control-Allow-Origin:
http://www.example.com www.websec.be
Access-Control-Allow-Credentials: true

#Devoxx #SecureSPA @PhilippeDeRyck


Elegantly Dealing with Legacy Servers

www.example.com
Load page

XHR: load users profile from websec.be


Origin: http://www.example.com

www.websec.be

#Devoxx #SecureSPA @PhilippeDeRyck


Elegantly Dealing with Legacy Servers

#Devoxx #SecureSPA @PhilippeDeRyck


But There Is More
www.example.com
Load page

XHR: delete users profile from websec.be


Origin: http://www.example.com

Absence of header means that this is not allowed


www.websec.be

var xhr = new XMLHttpRequest();


xhr.open(DELETE', 'http://www.websec.be/profile/1', false);
xhr.send();

// Access to the response is denied

#Devoxx #SecureSPA @PhilippeDeRyck


But There Is More
Denying access to the response protects sensitive data
Prevents an attacker from reading the users 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

#Devoxx #SecureSPA @PhilippeDeRyck


And Thats 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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


The Flow of a Preflight Request
www.example.com
Load page

Check if delete is allowed


OPTIONS /profile/1 HTTP/1.1
Origin: http://www.example.com
Access-Control-Request-Method: DELETE

Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Actual delete
DELETE /profile/1 HTTP/1.1
Origin: http://www.example.com

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

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


CORS in Practice
Virtually all modern browsers are CORS-enabled

http://caniuse.com/#search=cors
#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


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
Access-Control-Allow-Origin: *

JavaScript files that do not contain sensitive data or comments


Access-Control-Allow-Origin: *

#Devoxx #SecureSPA @PhilippeDeRyck


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 headers
Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: X-API-VERSION

#Devoxx #SecureSPA @PhilippeDeRyck


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
#Devoxx #SecureSPA @PhilippeDeRyck
HTML5 Canvas without CORS
Get image
<img src= />

Get image

<canvas>
</canvas>

Context: www.example.com img.onload = function() { www.websec.be


canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage( img, 0, 0 );
}

#Devoxx #SecureSPA @PhilippeDeRyck


HTML5 Canvas without CORS
Get image
<img src= />

Get image

<canvas>
</canvas>

// Get
Context: the CanvasPixelArray from the given coordinates and
www.example.com dimensions.
www.websec.be
var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

// Extract as Data URI


canvas.toDataURL("image/png);

#Devoxx #SecureSPA @PhilippeDeRyck


HTML5 Canvas with CORS
Get image
Origin: http://www.example.com

<canvas>
</canvas>

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

Context: www.example.com www.websec.be

var img = new Image();


img.crossOrigin = "Anonymous"; //or "use-credentials
img.src = "http://www.websec.be/topsecret.png";

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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

#Devoxx #SecureSPA @PhilippeDeRyck


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!


#Devoxx #SecureSPA @PhilippeDeRyck
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

#Devoxx #SecureSPA @PhilippeDeRyck


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 users browser

CSP does not relieve you from mitigating XSS!


#Devoxx #SecureSPA @PhilippeDeRyck
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!


#Devoxx #SecureSPA @PhilippeDeRyck
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!

#Devoxx #SecureSPA @PhilippeDeRyck


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

Starting from November 19, 1 session each week

https://goo.gl/17hVTa

#Devoxx #SecureSPA @PhilippeDeRyck

S-ar putea să vă placă și