Download - Web Integration Patterns in the Era of HTML5

Transcript
Page 1: Web Integration Patterns in the Era of HTML5

Web Integration Patterns In the Era of HTML5

@johnwilander atOWASP BeNeLux 2012, Leuven, BelgiumGeekMeet Stockholm, Sweden, 2013

Page 2: Web Integration Patterns in the Era of HTML5

@johnwilander

Part IThe Historyof Web Integration

Page 3: Web Integration Patterns in the Era of HTML5

@johnwilander

Remember when we had pages?

Page 4: Web Integration Patterns in the Era of HTML5

@johnwilander

… maybe a persistent menu system?

Menu

Page 5: Web Integration Patterns in the Era of HTML5

@johnwilander

Menu

… and 3rd party popus?

Page 6: Web Integration Patterns in the Era of HTML5

@johnwilander

You still see such sites.

Page 7: Web Integration Patterns in the Era of HTML5

@johnwilander

But product owners don’t want them

anymore.

Page 8: Web Integration Patterns in the Era of HTML5

@johnwilander

Menu

So we started loading things when we needed them, using Ajax and DOM manipulation with JavaScript.

Page 9: Web Integration Patterns in the Era of HTML5

@johnwilander

Menu

Page 10: Web Integration Patterns in the Era of HTML5

@johnwilander

Menu

The problem was that Ajax was only allowed to the same origin as the page. Ergo, no third party integration.

Page 11: Web Integration Patterns in the Era of HTML5

@johnwilander

But the same-origin policy didn’t apply to all

web elements.

Page 12: Web Integration Patterns in the Era of HTML5

@johnwilander

<form action="http://3rdparty.net"></form>

<img src="http://3rdparty.net">

<script src="http://3rdparty.net"></script>

Page 13: Web Integration Patterns in the Era of HTML5

@johnwilander

<form action="http://3rdparty.net"></form>

<img src="http://3rdparty.net">

<script src="http://3rdparty.net"></script>

The form tag actually had cross-domain intentions and is used for integration with e.g. payment providers such as PayPal. You post a purchase form from maindomain.com and enter the checkout process at paypal.com.

Page 14: Web Integration Patterns in the Era of HTML5

@johnwilander

<form action="http://3rdparty.net"></form>

<img src="http://3rdparty.net">

<script src="http://3rdparty.net"></script>The img tag has been used heavily for cross-origin web tracking such as Google Analytics and Omniture.

Page 15: Web Integration Patterns in the Era of HTML5

@johnwilander

Image srchttp://www.google-analytics.com/__utm.gif?utmwv=5.3.8&utms=1&utmn=1854976096&utmhn=appsandsecurity.blogspot.se&utmcs=UTF-8&utmsr=1920x1200&utmvp=1268x500&utmsc=24-bit&utmul=sv&utmje=1&utmfl=11.5%20r31&utmdt=Apps%20and%20Security&utmhid=2120874108&utmr=-&utmp=%2F&utmac=UA-6984098-5&utmcc=__utma%3D60396157.1187947367.1352854596.1353863861.1353882126.6%3B%2B__utmz%3D60396157.1352933082.2.2.utmcsr%3Dgoogle%7Cutmccn%3D(organic)%7Cutmcmd%3Dorganic%7Cutmctr%3D(not%2520provided)%3B&utmu=q~

Query string parametersutmwv:5.3.8utms:1utmn:1854976096utmhn:appsandsecurity.blogspot.seutmcs:UTF-8utmsr:1920x1200utmvp:1268x500utmsc:24-bitutmul:svutmje:1utmfl:11.5 r31utmdt:Apps and Securityutmhid:2120874108utmr:-utmp:/utmac:UA-6984098-5utmcc:__utma=60396157.1187947367.1352854596.1353863861.1353882126.6;+__utmz=60396157.1352933082.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided);utmu:q~

Page 16: Web Integration Patterns in the Era of HTML5

@johnwilander

<form action="http://3rdparty.net"></form>

<img src="http://3rdparty.net">

<script src="http://3rdparty.net"></script>

