Upload
philippe-de-ryck
View
452
Download
4
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
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
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
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
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• 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
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
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
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"><img src=”http://some-shop.com/coolcar.png"
onerror=“alert(1)” /></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
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
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
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!