The script tag became the workhorse for Ajax-like cross-origin sharing by means of the popular jsonp hack.

Page 17: Web Integration Patterns in the Era of HTML5

@johnwilander

Jsonp =Json with Padding

(should be ”Json, Please?”)

Page 18: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

</html>

Jsonp

Page 19: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

</html>

Inserts a new script element toretrieve data cross-domain

Jsonp

Page 20: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

<script src=”3rdparty.net/getData?cb=receive”></script>

</html>

Inserts a new script element toretrieve data cross-domain.

Jsonp

Page 21: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

<script src=”3rdparty.net/getData?cb=receive”></script>

</html>

Jsonp

Page 22: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

<script src=”3rdparty.net/getData?cb=receive”></script>

</html>

The third party domain ”pads” theresponse data with a call to the given callback function.

Jsonp

Page 23: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

<script src=”3rdparty.net/getData?cb=receive”></script>

</html>

receive({ ”prop1”: ”data”, ”prop2”: ”data”, ”prop3”: ”data”, ”prop4”: ”data”});

Jsonp

Page 24: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

</html>

{ ”prop1”: ”data”, ”prop2”: ”data”, ”prop3”: ”data”, ”prop4”: ”data”}

receive({ ”prop1”: ”data”, ”prop2”: ”data”, ”prop3”: ”data”, ”prop4”: ”data”});

Jsonp

Page 25: Web Integration Patterns in the Era of HTML5

@johnwilander

maindomain.com

3rdparty.net

<html>

<script> function receive(data) { var json = JSON.parse(data); ... };</script>

</html>

{ ”prop1”: ”data”, ”prop2”: ”data”, ”prop3”: ”data”, ”prop4”: ”data”}

receive({ ”prop1”: ”data”, ”prop2”: ”data”, ”prop3”: ”data”, ”prop4”: ”data”});

Jsonp

Data is fetched asynchronously, cross-domain.

Page 30: Web Integration Patterns in the Era of HTML5

@johnwilander

jQuery's ”crossDomain” Ajax is Jsonp

http://api.jquery.com/jQuery.ajax/

Page 31: Web Integration Patterns in the Era of HTML5

@johnwilander

Jsonp Is Inherently Dangerous

Benign server response: givenCallback({”prop1”: ”val1”});

Compromised server response: givenCallback({”prop1”: ”val1”}); evilCode(); moreEvilCode();

Page 32: Web Integration Patterns in the Era of HTML5

@johnwilander

Jsonp Is Inherently Dangerous

Benign server response: givenCallback({”prop1”: ”val1”});

Compromised server response: givenCallback({”prop1”: ”val1”}); evilCode(); moreEvilCode();

Note that a client doing jsonp calls has nochance to see/filter the reponse before it’s executed.The client has to blindly trust whatever code is returned.

Page 33: Web Integration Patterns in the Era of HTML5

@johnwilander

Jsonp and CSRF

Also, all relevant cookies for the Jsonp service are sent with the request opening up for non-blind CSRF. Non-blind as in the attacker getting the response in full.

Page 34: Web Integration Patterns in the Era of HTML5

@johnwilander

Demo jsonp

Page 35: Web Integration Patterns in the Era of HTML5

@johnwilander

Then there is the document.domain

trick.

Page 36: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

other.1-liner.org

Page 37: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

other.1-liner.org

Page 38: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

other.1-liner.org

Page 39: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

other.1-liner.org

Same-origin policyprohibits evendifferent subdomainsfrom interacting

Page 40: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

document.domain = ”1-liner.org”;

other.1-liner.org

document.domain = ”1-liner.org”;

Page 41: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

document.domain = ”1-liner.org”;

other.1-liner.org

document.domain = ”1-liner.org”;

Page 42: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

document.domain = ”1-liner.org”;

main.1-liner.org

But …

Page 43: Web Integration Patterns in the Era of HTML5

@johnwilander

Demo document.domain

Page 44: Web Integration Patterns in the Era of HTML5

@johnwilander

In summary, web integration used to be

all-or-nothing.

Page 45: Web Integration Patterns in the Era of HTML5

@johnwilander

Part 2New Integration Technologies

Page 46: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS var req = new XMLHttpRequest(); req.open(method, crossDomainUrl); req.send();

Sandboxed iframes <iframe src="http://3rdparty.net" sandbox="allow-scripts"></iframe>

postMessage API otherFrameOrWindow.postMessage( ’{"action": "purchase", "item": 34443}’, "http://3rdparty.net");

Page 47: Web Integration Patterns in the Era of HTML5

@johnwilander

Cross-Origin Resource Sharing, CORS

10+Partial supportin IE8 and IE9

15+

5.1+

22+

12+

3.2+

2.1+

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

Page 48: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS is basically cross-origin Ajax

Page 49: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS

• The server has to authorize requests in response headers: Access-Control-Allow-Origin allowed.domain.com

• HTTP GET and POST are like normal Ajax

• Other HTTP methods or GET and POST with custom headers require a preflight

• The client has to explicitly send cookies: xhr.withCredentials = true;

Page 50: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Unaware Server

Let's see what 2012 looks like if we are still running a …

Page 51: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Unaware ServerClient Server

Ajax GET

Looks likea normal GET.Has a reliable Origin header.

If no authori-zation logic is present it just responds.

If no allowing CORS header client gets no response.

No cookies

Page 52: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Unaware ServerClient Server

Ajax POST

Looks likea normal POST.Has a reliable Origin header.

If no authori-zation logic is present it just responds.

If no allowing CORS header client gets no response.

No cookies

Page 53: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Unaware ServerClient Server

Looks like a normal request.Has a reliable Origin header.

If no authori-zation logic is present it just responds.

If no allowing CORS header client gets no response.

CookiesAjax + withCredentials = true;

Page 54: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Unaware ServerClient Server

OPTIONS request with Access-Control-Request-Method: GET/POST

If no authori-zation logic is present it just responds.

If no allowing CORS header client never sends request.

Preflight requestAjax + setRequestHeader('X-Requested-With','XMLHttpRequest');

Page 55: Web Integration Patterns in the Era of HTML5

@johnwilander

CORS-Aware ServerClient Server

Looks like a normal request.Has a reliable Origin header.

Authorizes the calling origin and includesAccess-Control-Allow-Origin

If allowing CORS header client gets the response.

CookiesAjax + withCredentials = true;

Page 56: Web Integration Patterns in the Era of HTML5

@johnwilander

This means …

• Attackers can now do CSRF without img tags or form posting.

• Servers that don’t check origin headers have no clue it’s a cross-origin Ajax call.

• Custom headers including the Ajax header are effectively dead in the CORS case since developers want to avoid preflights.

Page 57: Web Integration Patterns in the Era of HTML5

@johnwilander

DEMO CORS

Page 58: Web Integration Patterns in the Era of HTML5

@johnwilander

Sandboxed iframes

10+Rumored to

not be there yet

17+

5.1+

22+

Nosupport

4.2+

2.2+

http://caniuse.com/#feat=iframe-sandbox

Page 59: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

<iframe src=”main.1-liner.org” sandbox>

<script></script><form></form>

</iframe>

Sandboxed iframe

Page 60: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

<iframe src=”main.1-liner.org” sandbox=”allow-same- origin”>

<script></script><form></form></iframe>

Sandboxed iframe

Page 61: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

<iframe src=”main.1-liner.org” sandbox=”allow-same- origin allow-scripts”>

<script></script><form></form></iframe>

Sandboxed iframe

Page 62: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

<iframe src=”main.1-liner.org” sandbox=”allow-same- origin allow-scripts allow-forms”><script></script><form></form></iframe>

Sandboxed iframe

Page 63: Web Integration Patterns in the Era of HTML5

@johnwilander

DEMO Sandboxed iframe

Page 64: Web Integration Patterns in the Era of HTML5

@johnwilander

Partialsupport inIE8 – IE10

15+

5.1+

22+

12+

3.2+

2.1+

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

postMessage

Page 65: Web Integration Patterns in the Era of HTML5

@johnwilander

postMessage

• Allows string-based communication between frames and windows

• You need a handle to the target to be able to send a message

• The recipient whitelists origins from which it accepts messages

Page 66: Web Integration Patterns in the Era of HTML5

@johnwilander

postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");

// Receiving messages requires an event listenerreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { return; } console.log(event.data);}window.addEventListener("message", receiveMessage, false);

Page 67: Web Integration Patterns in the Era of HTML5

@johnwilander

postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");

// Receiving messages requires an event listenerreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { return; } console.log(event.data);}window.addEventListener("message", receiveMessage, false);

Handle to receiving

window or frame

Target origin makes sure the window

or frame hasn’t been redirected

Page 68: Web Integration Patterns in the Era of HTML5

@johnwilander

postMessage// Sending messages requires a handle to the receiving endvar popup = window.open("http://other.1-liner.org", "_blank");popup.postMessage("Luke, I am your father.", "http://other.1-liner.org");

// Receiving messages requires an event listenerreceiveMessage = function(event) { if (event.origin !== "http://other.1-liner.org") { return; } console.log(event.data);}window.addEventListener("message", receiveMessage, false);

Receiving event listener has to check the message

comes from a trusted origin

Page 69: Web Integration Patterns in the Era of HTML5

@johnwilander

DEMO postMessage

Page 70: Web Integration Patterns in the Era of HTML5

@johnwilander

Part 3How To Use the Technologies Securely

Page 71: Web Integration Patterns in the Era of HTML5

@johnwilander

First stop using …

• Jsonp

• document.location trick

• img tag trick

Page 72: Web Integration Patterns in the Era of HTML5

@johnwilander

Implement CORS Server-Side Now

Client ServerAlways check origin header.

Authorize the calling origin based on a whitelist.

If allowing CORS header client gets the response.

CookiesAjax + withCredentials = true;

Page 73: Web Integration Patterns in the Era of HTML5

@johnwilander

HTML

HTML

HTML

CSS

CSS

JavaScript

JavaScript

CSS

JavaScript

Bad Web Architecture

Page 74: Web Integration Patterns in the Era of HTML5

@johnwilander

HTML

CSS on file

JavaScript on file

Import

CSS

JavaScript

Good Web Architecture

Page 75: Web Integration Patterns in the Era of HTML5

@johnwilander

A good separation of content, code, and style

allows for CSP.

Page 76: Web Integration Patterns in the Era of HTML5

@johnwilander

But our legacy applications are a mess.

Page 77: Web Integration Patterns in the Era of HTML5

@johnwilander

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

Placing legacy web and third party webin iframes allowsthe new code to runwith CSP.

iframe

Page 78: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

Then set the sandbox directive without allow-same-origin to leverage the same-origin policy for protection fromvulnerabilities in legacy or third party code.

Sandboxed iframe

main.1-liner.org… or …3rdparty.net

Page 79: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

A backwards compatible alternative is to move legacy code to anothersubdomain to leverage the same-origin policy for protection fromvulnerabilities in legacy code.

iframe

legacy.1-liner.org

Page 80: Web Integration Patterns in the Era of HTML5

@johnwilander

new.1-liner.org

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

But beware. Legacy code typically doesn’t relocate gracefully. So you might have to keep its domain and get a new subdomain for your new code.

iframe

main.1-liner.org

Page 81: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

Use the postMessage API for communicating between your iframes and your main window.

Sandboxed iframe

main.1-liner.org… or …3rdparty.net

postMessage

Page 82: Web Integration Patterns in the Era of HTML5

@johnwilander

main.1-liner.org

CORS from/to 3rdparty.net

HTML

CSS

HTMLCSS

JavaScript

JavaScript

JavaScript

HTML CSS

Sandboxed iframe

main.1-liner.org… or …3rdparty.net

postMessage

Finally, use CORS when retrieving content from third parties and make sure to encode it right before injecting it to the DOM.

Page 83: Web Integration Patterns in the Era of HTML5

@johnwilander

Thanks!